Most likely it is because you have not responded to the fake ajax request. The ember-testing
package counts the pending ajax requests made by jQuery (see pendingAjaxRequests here). If this stays at 1, the ember-testing wait()
helper never resolves.
The ember-testing
package increments this counter via ajaxStart and ajaxStop filters.
To clarify what's happening here: When you use the click()
helper, this sends a click message to the element, and then defers to the wait()
helper (a promise). The same applies for other helpers such as fillIn()
, keyEvent()
etc. You can see from the comments in the source for wait()
that it will not progress on with the rest of your specs:
// 1. If the router is loading
// 2. *If there are pending Ajax requests
// 3. If there are scheduled timers or we are inside of a run loop
The fix:
Unfortunately, if you never make it to the then
block of your test, you cannot fake a response via requests[0].respond(...)
.
Instead, I've solved this by using sinon's fake server:
var server;
beforeEach(function () {
server = sinon.fakeServer.create();
server.autoRespond = true;
server.autoRespondAfter = 1; // ms
App.reset();
});
afterEach(function () {
server.restore();
});
it("should make ajax call", function() {
// set up the fake response
server.responses[0].response = [200, { "Content-Type": "application/json" }, '{ "todos": [] }'];
visit('/')
.click($("a.test-link:first"))
.then(function() {
// should make it to here now
});
});
This pattern works fine when you are expecting a single, or a deterministic order of ajax requests going into your fake server. If you expect lots of requests (with different paths), you can use server.respondWith([regex], ...)
to match certain urls to specific responses.
Another thing to note is that it's generally good practice to put the success part of your ajax call into an Ember.run:
jQuery.ajax({
url: "/todo/items",
success: function(data) {
Ember.run(function () {
//callback(null, data);
})
}
});