Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 314
Leon Adler Avatar asked Jul 01 '16 08:07

Leon Adler


People also ask

How do you unit test a component that depends on parameters from ActivatedRoute?

The specific id is procured through a parameter that is passed via routing, specifically through the ActivatedRoute class. The constructor is as follows: constructor(private _router:Router, private _curRoute:ActivatedRoute, private _session:Session) {} ngOnInit() { this. _curRoute.

What are routing tests?

A route consistency test takes two different route advertisements to the same destination as input and outputs true if the routes are consistent and outputs false otherwise. Consistency is abstractly defined as follows: If both route announcements are valid then the output is true.


1 Answers

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
}
like image 127
Colum Avatar answered Sep 18 '22 19:09

Colum