Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 unit testing components with routerLink

I am trying to test my component with angular 2 final, but I get an error because the component uses the routerLink directive. I get the following error:

Can't bind to 'routerLink' since it isn't a known property of 'a'.

This is the relevant code of the ListComponent template

<a    *ngFor="let item of data.list"    class="box"   routerLink="/settings/{{collectionName}}/edit/{{item._id}}"> 

And here is my test.

import { TestBed } from '@angular/core/testing';  import { ListComponent } from './list.component'; import { defaultData, collectionName } from '../../config'; import { initialState } from '../../reducers/reducer';   const data = {   sort: initialState.sort,   list: [defaultData, defaultData], };  describe(`${collectionName} ListComponent`, () => {   let fixture;   beforeEach(() => {     TestBed.configureTestingModule({       declarations: [         ListComponent,       ],     }).compileComponents(); // compile template and css;     fixture = TestBed.createComponent(ListComponent);     fixture.componentInstance.data = data;     fixture.detectChanges();   });    it('should render 2 items in list', () => {     const el = fixture.debugElement.nativeElement;     expect(el.querySelectorAll('.box').length).toBe(3);   }); }); 

I looked at several answers to similar questions but could not find a solution that worked for me.

like image 346
select Avatar asked Sep 19 '16 16:09

select


1 Answers

You need to configure all the routing. For testing, rather than using the RouterModule, you can use the RouterTestingModule from @angular/router/testing, where you can set up some mock routes. You will also need to import the CommonModule from @angular/common for your *ngFor. Below is a complete passing test

import { Component } from '@angular/core'; import { Router } from '@angular/router'; import { By } from '@angular/platform-browser'; import { Location, CommonModule } from '@angular/common'; import { RouterTestingModule } from '@angular/router/testing'; import { TestBed, inject, async } from '@angular/core/testing';  @Component({   template: `     <a routerLink="/settings/{{collName}}/edit/{{item._id}}">link</a>     <router-outlet></router-outlet>   ` }) class TestComponent {   collName = 'testing';   item = {     _id: 1   }; }  @Component({   template: '' }) class DummyComponent { }  describe('component: TestComponent', function () {   beforeEach(() => {     TestBed.configureTestingModule({       imports: [         CommonModule,         RouterTestingModule.withRoutes([          { path: 'settings/:collection/edit/:item', component: DummyComponent }         ])       ],       declarations: [ TestComponent, DummyComponent ]     });   });    it('should go to url',     async(inject([Router, Location], (router: Router, location: Location) => {      let fixture = TestBed.createComponent(TestComponent);     fixture.detectChanges();      fixture.debugElement.query(By.css('a')).nativeElement.click();     fixture.whenStable().then(() => {       expect(location.path()).toEqual('/settings/testing/edit/1');       console.log('after expect');     });   }))); }); 

UPDATE

Another option, if you just want to test that the routes are rendered correctly, without trying to navigate...

You an just import the RouterTestingModule without configuring any routes

imports: [ RouterTestingModule ] 

then just check that the link is rendered with the correct URL path, e.g.

let href = fixture.debugElement.query(By.css('a')).nativeElement     .getAttribute('href'); expect(href).toEqual('/settings/testing/edit/1'); 
like image 109
Paul Samsotha Avatar answered Oct 02 '22 17:10

Paul Samsotha