When I run this unit test:
it('can click profile link in template', () => { const landingPageLinkDe = linkDes[0]; const profileLinkDe = linkDes[1]; const aboutLinkDe = linkDes[2]; const findLinkDe = linkDes[3]; const addLinkDe = linkDes[4]; const registerLinkDe = linkDes[5]; const landingPageLinkFull = links[0]; const profileLinkFull = links[1]; const aboutLinkFull = links[2]; const findLinkFull = links[3]; const addLinkFull = links[4]; const registerLinkFull = links[5]; navFixture.detectChanges(); expect(profileLinkFull.navigatedTo) .toBeNull('link should not have navigated yet'); profileLinkDe.triggerEventHandler('click', { button: 0 }); landingPageLinkDe.triggerEventHandler('click', { button: 0 }); aboutLinkDe.triggerEventHandler('click', { button: 0 }); registerLinkDe.triggerEventHandler('click', { button: 0 }); findLinkDe.triggerEventHandler('click', { button: 0 }); addLinkDe.triggerEventHandler('click', { button: 0 }); navFixture.detectChanges(); expect(landingPageLinkFull.navigatedTo).toBe('/'); expect(profileLinkFull.navigatedTo).toBe('/profile'); expect(aboutLinkFull.navigatedTo).toBe('/about'); expect(findLinkFull.navigatedTo).toBe('/find'); expect(addLinkFull.navigatedTo).toBe('/add'); expect(registerLinkFull.navigatedTo).toBe('/register'); });
I get this error:
zone.js:388 Unhandled Promise rejection: Cannot match any routes. URL Segment: 'add' ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Cannot match any routes. URL Segment: 'add'(…) Error: Cannot match any routes. URL Segment: 'add'
The test still passes but it would be interesting to know why I'm getting the error. I don't get the error when I use the application as a user would. I've researched the error and it's usually due to not providing a default path in the routes, however I have done that.
Am I doing something wrong to cause this error?
navbar.component.spec.ts
import 'zone.js/dist/long-stack-trace-zone.js'; import 'zone.js/dist/async-test.js'; import 'zone.js/dist/fake-async-test.js'; import 'zone.js/dist/sync-test.js'; import 'zone.js/dist/proxy.js'; import 'zone.js/dist/jasmine-patch.js'; import { ComponentFixture, TestBed, async, fakeAsync } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; import { By } from '@angular/platform-browser'; import { DebugElement, Component, ViewChild, Pipe, PipeTransform, CUSTOM_ELEMENTS_SCHEMA, NO_ERRORS_SCHEMA } from '@angular/core'; import { DatePipe } from '@angular/common'; import { Router, RouterOutlet, RouterModule } from '@angular/router'; import { RouterTestingModule } from '@angular/router/testing'; import { NavbarComponent } from './navbar.component'; import { RouterLinkStubDirective } from '../../router-stubs'; import { click } from '../../test/utilities.spec'; describe('NavbarComponent', () => { let navComponent: NavbarComponent; let navFixture: ComponentFixture<NavbarComponent>; let linkDes: any; let links: any; let landingPageLink: any; let profileLink: any; let aboutLink: any; let findLink: any; let addLink: any; let registerLink: any; beforeAll(() => { TestBed.resetTestEnvironment(); TestBed.initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting()); }); beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ NavbarComponent, RouterLinkStubDirective ], imports: [RouterTestingModule], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); })); beforeEach(() => { navFixture = TestBed.createComponent(NavbarComponent); navComponent = navFixture.componentInstance; navFixture.detectChanges(); linkDes = navFixture.debugElement .queryAll(By.directive(RouterLinkStubDirective)); links = linkDes .map((de: any) => de.injector .get(RouterLinkStubDirective) as RouterLinkStubDirective); landingPageLink = links[0].linkParams; profileLink = links[1].linkParams; aboutLink = links[2].linkParams; findLink = links[3].linkParams; addLink = links[4].linkParams; registerLink = links[5].linkParams; }); it('can get RouterLinks from template', () => { expect(links.length).toBe(6, 'should have 6 links'); expect(landingPageLink[0]) .toEqual('/', '1st link should go to landing page'); expect(profileLink[0]) .toEqual('/profile', '2nd link should go to profile'); expect(aboutLink[0]) .toEqual('/about', '3rd link should go to about'); expect(findLink[0]) .toEqual('/find', '4th link should go to find'); expect(addLink[0]) .toEqual('/add', '5th link should go to add'); expect(registerLink[0]) .toEqual('/register', '6th link should go to register'); }); it('can click profile link in template', () => { const landingPageLinkDe = linkDes[0]; const profileLinkDe = linkDes[1]; const aboutLinkDe = linkDes[2]; const findLinkDe = linkDes[3]; const addLinkDe = linkDes[4]; const registerLinkDe = linkDes[5]; const landingPageLinkFull = links[0]; const profileLinkFull = links[1]; const aboutLinkFull = links[2]; const findLinkFull = links[3]; const addLinkFull = links[4]; const registerLinkFull = links[5]; navFixture.detectChanges(); expect(profileLinkFull.navigatedTo) .toBeNull('link should not have navigated yet'); profileLinkDe.triggerEventHandler('click', { button: 0 }); landingPageLinkDe.triggerEventHandler('click', { button: 0 }); aboutLinkDe.triggerEventHandler('click', { button: 0 }); registerLinkDe.triggerEventHandler('click', { button: 0 }); findLinkDe.triggerEventHandler('click', { button: 0 }); addLinkDe.triggerEventHandler('click', { button: 0 }); navFixture.detectChanges(); expect(landingPageLinkFull.navigatedTo).toBe('/'); expect(profileLinkFull.navigatedTo).toBe('/profile'); expect(aboutLinkFull.navigatedTo).toBe('/about'); expect(findLinkFull.navigatedTo).toBe('/find'); expect(addLinkFull.navigatedTo).toBe('/add'); expect(registerLinkFull.navigatedTo).toBe('/register'); }); });
stub for test:
import 'zone.js/dist/long-stack-trace-zone.js'; import 'zone.js/dist/async-test.js'; import 'zone.js/dist/fake-async-test.js'; import 'zone.js/dist/sync-test.js'; import 'zone.js/dist/proxy.js'; import 'zone.js/dist/jasmine-patch.js'; import { EventEmitter, Output, trigger, state, style, transition, animate, Directive, Input } from '@angular/core'; import { ComponentFixture, TestBed, async, fakeAsync } from '@angular/core/testing'; import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; import { By } from '@angular/platform-browser'; import { DebugElement, Component, ViewChild, Pipe, PipeTransform } from '@angular/core'; import { DatePipe } from '@angular/common'; import { Router } from '@angular/router'; import { NavbarComponent } from './shared/subcomponents/navbar.component'; import { AppComponent } from './app.component'; import { click } from './test/utilities.spec'; import { FormsModule, ReactiveFormsModule } from '@angular/forms' @Directive({ selector: '[routerLink]', host: { '(click)': 'onClick()' } }) export class RouterLinkStubDirective { @Input('routerLink') linkParams: any; navigatedTo: any = null; onClick() { this.navigatedTo = this.linkParams[0]; } }
app.routes.ts:
import { Routes } from '@angular/router'; import { LandingPageComponent } from './landing-page/landing-page.component'; import { FindPageComponent } from './find-page/find-page.component'; import { AddPageComponent } from './add-page/add-page.component'; import { RegisterPageComponent } from './register-page/register-page.component'; import { AboutPageComponent } from './about-page/about-page.component'; import { ProfilePageComponent } from './profile-page/profile-page.component'; export const routerConfig: Routes = [ { path: '', component: LandingPageComponent }, { path: '', redirectTo: '', pathMatch: 'full' }, { path: 'find', component: FindPageComponent }, { path: 'add', component: AddPageComponent }, { path: 'register', component: RegisterPageComponent }, { path: 'about', component: AboutPageComponent }, { path: 'profile', component: ProfilePageComponent } ];
navbar.component.html:
<nav class="navbar navbar-dark navbar-fixed-top text-uppercase"> <div class="container-fluid"> <button class="navbar-toggler hidden-md-up pull-xs-right" type="button" data-toggle="collapse" data-target="#nav-content"> ☰ </button> <a class="navbar-brand" [routerLink]="['/']" routerLinkActive="active">vepo</a> <div class="collapse navbar-toggleable-sm" id="nav-content"> <ul class="nav navbar-nav pull-xs-right"> <li class="nav-item"> <a class="nav-link" [routerLink]="['/profile']" routerLinkActive="active">profile</a> </li> <li class="nav-item"> <a class="nav-link" [routerLink]="['/about']" routerLinkActive="active">about</a> </li> <li class="nav-item"> <a class="nav-link" [routerLink]="['/find']" routerLinkActive="active">find</a> </li> <li class="nav-item"> <a class="nav-link" [routerLink]="['/add']" routerLinkActive="active">add</a> </li> <li class="nav-item"> <button type="button" class="as-text nav-link text-uppercase" (click)="openModal()"> login </button> </li> <li class="nav-item"> <a class="nav-link signup" [routerLink]="['/register']" routerLinkActive="active">sign up free</a> </li> </ul> </div> </div> </nav> <login #modal></login> <router-outlet></router-outlet>
I had the same problem recently. It was caused by a call to router.navigate
inside the ngOnInit
method of a component. The test was trying to create the component, but inside ngOnInit
it was attempting to navigate away from the component (because certain conditions were not met).
In my case, I am importing the RouterTestingModule
as part of TestBed.configureTestingModule
. So to fix this I simply registered a route with RouterTestingModule
. For example, suppose your navigation call looks like router.navigate(['example'])
and it resolves to ExampleComponent
. You can set up the test as follows:
RouterTestingModule.withRoutes([ { path: 'example', component: ExampleComponent} ])
Doing the above allowed my tests to run without issuing Cannot match any routes
errors.
For what it's worth, I think a better way would be to stub the router and just confirm that appropriate calls to navigate
are made.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With