10

I am trying to test routing in the following very simple component:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'side-bar',
  templateUrl: `
    <div class="sidebar hidden-sm-down">
        <div class="sidebar-block" >
            <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}">Home</a>
        </div>

        <div class="sidebar-block">
            <a routerLink="/edit" routerLinkActive="active">Edit</a>
        </div>
    </div>
  `,
  styleUrls: ['./side-bar.component.scss']
})
export class SideBarComponent implements OnInit {

  ngOnInit() { }

}

I currently have:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';

import { RouterLinkStubDirective } from '../../../testing/router-stubs';
import { SideBarComponent } from './side-bar.component';

describe('SideBarComponent', () => {
    let component: SideBarComponent;
    let fixture: ComponentFixture<SideBarComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [ RouterTestingModule ],
            declarations: [SideBarComponent, RouterLinkStubDirective ]
        })
        .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(SideBarComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    });

    it('can be instantiated', () => {
        expect(component).not.toBeNull();
    });

    it('can link to main pages', () => {
        var linkElements = fixture.debugElement.queryAll(By.directive(RouterLinkStubDirective));
        var links = linkElements.map(element => element.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);

        expect(links.length).toBe(2, 'should have 3 links');
        expect(links[0].linkParams).toBe('/', '1st link should go to Home');
        expect(links[1].linkParams).toBe('/edit', '2nd link should go to Edit');
    });

    it('can show the active link', () => {
        var activeLinks = fixture.debugElement.queryAll(By.css('.active')).map(element => element.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);
        expect(activeLinks.length).toBe(0, 'should only have 1 active link');
        expect(activeLinks[0].linkParams).toBe('/', 'active link should be for Home');
    });
});

The first couple of tests are working and follow the example laid out in the official angular testing documentation with the only departure being that I had to import the RouterTestingModule so that the routerLinkActiveOptions wouldn't cause an error to be thrown.

The goal in the final test is to assert that routerLinkActive is working as expected. I'm not expecting the current implementation to work, ideally I would be able to set the current route and then check that the active link is correctly set in a way similar to the last test.

The documentation around the RouterTestingModule is non-existent so it may be possible to do it using this. If anyone knows a way to achieve this, help would be greatly appreciated.

Ben Smith
  • 101
  • 1
  • 4

1 Answers1

10

To do test like this you need to use a router, there is an example stackblitz!

But there is some issue with invoking router navigation inside test. link to issue!

import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { DebugElement, Component } from '@angular/core';

import { RouterLinkStubDirective } from '../testing/router-link-directive-stub';
import { SideBarComponent } from './side-bar.component';
import { Routes, Router } from '@angular/router';

@Component({
  template: ``
})
export class HomeComponent { }

@Component({
  template: ``
})
export class EditComponent { }

const routes: Routes = [
  {
    path: '', component: HomeComponent,
  },
  {
    path: 'edit', component: EditComponent
  }
];

describe('SideBarComponent', () => {
  let component: SideBarComponent;
  let fixture: ComponentFixture<SideBarComponent>;
  let router: Router;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes(routes)],
      declarations: [SideBarComponent, RouterLinkStubDirective, 
HomeComponent, EditComponent]
     })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(SideBarComponent);
    component = fixture.componentInstance;
    router = TestBed.get(Router);
    fixture.detectChanges();
  });

  it('can be instantiated', () => {
    expect(component).not.toBeNull();
  });

  it('can link to main pages', () => {
    var linkElements = 
fixture.debugElement.queryAll(By.directive(RouterLinkStubDirective));
    var links = linkElements.map(element => element.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);

    expect(links.length).toBe(2, 'should have 3 links');
    expect(links[0].linkParams).toBe('/', '1st link should go to Home');
    expect(links[1].linkParams).toBe('/edit', '2nd link should go to Edit');
  });

  it('can show the active link', fakeAsync(() => {
    router.navigate(['edit']);
    tick();
    var activeLinks = fixture.debugElement.queryAll(By.css('.active')).map(element => element.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);
    expect(activeLinks.length).toBe(1, 'should only have 1 active link');
    expect(activeLinks[0].linkParams).toBe('/edit', 'active link should be for Home');

    router.navigate(['']);

    tick();
    var activeLinks = fixture.debugElement.queryAll(By.css('.active')).map(element => element.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);
    expect(activeLinks.length).toBe(1, 'should only have 1 active link');
    expect(activeLinks[0].linkParams).toBe('/', 'active link should be for Home');
  }));
})
Roman Lonsky
  • 101
  • 1
  • 6
  • this answer should be accepted. It works fine in Angular7. https://i.imgur.com/tIZ0vVI.png – Raj Apr 01 '19 at 10:38