Firstly, I don't believe it is a duplicate as the SO questions and answers describe testing of promise handling in angular1 and are resolved by calling $timeout.flush()
or $rootScope.$apply()
so no applicable to this Angular2 case.
My question is how I can test logic of Angular2 component which is being executed after resolving a promise. (Preferably in Jasmine).
To illustrated it I modified quick start examples from Angular2 docs. Simple component lists existing heros and allows registration of a new one. The heros list and registration is done by a service, which returns responses as Promises (with list of heros, or newly registered hero object).
Now once a new hero is registered (and Promise resolved) I want the component to make the hero selected and retrieve again the hero list:
...
register(heroName:string) {
this.postRegistration(this._heroService.registerHero(heroName));
}
//this extra method helps testing without stubing of the service
postRegistration(heroPromise:Promise<Hero>) {
heroPromise.then( hero => {
//I want to test that the two actions below took place
this.selectedHero = hero;
this.getHeroes(); })
}
getHeroes() {
this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}
I split registration in two methods, so it can be tested without stubing of the service
Using Jasmine asynchronous testing with done()
I can easily test the service behaviour, ie. that it returns correct promises.
But how to test, that the component invoked getHeros
to refresh its list or correctly set the selected hero.
I managed to test for setting the variable with the spec:
it("postRegistration sets selectedHero as registered one",done =>{
let promise = service.registerHero("Bosek"); //Promise.resolve(hero);
component.postRegistration(promise);
promise.then( hero => {
expect(component.selectedHero).toBe(hero);
expect(component.heroes.indexOf(hero)).toBeGreaterThan(0);
done();
})
})
I "hooked" my assertion to the same promise which was passed to the component.
My first question: Was I lucky or is it guarantee that if I subscribe to the same promise and call from its 'then' clause jasmine done() it will wait till my other "subscribers" (in that case component) process that promise and subsequent ones.
Secondly, Is there a way to force all Promises to be synchronous during testing, that would solved the whole problem.
I found mock-promise project https://github.com/charleshansen/mock-promises which allows "firing" the promises but it has been dead for 2 years.
This problem should be common enough to have a standard answer.
I am asking in the context of Angular2 and Jasmine, but, I am interest in simple 'unit test' approach as well, for example the current test is fully independent of Angular framework. And typescript please as I don't work with JS normally.
The whole code (it is a simple clone of Angular2 Hero quick start example) is under: https://github.com/tzielins/angular-start-project