samedi 28 février 2015

Testing: how to assert between two sequential promises/run.laters? How to skip `run.later` waiting in tests?

Here's a simple component:



App.FooBarComponent = Ember.Component.extend({
tagName: "button",
status: "Ready",
revertStatusPeriodMs: 2000,

click: function() {
this.set('status', 'Pending');

// A fake ajax
this.run()
.then( function() {
this.updateStatus('Finished');
}.bind(this))
.catch( function() {
this.updateStatus('Error');
}.bind(this));
},

run: function() {
return new Ember.RSVP.Promise( function(resolve) {
Ember.run.later( function() {
resolve();
}, 500);
});
},

updateStatus: function(statusText) {
this.set('status', statusText);

var periodMs = this.get('revertStatusPeriodMs') || 1000;

Ember.run.later( function() {
this.set('status', 'Ready');
}.bind(this), 500);
}
});


It does a simple thing: when clicked, it displays some text. Later replaces the text with another one. Even later, it reverts the text to the initial one.


The code works fine. My problem is that i'm unable to write a test for it.



test('clicking the button should set the label', function(assert) {
expect(4);

visit('/');

assert.equal( find('button').text().trim(), 'Ready', 'Should initially be "Ready"');

andThen(function() {
click('button');
assert.equal( find('button').text().trim(), 'Pending', 'Should "Pending" right after click');
});

// This one fires too late!
andThen(function() {
assert.equal( find('button').text().trim(), 'Finished', 'Should become "Finished" after promise fulfills');
});

andThen(function() {
assert.equal( find('button').text().trim(), 'Ready', 'Should eventually return to the "Ready" state');
});
});


I have two problems:




  1. I'm unable to test the Finished state. It seems that andThen waits for all promises and run.laters to finish, while i want to test an intermediate state. How do i run an assertion between two sequential promises/run.laters?




  2. Times can be long, and tests can take forever to complete. I generally don't mind refactoring the code for better testability, but i refuse to adjust times in the app based on the environment (e. g. 2000 for dev/prod, 0 for test). Instead, i would like to use a timer mock or some other solution.


    I've tried Sinon and failed: when i mock the timer, andThen never returns. Neither of these solutions helped me.




JSBin: http://ift.tt/188EBwh (Sinon is included)





Aucun commentaire:

Enregistrer un commentaire