The way to test router componet needs a little bit setup, first we need to create a "router-stubs.ts". This file is a helper file.
// export for convenience. export { ActivatedRoute, Router, RouterLink, RouterOutlet} from '@angular/router'; import { Component, Directive, Injectable, Input } from '@angular/core'; import { NavigationExtras } from '@angular/router'; @Directive({ selector: '[routerLink]', host: { '(click)': 'onClick()' } }) export class RouterLinkStubDirective { @Input('routerLink') linkParams: any; navigatedTo: any = null; onClick() { this.navigatedTo = this.linkParams; } } @Component({selector: 'router-outlet', template: ''}) export class RouterOutletStubComponent { } @Injectable() export class RouterStub { navigate(commands: any[], extras?: NavigationExtras) { } } // Only implements params and part of snapshot.paramMap import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { convertToParamMap, ParamMap } from '@angular/router'; @Injectable() export class ActivatedRouteStub { // ActivatedRoute.paramMap is Observable private subject = new BehaviorSubject(convertToParamMap(this.testParamMap)); paramMap = this.subject.asObservable(); // Test parameters private _testParamMap: ParamMap; get testParamMap() { return this._testParamMap; } set testParamMap(params: {}) { this._testParamMap = convertToParamMap(params); this.subject.next(this._testParamMap); } // ActivatedRoute.snapshot.paramMap get snapshot() { return { paramMap: this.testParamMap }; } } /* Copyright 2017 Google Inc. All Rights Reserved. Use of this source code is governed by an MIT-style license that can be found in the LICENSE file at http://angular.io/license */
The component we want to test:
<app-banner></app-banner> <app-welcome></app-welcome> <nav> <a routerLink="/dashboard">Dashboard</a> <a routerLink="/heroes">Heroes</a> <a routerLink="/about">About</a> </nav> <router-outlet></router-outlet>
import { Component } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html' }) export class AppComponent { }
Testing setup:
beforeEach( async(() => { TestBed.configureTestingModule({ declarations: [ AppComponent, BannerComponent, WelcomeStubComponent, RouterLinkStubDirective, RouterOutletStubComponent ] }) .compileComponents() .then(() => { fixture = TestBed.createComponent(AppComponent); comp = fixture.componentInstance; }); }));
We need to declare 'RouterLinkStubDirective' & 'RouterOutletStubComponent' which we created in stub helper file.
beforeEach(() => { // trigger initial data binding fixture.detectChanges(); // find DebugElements with an attached RouterLinkStubDirective linkDes = fixture.debugElement .queryAll(By.directive(RouterLinkStubDirective)); // get the attached link directive instances using the DebugElement injectors links = linkDes .map(de => de.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective); });
Some tests:
it('can get RouterLinks from template', () => { expect(links.length).toBe(3, 'should have 3 links'); expect(links[0].linkParams).toBe('/dashboard', '1st link should go to Dashboard'); expect(links[1].linkParams).toBe('/heroes', '1st link should go to Heroes'); }); it('can click Heroes link in template', () => { const heroesLinkDe = linkDes[1]; const heroesLink = links[1]; expect(heroesLink.navigatedTo).toBeNull('link should not have navigated yet'); heroesLinkDe.triggerEventHandler('click', null); fixture.detectChanges(); expect(heroesLink.navigatedTo).toBe('/heroes'); });