When I provide params to my TestComponent
the test bed blows up if the html contains a [routerLink]
testbed setup
I figured out the problem/solution.
We're seeing Cannot read property '_lastPathIndex' of undefined
because at one point the Angular router expects a _lastPathIndex
property on a snapshot
object.
The relevant part of the Angular source code looks like this:
if (route.snapshot._lastPathIndex === -1) {
return new Position(route.snapshot._urlSegment, true, 0);
}
If snapshot
is undefined, it will of course raise the error we're seeing.
The problem can be solved by making snapshot
not-undefined.
Here's how I did it. My code is a little different from the OP's.
I have a class called MockActivatedRoute
that looks like this.
export class MockActivatedRoute {
parent: any;
params: any;
constructor(options) {
this.parent = options.parent;
this.params = options.params;
}
}
Here's how I use it in my test.
let mockActivatedRoute = new MockActivatedRoute({
parent: new MockActivatedRoute({
params: Observable.of({ id: '1' })
})
});
To make the error go away I just added a snapshot
property to MockActivatedRoute
.
export class MockActivatedRoute {
parent: any;
params: any;
snapshot = {};
constructor(options) {
this.parent = options.parent;
this.params = options.params;
}
}
You can add snapshot property inside your providers array.
providers: [{ provide: ActivatedRoute, useValue: { snapshot: {} } }]
This works with no errors and no hack
import {
TestBed,
async
} from '@angular/core/testing';
import {
HttpModule,
BaseRequestOptions,
Http
} from '@angular/http';
import { APP_BASE_HREF } from '@angular/common';
import {
RouterModule,
ActivatedRoute
} from '@angular/router';
import { MockBackend } from '@angular/http/testing';
import { Observable } from 'rxjs';
import { Component } from '@angular/core';
fdescribe( 'AppComponent', () => {
beforeEach( () => {
TestBed.configureTestingModule( {
imports : [
HttpModule,
RouterModule.forRoot(
[
{
path : '',
component : TestComponent
}
] )
],
declarations : [ TestComponent ],
providers : [
BaseRequestOptions,
MockBackend,
{
provide : Http,
useFactory : function ( backend : MockBackend, defaultOptions : BaseRequestOptions ) {
return new Http( backend, defaultOptions );
},
deps : [ MockBackend, BaseRequestOptions ]
},
{
provide : APP_BASE_HREF,
useValue : '/'
},
{
provide : ActivatedRoute,
useValue : {
params : Observable.of( { versionId : '1' } ),
parent : {
params : Observable.of( { uniqueId : '1234' } )
}
}
}
]
} );
TestBed.compileComponents();
} );
it( 'should create the app', async( () => {
let fixture = TestBed.createComponent( TestComponent );
let app = fixture.debugElement.componentInstance;
expect( app ).toBeTruthy();
} ) );
} );
@Component( {
selector : 'app-root',
template : `
<a class="button" [routerLink]="['/']">Back</a>
<router-outlet></router-outlet>
`,
} )
export class TestComponent {
}