I'm trying to get chai-as-promised
to work with $q
promises with karma unit tests.
svc.test = function(foo){
if (!foo){
// return Promise.reject(new Error('foo is required'));
return $q.reject(new Error('foo is required'));
} else {
// get data via ajax here
return $q.resolve({});
}
};
it.only('should error on no foo', function(){
var resolvedValue = MyServices.test();
$rootScope.$apply();
return resolvedValue.should.eventually.be.rejectedWith(TypeError, 'foo is required');
});
The unit test just times out. I am not sure what I'm doing wrong here to get the promise to resolve properly. It seems to be an issue with using $q
-- when I use native Promise.reject()
it works fine.
I filed a ticket here, but nobody seems to be responding: https://github.com/domenic/chai-as-promised/issues/150
The way
chai-as-promised
expects to modify promise assertions istransferPromiseness
method.For Angular 1.3+ support,
$q
promises can be duck-typed by$$state
property, so native promises won't be affected:chaiAsPromised
chains each asserted promise withthen
. Even if the promise is settled, the rest of the chain still requires the digest to be triggered manually with$rootScope.$digest()
.As long as the spec contains no asynchronous code, it becomes synchronous, no promise is required to be returned:
And is equal to mandatory
$rootScope.$digest()
after each set ofeventually
assertions/expectation whentransferPromiseness
wasn't set:You need to change the order of execution in your tests. Asynchronous tasks with chai-as-promised need to happen before the expectation.
You need to initiate the call to the asynchronous task before flushing the queue of asynchronous tasks.
Also, don't use
$rootScope.$digest
. That may have other side effects that are not desirable within your test(s).$timeout.flush
is what you're looking for.https://docs.angularjs.org/api/ngMock/service/$timeout
To get your specific test(s) working:
tl;dr
Given the comments posted:
Fair enough. I think the answer is misleading, given that there is no extra setup necessary to get chai-as-promised working with Angular without having to deal with the
done
callback. Fwiw, I'll go ahead and try to revoke said downvote and be ethical about it.$rootScope.$digest
is effectively the same as$rootScope.$apply
(and$scope.$apply
for that matter). source$timeout.flush
will flush non-$timeout
based functions just as well. It is not exclusive to$timeout
based functions.Plunker to showcase how it just works™: plunker