Sunday, July 10, 2016

How can I unit test components that depend on the RC3 router?

Leave a Comment

I am trying to get unit tests that worked with RC1 working with the "new new" router. How can I achieve this on 3.0.0-alpha.8?

My dependencies:

"@angular/common": "2.0.0-rc.3", "@angular/compiler": "2.0.0-rc.3", "@angular/core": "2.0.0-rc.3", "@angular/forms": "0.2.0", "@angular/platform-browser": "2.0.0-rc.3", "@angular/platform-browser-dynamic": "2.0.0-rc.3", "@angular/router": "3.0.0-beta.2", 

The component that I would like to test that uses the routerLink directive:

import {ROUTER_DIRECTIVES} from '@angular/router'; @Component({     selector: 'app-topmenu',     template: require('./app-topmenu.tpl.html'),     directives: [ROUTER_DIRECTIVES] }) export class TopMenu { 
<nav class="app-top-menu">     <a *ngFor="let link of links" [routerLink]="link.route">{{link.text}}</a> </nav> 

Previously, with rc1, I was using something like this to unit-test my component:

import {Location} from '@angular/common'; import {SpyLocation} from '@angular/common/testing'; import {Router, RouteRegistry, ROUTER_DIRECTIVES, ROUTER_PRIMARY_COMPONENT} from '@angular/router-deprecated'; import {RootRouter} from '@angular/router-deprecated/src/router';  describe('Router link capabilities', () => {     beforeEachProviders(() => [         RouteRegistry,         { provide: Location, useClass: SpyLocation },         { provide: ROUTER_PRIMARY_COMPONENT, useValue: TestComponent },         { provide: Router, useClass: RootRouter }     ]);      it('creates routerLinks with the expected URLs', fakeAsync(         inject([TestComponentBuilder, Location], (tcb: TestComponentBuilder, spyLocation: SpyLocation) => {             tcb.overrideTemplate(TestComponent, `                 <app-top-menu [links]='[                     { text: "A", route: ["/TestA/TestB/TestC"] },                     { text: "B", route: ["/TestA", "TestB", "TestC"] }                 ]'></app-top-menu>                 <router-outlet></router-outlet>             `).createAsync(TestComponent)             .then((fixture: ComponentFixture<TestComponent>) => {                 fixture.detectChanges();                 spyLocation.simulateUrlPop('url-a/url-b/url-c');                 tick();                 fixture.detectChanges();                 let nativeLinks: HTMLAnchorElement[] = fixture.nativeElement.querySelectorAll('a');                  expect(nativeLinks.length).toBe(2);                 expect(nativeLinks[0].textContent).toBe('A');                 expect(nativeLinks[1].textContent).toBe('B');             });         })     )); }); 

When I try to just switch the routerLink imports from @angular/router-deprecated to importing ROUTER_DIRECTIVES from @angular/router, I receive an error:

ORIGINAL EXCEPTION: Platforms have to be created via `createPlatform`! 

All documentation I can find online about testing the "new new" router and the createPlatform message refers to providing ROUTER_FAKE_PROVIDERS which appears to be included in rc2, but gone with rc3:

import {ROUTER_FAKE_PROVIDERS} from '@angular/router/testing'; // ^ [ts] Cannot find module '@angular/router/testing'. 

Searching through the compiled .d.ts files in node_modules/@angular/router folder, I did also not find any references to testing/mocks/fakes.

Did anyone migrate to rc3 and get this working yet?

1 Answers

Answers 1

To test the RC3 (3.0.0-alpha.*) router, you need to do a couple of things differently from how the router was set up in previous versions.

You need to define a RouterConfig like this:

import {provideRouter, RouterConfig} from '@angular/router';  export const APP_ROUTES : RouterConfig = [     {path: '', component: AppComponent},     // more paths ];  export const APP_ROUTE_PROVIDERS = [     provideRouter(APP_ROUTES)   ]; 

then in your test file

import {ActivatedRoute, RouterConfig, Router} from '@angular/router';  class MockRouter { createUrlTree() {} } class MockActivatedRoute { }  beforeEachProviders(() => [   provide(Router, { useClass: MockRouter }),   provide(ActivatedRoute, { useClass: MockActivatedRoute }), ]);  describe(){    // etc } 

Your router is now testable.

for RC4:

import {ActivatedRoute, RouterConfig, Router} from '@angular/router';  class MockRouter { createUrlTree() {} } class MockActivatedRoute { }    describe(){   beforeEach(() => [       addProviders([           provide(Router, { useClass: MockRouter }),           provide(ActivatedRoute, { useClass: MockActivatedRoute }),       ]);   ]);   //etc } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment