I am doing integration test of my ember application and one of my test is failing because of a promise resolves after my tests have ran. My promise wraps an animation event(bs collapse). Here is a part of the code that I am trying to test:
//in my component
/**
* Closes the component DOM with collapse animation
*
* @method 'animateClose'
* @return {Ember.RSVP.Promise} promise that gets resolved once the collapse animation is complete
*/
animateClose() {
let element = Ember.$(this.get('element'));
return new Ember.RSVP.Promise(function(resolve) {
element.on('hidden.bs.collapse', function() {
resolve();//never gets here!!!
});
element.collapse('hide');
});
},
actions: {
/**
* Invokes close action.
*
* @action 'close'
* */
close() {
let defer = Ember.RSVP.defer();
defer.promise.then(function() {
return this.animateClose().then(function() {
this.sendAction("close");
}.bind(this));
}.bind(this));
this.sendAction("confirmClose", defer);
}
}
As you can see, I am passing a defer object to the controller which will resolve it based on some criteria and if the defer object is resolved it does the collapse animation on the component and closes it. My test code looks like this:
test("should save and close", function(assert) {
click(".save-close-btn");//this invokes the close action in component
//wait();
andThen(function() {
//assert something
});
});
And when I debug it, I can see that my assertions are getting hit first and then later the promise returned from animateClose resolves causing my tests to fail. How can I resolve this issue? Thanks.
UPDATE: turns out that my component has not completely collapsed for some reason and hence the resolve within "animateClose" is not getting fired. Not sure why the collapse event doesn't complete and the dom is in "collapsing" state
TEMPORARY SOLUTION : for now I dumped the bootstrap collapse and used jquery slide animation instead and my tests are working fine. There must be something going on in the test environment that messes with bootstrap collapse animation/events.
The most common (anti-)pattern for this is to check if the component has been destroyed.
This is totally acceptable and works for just passing your tests. Note that the animation will not actually stop if your component is destroyed.
However, recently Alex Matchneer of the Ember core team has pioneered a better solution involving a cancelable promise. He has published an addon with the result: ember-concurrency. For more information, see the docs.