Closed lrdevries closed 8 years ago
Here you can find a jsfiddle example: http://jsfiddle.net/21af9puz/1/
The test fails because of the async call of the bootbox
I now use the cookbooks method for modals, that works: http://jsfiddle.net/21af9puz/14/ But this should be also a problem in other situations i think.
Here you go, try this: http://jsfiddle.net/21af9puz/17/ In your case, the test was failing because you weren't actually click the link, right?
However, if it was an async issue I'd recommend using Ember.Test.registerWaiter
.
Oh yea, I see you found the outlets. Yea, the real problem with your case was the click
doesn't look for thing outside of the ember app space. So if you're using a modal and not using an outlet, I'd recommend an andThen
.
what is the biggest difference between click an $('jquery').click(); ? if i wrap the click() in an andThen, it also doesn't work.
If you use RSVP promises (Ember has these as Ember.RSVP.Promise
), Ember can watch for them in testing mode and wait for the promises to resolve before other stuff happens.
I would try the following in your view code:
actions: {
askDelete: function(){
var self = this;
return new Ember.RSVP.Promise(function(resolve, reject){
self.$('td').slideUp('500').promise().then(function(){
self.get('controller').send('delete');
resolve();
});
});
}
}
I tried that, but it didn't work. Probably because an action can only return a boolean. And therefore the promise do not reach the test Op 27 aug. 2014 00:13 schreef "Stanley Stuart" notifications@github.com:
If you use RSVP promises (Ember has these as Ember.RSVP.Promise), Ember can watch for them in testing mode and wait for the promises to resolve before other stuff happens.
I would try the following in your view code:
actions: { askDelete: function(){ var self = this; return new Ember.RSVP.Promise(function(resolve, reject){ self.$('td').slideUp('500').promise().then(function(){ self.get('controller').send('delete'); resolve(); }); }); } }
— Reply to this email directly or view it on GitHub https://github.com/emberjs/ember.js/issues/5494#issuecomment-53501017.
Well, the RSVP scheduler is supposed to do this for us since 1.6, regardless of if you return or not. @lrdevries you can work around it by making the promise available somewhere globally like http://jsfiddle.net/x2jk4vf2/1/
Thank you for the solution, but I think the global isn't the most beautiful solution. I will take a look at the RSVP scheduler, how I can let it work through that. Op 27 aug. 2014 00:19 schreef "Stanley Stuart" notifications@github.com:
Well, the RSVP scheduler is supposed to do this for us since 1.6, regardless of if you return or not. @lrdevries https://github.com/lrdevries you can work around it by making the promise available somewhere globally like http://jsfiddle.net/x2jk4vf2/1/
— Reply to this email directly or view it on GitHub https://github.com/emberjs/ember.js/issues/5494#issuecomment-53501699.
I think there may be some semantics in here that may be worth improving: https://github.com/emberjs/ember.js/blob/master/packages/ember-runtime/lib/ext/rsvp.js#L26
Maybe we just want to always asyncStart() asyncEnd() if in Ember.testing? cc @stefanpenner
So i think the problem is that we are firing asyncEnd any time a promise is resolved during async...?
No. I believe the problem is the click
. His modal is outside of the application template. So the testing click handler doesn't seem to find it. If you look at this: http://jsfiddle.net/21af9puz/17/ You'll see it works without any promises or async helpers.
@lrdevries IIRC the click
helper is design to only click things within your "application". Meaning anything that is a descendant of your application template. Using the andThen(function() { $('.btn-primary').click(); })
enabled it to search the entire document.
@workmanw ahh i see. i noticed that click($('.btn-primary')); also worked.
This lets the test wait for the click. But if you want to wait for the whole modal window, you have to wait for the promise.
@lrdevries Just as a heads up, you cannot depend on click($('.btn-primary'))
to always work. Each of the helpers in your test is executed without blocking (obviously, it's JS of course). So if any action you take might create an async operation (promises, deferred, ajax, animation, etc). The test will continue executing the helper calls (even if waiting for an AJAX) and the internal test suite will queue up each subsequent helper action.
In the case of click($('.btn-primary'))
, if a prior async operation had existed, $('.btn-primary')
could have resolved before a prior operation had been completed (and potentially before '.btn-primary' was in the DOM). That's why you always wrap anything that's not an async helper with and andThen
.
Make sense?
Yes it definitely make sense.
Sorry to wake this back up, but is there a best practice for this? We are seeing the same issue when launching a foundation modal from an action:
actions: {
openModal: function () {
$("#some_modal_id").foundation("reveal", "open");
}
}
I'm running into this issue as well @benkiefer
If i remember correctly i noticed a difference between click($(..)); and $(..).click();. And if i'm right i solved it with this.
$(..).click() works occasionally for me. I ended up solving it with the answer to this question:
http://stackoverflow.com/questions/25512168/async-call-in-ember-testing
My code looks like this:
click("#modal-launch-btn");
andThen(function () {
waitFor(function () {
assert.ok(!find("#myModal").is(":hidden"));
});
});
runAndWaitFor looks like this:
function waitFor(callback, timeout) {
timeout = timeout || 500;
stop();
Ember.run.later(function(){
callback();
start();
}, timeout);
}
Which basically just means I pause the test and take a nap. Not ideal, but at least I can test drive my modals now.
Thanks @benkiefer
From the last few comments this issue looks to be resolved.
In my application i use bootbox (http://bootboxjs.com/) for confirming to delete some models. In my test i click on the button with an {{ action }}, in this action i open a bootbox. In the text i click the OK button on the bootbox.
But the andThen method does not wait for the bootbox to dissapear. The check if a model is removed is therefore always false. I tried to return an promise but the andThen helpen also doesn't wait for promisses.
Is there a way to let the test wait untill the promise of the bootbox is resolved, or the callback of the bootbox is finished?
Extra information: My template is:
My View is:
My controller:
My test:
But the latest ok is called before the save action in the controller is triggered, and therefore alwasy false.