I'm unit testing a component, in particular the rendered form. I'm approaching this pretty much as described in the Ember Guides.
In particular, the component has three computed properties which show different classes on the rendered elements depending on the backing model. I'm tweaking the properties in Ember.run()
blocks and then looking at the rendered component again.
What's interesting here is that the computed properties seem not to be re-computing even through I'm touching the attribute they observe. Later tests which don't test rendering - just the return from the component - do pass.
Here's my test code:
moduleForComponent('wizard-tab', "Component - WizardTab", {
setup: function () {
this.tab = this.subject({ step: 2, stepCompleted: 1, tab: tabs.all()[1] });
}
});
test('#render', function () {
let tab = this.tab;
ok(this.$().find('span.wizard-tab-detail').length, "Active tab has a detail span"); // Passes
// Note that both of the additional states observe stepCompleted
// so I need to touch that to get them to recalculate
Ember.run( function () {
tab.set('stepCompleted', 2);
tab.set('tab', WizardTab.all()[4]);
});
ok(this.$().find('span.wizard-tab-icon-disabled').length, "Future tabs have a disabled class"); // Fails
Ember.run( function () {
tab.set('stepCompleted', 3);
tab.set('tab', WizardTab.all()[1]);
});
ok(this.$().find('span.wizard-tab-icon-done').length, "Inactive tabs have a done class"); // Fails
});
The first assertion passes, the next two fail. Using console.log
statements I've validated that the set()
s are working, but the property calculated from them is returning the wrong result.
Here's one of the computed property definitions:
disabled: function() {
return this.get('tab.stepNumber') > (this.get('stepCompleted') + 1);
}.property('stepCompleted')
(I literally get false
for 5 > 2
when I put in console.log
checks on that comparison.) Is there something I'm missing that would prevent that from updating when I check subsequent renders of the component?
This is ember CLI 0.2.0, Ember 1.10.0 and ember-cli-qunit 0.3.8.
ETA: Probably relevant: this test passes on Ember 1.8 and ember-cli-qunit 0.3.1. It's the update to Ember CLI 0.2.0 and accompanying Ember and ember-cli-qunit updates which cause the failure.
(ETA: note from kiwiupover's comment below that this section below isn't relevant to the problem; the guides may not show the best current way to do this.)
Note that the guides use a similar pattern:
test('changing colors', function() {
// this.subject() is available because we used moduleForComponent
var component = this.subject();
// we wrap this with Ember.run because it is an async function
Ember.run(function() {
component.set('name','red');
});
// first call to $() renders the component.
equal(this.$().attr('style'), 'color: red;');
// another async function, so we need to wrap it with Ember.run
Ember.run(function() {
component.set('name', 'green');
});
equal(this.$().attr('style'), 'color: green;');
});
I tried wrapping the second and third assertions in andThen()
but that raised errors - andThen()
was undefined.
I got this working by starting a new branch off development (our default branch) and re-running the update. Here are the differences between my original pass and what worked:
ember-resolver
, loader.js
, ember-cli-app-version
and ember-cli-dependency-checker
had all moved up. I don't know if any of those mattered, but they did change.Ember.run()
block for each test that used different attribute values from the setup component.Here's what the three tests looked like when they passed:
moduleForComponent('wizard-tab', "Component - WizardTab", {
setup: function () {
this.tab = this.subject({ step: 2, stepCompleted: 1, tab: WizardTab.all()[1] });
}
});
test('Rendered active tabs have a detail span', function () {
let tab = this.tab;
ok(this.$().find('span.wizard-tab-detail').length, "Active tab has a detail span");
});
test('Rendered future tabs have a disabled class', function () {
let tab = this.tab;
Ember.run( function () {
tab.set('step', 2);
tab.set('stepCompleted', 2);
tab.set('tab', WizardTab.all()[4]);
});
ok(this.$().find('span.wizard-tab-icon-disabled').length, "Future tabs have a disabled class");
});
test('Rendered inactive tabs have a done class', function () {
let tab = this.tab;
Ember.run( function () {
tab.set('step', 2);
tab.set('stepCompleted', 3);
tab.set('tab', WizardTab.all()[1]);
});
ok(this.$().find('span.wizard-tab-icon-done').length, "Inactive tabs have a done class");
});
I believe that last change - moving from one test with some Ember.run()
blocks to three - is what really did it. I used some {{log value}}
lines in the template to look at which values were being sent to the template, and it was using the subject from the setup
block all three times until I added the Ember.run()
blocks.