This is an Ember component that will need this
at some point:
export default Component.extend({
filteredSubs: computed.filter('model.subs', function() {
// this will always return true in development http://localhost:4200/dummy
// but will always return false in test because 'this' becomes undefined
return this;
})
});
Dummy
has a one-to-many relationship to Sub
:
export default Model.extend({
subs: hasMany('sub')
});
export default Model.extend({
dummy: belongsTo('dummy')
});
This test fails but shouldn't:
test('it renders', function(assert) {
let dummy = server.create('dummy');
server.create('sub', { dummy });
this.set('dummy', dummy);
this.render(hbs`{{show-dummy model=dummy}}`);
assert.equal(this.$().text().trim(), 'Hi! There are 1 sub-dummies');
});
not ok 13 Chrome 63.0 - Integration | Component | show dummy: it renders
actual: Hi! There are 0 sub-dummies
expected: Hi! There are 1 sub-dummies
Your problem comes from an unfortune sequense of falsy assumptions.
The first assumption of you is that this
inside a Ember.computed.filter
should be the corresponding object. I'm not 100% sure this is documented behaviour, and personally wouldnt rely on it. If you need full access to this
I would go with a simple Ember.computed
.
However your primary mistake is in your test. And this also explains why you only have this problem in testing. Your directly using a mirage model as model
for your component:
let dummy = server.create('dummy');
server.create('sub', {
dummy
});
this.set('dummy', dummy);
this.render(hbs`{{show-dummy model=dummy}}`);
Here you assume that the result of server.create
, a mirage model, is in some ways similar to a ember-data
model. It is not! In fact, a mirage model is not even an ember
object! So you can't use .get
or .set
on it, or anything you defined on your model, and definitly should not use it ever as an model für component testing. Instead you should use mirage as data-source for your ember-data
models.
The question why this
is undefined if your model is a mirage model leads to this line in ember-cli-mirage
:
filter(f) {
let filteredModels = this.models.filter(f);
return new Collection(this.modelName, filteredModels);
}
where the this
-context gets lost. Basically mirage is overriding the .filter
function on their custom array-like structure, and doesnt ensure to keep the this
-context.