I have a component in angular 2 which responds to changes in the route parameters (the component doesn't reload from scratch because we're not moving out of the main route. Here's the component code:
export class MyComponent{
ngOnInit() {
this._routeInfo.params.forEach((params: Params) => {
if (params['area']){
this._pageToShow =params['area'];
}
});
}
}
This works a treat and _pageToShow
is set appropriate on navigation.
I'm trying to test the behaviour on a change to the route (so a second trigger of the observable but it's refusing to work for me.) Here's my attempt:
it('sets PageToShow to new area if params.area is changed', fakeAsync(() => {
let routes : Params[] = [{ 'area': "Terry" }];
TestBed.overrideComponent(MyComponent, {
set: {
providers: [{ provide: ActivatedRoute,
useValue: { 'params': Observable.from(routes)}}]
}
});
let fixture = TestBed.createComponent(MyComponent);
let comp = fixture.componentInstance;
let route: ActivatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
comp.ngOnInit();
expect(comp.PageToShow).toBe("Terry");
routes.splice(2,0,{ 'area': "Billy" });
fixture.detectChanges();
expect(comp.PageToShow).toBe("Billy");
}));
But this throws a TypeError: Cannot read property 'subscribe' of undefined
exception when I run it. If I run it without the fixture.detectChanges();
line it fails as the second expectation fails.
I prefer to get route params and data from ActivatedRouteSnapshot like this
this.route.snapshot.params['type']
If you use the same way, you can test it like this
1) In your test providers
2) in your test spec
Firstly, you should use a
Subject
instead of anObservable
. The observable only gets subscribed to once. So it will only emit the first set of params. With aSubject
, you can keep emitting items, and the single subscription will keep getting them.Then in your test just emit new values with
params.next(newValue)
.Secondly, you need to make sure to call
tick()
. This is howfakeAsync
works. You control asynchronous task resolution. Since the observable as asychrounous, the moment we sent the event, it will not get to the subscriber synchronously. So we need to force synchronous behavior withtick()
Here is a complete test (
Subject
is imported from'rxjs/Subject'
)