Hey Team,
I’m having a bunch of trouble with the learning curve on ember-cli testing.
Basically, it seems like Ember (ember-cli?) is super committed to isolated Unit tests - that is, tests with minimal dependencies. Definitely sounds like a recipe for speed and correct tests
Perhaps it’s because I’m used to Rails, but I’m getting the feeling that the tests are over-isolated - that is, there could/should be some pragmatic additions that wouldn’t harm speed or nicely-split up testing, but would make things Just Work™ a little more. I’m happy to be proved wrong of course!
As a concrete example, pretend you’re testing what I’m guessing is a fairly standard Route:
import Ember from 'ember';
export default Ember.Route.extend({
model: function() {
return this.store.find("tutorial");
},
actions: {
createTutorial: function() {
var tut = this.store.createRecord("tutorial");
tut.save().then( () => {
this.transitionTo('whatever-route', tut);
});
return tut;
}
}
});
So you’ve got an action, and then you want to test it (I’ll omit most of the test boilerplate)
test('I can create a tutorial', function() {
var route = this.subject();
this.subject.get('actions').createTutorial();
// assert something maybe...
}
Except that doesn’t work (My Ember-fu is not strong enough to figure out why actions is undefined, no matter what way I try to access it - if someone could enlighten me I’d be very appreciative!)
The docs suggest separating concerns to define an _createTutorial method, and call that from within actions… which I’m really not sure I buy (how often are they going to be legitimately separate concerns? My example must be pretty common, and I can’t think of another reason for something else in my Route to be creating a Tutorial… when am I going to want to do something from a User action but do it a different way internally?) but anyway, I’ll do that…
test('I can create a tutorial', function() {
var route = this.subject();
this.subject._createTutorial();
// assertions?
}
Which results in:
TypeError: Cannot read property 'createRecord' of undefined
Oh. For some reason the route doesn’t have a DS.Store injected like my controllers in action do
A quick google reveals an awesome presentation that reveals that moduleForModel
adds this.store()
(slide #23). But the Route test is just using moduleFor
, presumably in the interests of isolation. There are also a lot of people using the dependency injection (i.e looking up store:main on App.__container__
or similar, which seems hacky to me…?)
I understand the argument, but just having an in-memory (Fixture?) store feels like it would smooth out the learning curve there a bit - given that (again, as I understand it) the role of a Route is to hook user actions into your data store.
I apologise profusely if I happen to have just messed something up, please correct me
tl;dr
- How do I get access to a DS.Store instance in a Unit test for a Route?
- Would there be an interest in having a moduleForRoute or some similar kind of “base” set of assumptions per test type that makes a simple test a bit more frictionless?
Thanks,
Nik