Don't mix-and-match Angular and native Promises
Well this was fun to debug. Not. So, it seems that in 1.4 (as opposed to 1.2) Angular Promises are special, and don't play well with native browser Promises. In particular, Angular promises don't resolve until a digest cycle, which means that while this test will pass: it('should resolve', function (done) { var resolved = false; $timeout(function () { resolved = true; }); .then(function () { assert.isTrue(resolved); }) .then(done, done); $timeout.flush(); // <- this triggers a digest cycle }); This one will not -- Mocha will time it out, because the digest cycle triggered by `$timeout.flush()` occurs before the fulfillment handlers (with the assertions and the call to `done`) are registered: it('should resolve', function (done) { var resolved = false; var wait = $timeout(function () { resolved = true; }); $timeout.flush(); wait.then(function () { assert.isTrue(resolved); }) .then(done, done); }); If that were the whole story, I would be merely mildly displeased. But it's not... The return value of a call to `.then(onFulfilled, onRejected)` is a promise of the return value of the `onFulfilled` callback, which is what makes Promises chainable. If `onFulfilled` returns a promise, then that is (or should be) the promise returned by `.then(...)`. Unfortunately, if we actually do this: it('should resolve', function (done) { $timeout(function () { return Promise.resolve('abc'); }) .then(function (val) { assert.equal(val, 'abc'); }) .then(done, done); $timeout.flush(); // <- this triggers a digest cycle }); Then again, Mocha will time out on this test. This is probably because the returned Promise resolves on runtime `nextTick`, which is *after* the call to `$timeout.flush()`, which means it's after the relevant part of the digest cycle which processes the fulfillment handlers for the Angular-style promise. ARGH, Angular. Argh.
Showing
Please register or sign in to comment