Angular 2.0.0 - Mock File Uploader - unit-testing

I am using ng2-file-upload. How do I mock its FileUploader class in unit testing?
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
#Component({
selector: 'my-component',
template: '...',
providers: [ MyService ]
})
export class MyComponent {
public uploader: FileUploader = new FileUploader({url: '/my-app/api/upload',
authToken: 'token'});
constructor() {
this.uploader.onCompleteItem = (item:any, response: any, headers: any) => {
console.log('how to test here');
}
}
I am having a hard time mocking it in my spec. Please help.

I was going to reply to your comment, but I think the following may help to answer your original question on how to mock the FileUploader class taken from their unit test from the file file-drop.directive.spec.ts:
import { Component } from '#angular/core';
import { inject, ComponentFixture, TestBed } from '#angular/core/testing';
import { FileUploader } from './file-uploader.class';
import { FileUploadModule } from './file-upload.module';
#Component({
selector: 'container',
template: `<input type="file" ng2FileSelect [uploader]="uploader" />`
})
export class ContainerComponent {
public uploader:FileUploader = new FileUploader({url: 'localhost:3000'});
}
describe('Directive: FileSelectDirective', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FileUploadModule],
declarations: [ContainerComponent],
providers: [ContainerComponent]
});
});
it('should be fine', inject([ContainerComponent], (fixture:ComponentFixture<ContainerComponent>) => {
expect(fixture).not.toBeNull();
}));
});
Where import { FileUploader } from './file-uploader.class'; is how you import the FileUploader into your test, ContainerComponent is imported into the test itself.
Further to this, I have created a dummy file to test with on my component, but I am still writing it!
it('should accept a file for upload', () => {
var modifiedDate = new Date();
var file = new File([3555], 'test-file.jpg', {lastModified : modifiedDate, type: 'image/jpeg'});
FileUploadComponent.upload(file);
});
To test if this works, I have a metadata model that I expect to be populated upon the file being selected. I can therefore make two assertions, that both the upload input box will have a file and that the metadata object will be populated.
In the case of ng2-file-upload, I beleive the file list will be populated allowing you to check that the test file has been imported into that.
Good luck!

Related

Testing a component with dependencies using karma & jasmine

I'm new to angular 2 and I have some problems testing my code. I use the jasmine testing framework and the karma test runner to test my app.
I have a component (called GroupDetailsComponent) that I want to test. This component uses two services (GroupService & TagelerServie, both have CRUD methods to talk to an API) and some pipes in the html file. My component looks like this:
import 'rxjs/add/operator/switchMap';
import { Component, Input, OnInit } from '#angular/core';
import { Tageler } from '../../tagelers/tageler';
import { TagelerService } from '../../tagelers/tageler.service';
import { Params, ActivatedRoute } from '#angular/router';
import { GroupService} from "../group.service";
import { Group } from '../group';
#Component({
selector: 'app-group-details',
templateUrl: 'group-details.component.html',
styleUrls: ['group-details.component.css'],
})
export class GroupDetailsComponent implements OnInit {
#Input()
tageler: Tageler;
tagelers: Tageler[];
group: Group;
constructor(
private route: ActivatedRoute,
private groupService: GroupService,
private tagelerService: TagelerService) {
}
ngOnInit() {
console.log("Init Details");
this.route.params
.switchMap((params: Params) => this.groupService.getGroup(params['id']))
.subscribe(group => this.group = group);
this.tagelerService
.getTagelers()
.then((tagelers: Tageler[]) => {
// some code
}
return tageler;
});
});
}
}
And the test file looks like this:
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { GroupDetailsComponent } from './group-details.component';
import { FilterTagelerByGroupPipe } from '../../pipes/filterTagelerByGroup.pipe';
import { SameDateTagelerPipe } from '../../pipes/sameDateTageler.pipe';
import { CurrentTagelerPipe } from '../../pipes/currentTageler.pipe';
import { NextTagelerPipe } from '../../pipes/nextTageler.pipe';
import { RouterTestingModule } from '#angular/router/testing';
import { GroupService } from '../group.service';
import { TagelerService } from '../../tagelers/tageler.service';
describe('GroupDetailsComponent', () => {
let component: GroupDetailsComponent;
let fixture: ComponentFixture<GroupDetailsComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
GroupDetailsComponent,
FilterTagelerByGroupPipe,
SameDateTagelerPipe,
CurrentTagelerPipe,
NextTagelerPipe, ],
imports: [ RouterTestingModule ],
providers: [{provide: GroupService}, {provide: TagelerService}],
})
fixture = TestBed.createComponent(GroupDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
class MockGroupService {
getGroups(): Array<Group> {
let toReturn: Array<Group> = [];
toReturn.push(new Group('Trupp', 'Gruppe 1'));
return toReturn;
};
}
it('should create component', () => {
expect(component).toBeDefined();
});
});
I read the angular 2 documentation about testing and a lot of blogs, but I still don't really understand how to test a component that uses services and pipes. When I start the test runner, the test 'should create component' fails and I get the message that my component is not defined (but I don't understand why). I also don't understand how I have to inject the services and pipes. How do I mock them the right way?
I hope that someone can give me helpful advice!
Ramona
You can use spyOn to fake the call in jasmine.
spyOn(yourService, 'method').and.returnValue($q.resolve(yourState));

How can I test the rendering of an element using the date pipe in Angular 2?

I can't seem to test a component that uses a Date pipe in Angular 2 (using Karma through PhantomJS). When I try, I get ORIGINAL EXCEPTION: ReferenceError: Can't find variable: Intl
Here's my entire spec file:
import { provide, PLATFORM_PIPES } from '#angular/core';
import { DatePipe } from '#angular/common';
import { addProviders, async, inject } from '#angular/core/testing';
import { Post, PostComponent, PostHtmlComponent } from './';
import { usingComponentFixture } from '../../test-helpers';
describe('Component: Post', () => {
beforeEach(() => {
provide(PLATFORM_PIPES, {useValue: DatePipe, multi: true });
addProviders([PostComponent, PostHtmlComponent, ]);
});
it('should render an h1 tag with text matching the post title',
usingComponentFixture(PostComponent, fixture => {
let component = <PostComponent>fixture.componentInstance;
let element = fixture.nativeElement;
component.post = <Post>{ title: 'Hello', publishedOn: new Date('8/5/2016') };
fixture.detectChanges();
expect(element.querySelector('.blog-post-header h1').innerText).toBe('Hello');
})
);
});
And this is the component template:
<div class="col-lg-8 col-md-7 col-sm-6">
<h1>{{post.title}}</h1>
<p class="lead">{{post.publishedOn | date:'fullDate'}}</p>
</div>
I was able to resolve this issue. Here's what I had to do:
npm install karma-intl-shim --save-dev
Add 'intl-shim' to the frameworks collection in karma.conf.js
Add the following to karma-test-shim.js (this is referenced in the files collection of karma.conf.js)
require('karma-intl-shim');
require('./en-us.js'); // copied from https://github.com/andyearnshaw/Intl.js/blob/master/locale-data/json/en-US.json
Intl.__addLocaleData(enUsLocaleData);
Instead of mocking the DatePipe, you can use the transform method of DatePipe in typescript which is equivalent to the | operator in the HTML file
import {DatePipe} from '#angular/common';
let pipe = new DatePipe('en');
expect(page.myDate.nativeElement.innerHTML).toBe(pipe.transform(model.date, 'dd/MM/yyyy');
For tests I mock date pipe:
#Pipe({
name: 'date',
pure: false // required to update the value when the promise is resolved
})
export class MockedDatePipe implements PipeTransform {
name: string = 'date';
transform(query: string, ...args: any[]): any {
return query;
}
}
Then when I configure testing module I inject it into declaration:
TestBed.configureTestingModule( {
providers: [
SelectionDispatcher,
{ provide: MyService, useClass: MockedMyServiceService }
],
declarations: [ MyComponent, MockedTranslatePipe, MockedDatePipe ]
});
That worked for me:
import { DatePipe, registerLocaleData } from '#angular/common';
import localeDe from '#angular/common/locales/de';
registerLocaleData(localeDe);
//..
describe('My Test', () => {
let pipe = new DatePipe('de-DE');
it('My Test-Case', () => {
expect(page.myDate.nativeElement.innerHTML).toBe(pipe.transform(model.date);
});
});
You must set the right locale.
That is a snippet from a Cypress-Test.
that's what worked for me:
import {DatePipe} from "#angular/common";
...
TestBed.configureTestingModule({
...
providers: [DatePipe]
...
});
Expanding on other answers on here I was using the DatePipe in my component to produce a payload. I had the following setup.
Return the transform method on DatePipe in the mock, matching parameters used by the component i.e. ('YY'). Otherwise we will just get undefined as the value when testing.
.spec file
import { DatePipe } from '#angular/common';
.....
const mockDatePipe = {
transform: jest.fn((val) => new DatePipe('en').transform(val, 'YY')),
};
.....
beforeEach(() => {
component = new TestComponent(
(mockDatePipe as unknown) as DatePipe,
.....
);
});
it('should return correct payload', () => {
expect(component.getPayload(new Date('2022-02-02')).toEqual(
{
purchaseYear: '22',
}
}
.ts file
public getPayload(date: new Date(), .....){
return {
purchaseYear: this.datePipe.transform(date, 'YY')
};
);

Angular2 Inject ElementRef in unit test

I am trying to test a component that receives a reference to ElementRef through DI.
import { Component, OnInit, ElementRef } from '#angular/core';
#Component({
selector: 'cp',
templateUrl: '...',
styleUrls: ['...']
})
export class MyComponent implements OnInit {
constructor(private elementRef: ElementRef) {
//stuffs
}
ngAfterViewInit() {
// things
}
ngOnInit() {
}
}
and the test:
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
} from '#angular/core/testing';
import { ComponentFixture, TestComponentBuilder } from '#angular/compiler/testing';
import { Component, Renderer, ElementRef } from '#angular/core';
import { By } from '#angular/platform-browser';
describe('Component: My', () => {
let builder: TestComponentBuilder;
beforeEachProviders(() => [MyComponent]);
beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
builder = tcb;
}));
it('should inject the component', inject([MyComponent],
(component: MyComponent) => {
expect(component).toBeTruthy();
}));
it('should create the component', inject([], () => {
return builder.createAsync(MyComponentTestController)
.then((fixture: ComponentFixture<any>) => {
let query = fixture.debugElement.query(By.directive(MyComponent));
expect(query).toBeTruthy();
expect(query.componentInstance).toBeTruthy();
});
}));
});
#Component({
selector: 'test',
template: `
<cp></cp>
`,
directives: [MyComponent]
})
class MyTestController {
}
Both the component and the test blueprint have been generated by Angular-cli. Now, I can't figure out which provider, if any, I should add in the beforeEachProviders for the injection of ElementRef to be successful. When I run ng test I got Error: No provider for ElementRef! (MyComponent -> ElementRef).
I encounter Can't resolve all parameters for ElementRef: (?) Error using the mock from #gilad-s in angular 2.4
Modified the mock class to:
export class MockElementRef extends ElementRef {
constructor() { super(null); }
}
resolves the test error.
Reading from the angular source code here: https://github.com/angular/angular/blob/master/packages/core/testing/src/component_fixture.ts#L17-L60
the elementRef of the fixture is not created from the mock injection. And in normal development, we do not explicitly provide ElementRef when injecting to a component. I think TestBed should allow the same behaviour.
On Angular 2.2.3:
export class MockElementRef extends ElementRef {}
Then in the test:
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
//more providers
{ provide: ElementRef, useClass: MockElementRef }
]
}).compileComponents();
}));
To inject an ElementRef:
Create a mock
class MockElementRef implements ElementRef {
nativeElement = {};
}
Provide the mock to the component under test
beforeEachProviders(() => [Component, provide(ElementRef, { useValue: new MockElementRef() })]);
EDIT: This was working on rc4. Final release introduced breaking changes and invalidates this answer.
A good way is to use spyOn and spyOnProperty to instant mock the methods and properties as needed. spyOnProperty expects 3 properties and you need to pass get or set as third property. spyOn works with class and method and returns required value.
Example
const div = fixture.debugElement.query(By.css('.ellipsis-overflow'));
// now mock properties
spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400);
spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400);
Here I am setting the get of clientWidth of div.nativeElement object.
It started showing up after I did a package update in my Angular project.
I tried all the solutions above and none of them worked for me. The problem occurred when I ran the npm run test command.
I managed to solve by updating all jest dependencies. In this case, the dependencies I updated were #briebug/jest-schematic, #types/jest, jest-preset-angular and jest

Angular 2 RC4: Unit test component that has dependency injection a service that has its own

As Angular team is constantly upgrading/deprecating stuff in Angular 2 RC versions I encountered this problem.
I have a component that has a Dependency Injection (DI), which is actually a service (UserService in this case). This UserService of course has some DIs of its own. After updating to the latest RC4 of Angular 2 I realised that I cannot create similar tests any more.
So as the docs are not mentioning something relative here's my code (simplified for this question).
My component:
import { Component } from '#angular/core';
import { MdButton } from '#angular2-material/button';
import {
MdIcon,
MdIconRegistry
} from '#angular2-material/icon';
import { UserService } from '../../services/index';
#Component({
moduleId: module.id,
selector: 'logout-button',
templateUrl: 'logout-button.component.html',
styleUrls: ['logout-button.component.css'],
providers: [MdIconRegistry, UserService],
directives: [MdButton, MdIcon]
})
export class LogoutButtonComponent {
constructor(public userService: UserService) {}
/**
* Call UserService and logout() method
*/
logout() {
this.userService.logout();
}
}
Component's DI, UserService whic as you can see has some DIs (Router, AuthHttp & Http):
import { Injectable } from '#angular/core';
import {
Http,
Headers
} from '#angular/http';
import {
AuthHttp,
JwtHelper
} from 'angular2-jwt';
import { Router } from '#angular/router';
import { UMS } from '../common/index';
#Injectable()
export class UserService {
constructor(
private router: Router,
private authHttp: AuthHttp,
private http: Http) {
this.router = router;
this.authHttp = authHttp;
this.http = http;
}
/**
* Logs out user
*/
public logout() {
this.authHttp.get(UMS.url + UMS.apis.logout)
.subscribe(
data => this.logoutSuccess(),
err => this.logoutSuccess()
);
}
}
And here's the test for the component:
import { By } from '#angular/platform-browser';
import { DebugElement } from '#angular/core';
import {
beforeEach,
beforeEachProviders,
describe,
expect,
it,
inject,
fakeAsync,
TestComponentBuilder
} from '#angular/core/testing';
import { AuthHttp } from 'angular2-jwt';
import { Router } from '#angular/router';
import { Http } from '#angular/http';
import { LogoutButtonComponent } from './logout-button.component';
import { UserService } from '../../services/index';
describe('Component: LogoutButtonComponent', () => {
beforeEachProviders(() => [
LogoutButtonComponent,
UserService
]);
it('should inject UserService', inject([LogoutButtonComponent],
(component: LogoutButtonComponent) => {
expect(component).toBeTruthy();
}));
});
Don't worry about the (it) for now.
As you can see I;m adding the related providers on the beforeEachProviders.
In this case I'm getting an error when I run the tests:
Error: No provider for Router! (LogoutButtonComponent -> UserService -> Router)
Which is expected let's say.
So in order to don't get those errors I'm adding the service's DIs in the providers also:
beforeEachProviders(() => [
LogoutButtonComponent,
Router,
AuthHttp,
Http,
UserService
]);
But now I'm, getting this error:
Error: Cannot resolve all parameters for 'Router'(?, ?, ?, ?, ?, ?, ?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'Router' is decorated with Injectable.
I'm really trying to figure out what's happening so I found some related answers here but ALL are outdated and covers the old router-deprecated or angular2/router but both are deprecated and are not covering this case.
Would love some help on this and maybe some resources as I cannot find anything related to the latest version of Router: "#angular/router": "3.0.0-beta.2", and RC4.
Thanks
UPDATE!
I manage to bypass the two errors above and now I can access the component. Here's the description code:
describe('Component: LogoutButtonComponent', () => {
let component: LogoutButtonComponent;
let router: any = Router;
let authHttp: any = AuthHttp;
let http: any = Http;
let service: any = new UserService(router, authHttp, http);
beforeEachProviders(() => [
LogoutButtonComponent
]);
beforeEach(() => {
component = new LogoutButtonComponent(service);
});
it('should inject UserService', () => {
expect(component.userService).toBeTruthy();
});
it('should logout user', () => {
localStorage.setItem('token', 'FOO');
component.logout();
expect(localStorage.getItem('token')).toBeUndefined();
});
});
But it seems that even that the DI service is injected and accessible the DIs of the service are not. So now I get this error:
TypeError: this.authHttp.get is not a function
Any ideas?
It looks like you were experiencing a dependencies loop problem, because your UserSerivce also need inject AuthHttp, Http, etc... it really will be disturb once if you need test your component.
My way is just create a mock UserSerivce and return the expect mocked value through UserService.logout() method, because you don't have to know what really happened in UserService, all you need is just a return value:
let MockUserService = {
logout() {
// return some value you need
}
}
Then, in test suite:
import { provide } from '#angular/core'
beforeEachProviders(() => [
provide(UserService, {useClass: MockUserService})
])
... detail test code here
I hope this works for you.
And here is a post that helps me a lot:
https://developers.livechatinc.com/blog/testing-angular-2-apps-dependency-injection-and-components/
With RC4, some workarounds are needed to use http in a test. See also this issue (should be fixed in RC5):
https://github.com/angular/angular/issues/9294
Adding this to my unit-tests.html fixed it for me:
System.import('#angular/platform-browser/src/browser/browser_adapter').then(function(browser_adapter) {
browser_adapter.BrowserDomAdapter.makeCurrent();
})

Trouble unit testing service with the Router injected in the constructor in Angular 2

I'm trying to test a service that has the application router injected in its constructor. Following Julie Ralph's suggestions presented in AngularConnect conf 2015 (and her repository: https://github.com/juliemr/ng2-test-seed),
I'm using Karma and Jasmine.
It follows the example service to be tested:
import { Router } from 'angular2/router';
export class ExampleService {
constructor(router : Router) {
this._router = router;
}
//...
}
Right now, I'm just asserting the truth. It follows the service test:
import { it, describe, expect, inject, beforeEachProviders, MockApplicationRef } from 'angular2/testing';
import { ROUTER_PROVIDERS } from 'angular2/router';
import { provide, ApplicationRef } from 'angular2/core';
import { ExampleService } from 'example-service.js';
describe('ExampleService', () => {
beforeEachProviders(() => [
ROUTER_PROVIDERS, ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
it('should validate the truth', inject([ExampleService], (exService) => {
expect(true).toBeTruthy();
}));
});
when I run the tests ( > karma start karma.config.js ), I get a TypeError: Cannot read property 'length' of null
Looking at the router.js source code, it looks like I should bootstrap at least one component before injecting router. Is there
an easy way to inject the Router dependency in a test?
The Stacktrace:
ORIGINAL EXCEPTION: TypeError: Cannot read property 'length' of null
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'length' of null
at routerPrimaryComponentFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/router.js:2963:27)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11920:19)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector._getByDependency (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11990:21)
at Injector._instantiate (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11887:32)
at Injector._instantiateProvider (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11859:21)
at Injector._new (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11849:19)
at InjectorDynamicStrategy.getObjByKeyId (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11733:42)
at Injector._getByKeyDefault (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12048:33)
at Injector._getByKey (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:12002:21)
at Injector.get (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2.js:11804:19)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2477:25
at Array.map (native)
at Array.map (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/es6-shim/es6-shim.js:1113:14)
at FunctionWithParamTokens.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2476:33)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2601:25
at Zone.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/angular2-polyfills.js:138:17)
at Zone.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2544:30)
at runInTestZone (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2588:23)
at Object. (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/angular2/bundles/testing.dev.js:2600:33)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at QueueRunner.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10)
at Spec.Env.queueRunnerFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35)
at Spec.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:353:10)
at Object.fn (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2360:37)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at QueueRunner.execute (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1762:10)
at Env.queueRunnerFactory (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:627:35)
at Object.fn (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2345:13)
at attemptAsync (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1819:24)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1774:9)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9
at queueRunnerFactory.onComplete (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:2348:17)
at QueueRunner.clearStack (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:605:9)
at QueueRunner.run (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1784:12)
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1801:16
at C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:1745:9
at complete (C:/Users/LSANTOS/Desktop/ng2-test-seed/node_modules/jasmine-core/lib/jasmine-core/jasmine.js:365:9)
See also https://github.com/angular/angular/issues/6325
Problem solved, just need to provide the ROUTER_PRIMARY_COMPONENT.
import {ROUTER_PRIMARY_COMPONENT} from 'angular2/router';
class MockPrimaryComponent {
}
beforeEachProviders(() => [
ROUTER_PROVIDERS,
provide(ROUTER_PRIMARY_COMPONENT, {useClass: MockPrimaryComponent}),
ExampleService,
provide(ApplicationRef, { useClass: MockApplicationRef })
]);
I know this post is related to the old router, but I thought it might be useful to answer this. Using angular version rc.1 with the new router, I got unit tests with the router, including testing navigateByUrl, by using this test within angular as inspiration: https://github.com/angular/angular/blob/master/modules/%40angular/router/test/integration_spec.ts
saved me a lot of hastle
Here's a working example
import {setBaseTestProviders,beforeEachProviders,inject,it,describe,expect,beforeEach} from '#angular/core/testing'
import { Component,provide} from '#angular/core';
import {Routes,ROUTER_DIRECTIVES,Route} from "#angular/router";
import {ComponentResolver} from '#angular/core';
import {Router,RouterOutletMap,RouteSegment,RouterUrlSerializer,DefaultRouterUrlSerializer} from '#angular/router';
import {SpyLocation} from '#angular/common/testing';
import {Location} from '#angular/common';
import {ComponentFixture, TestComponentBuilder} from '#angular/compiler/testing';
import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from '#angular/platform-browser-dynamic/testing';
#Component({
selector: 'some-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class SomeComponent {
}
#Component({
selector: 'another-component',
template: `Blah!`,
directives: [ROUTER_DIRECTIVES]
})
export class AnotherComponent {
}
#Component({
selector: 'root-cmp',
template: `<router-outlet></router-outlet>`,
directives: [ROUTER_DIRECTIVES]
})
#Routes([
new Route({path: '/some-path',component:SomeComponent}),
new Route({path: '/another-path',component:AnotherComponent})
])
export class RootCmp {
}
export const PROVIDERS_TESTING = [
provide(RouterUrlSerializer, {useClass: DefaultRouterUrlSerializer}),
RouterOutletMap,
provide(Location, {useClass: SpyLocation}),
provide(RouteSegment, {useFactory: (r) => r.routeTree.root, deps: [Router]}),
provide(Router,{
useFactory: (resolver, urlParser, outletMap, location) => new Router(
"RootComponent", RootCmp, resolver, urlParser, outletMap, location),
deps: [ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location]
}
),
]
setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,[TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,PROVIDERS_TESTING]);
it('some test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/some-path').then(()=>{
expect(location.path()).toEqual('/some-path');
resolve()
})
})
})
}))
it('another test',inject([Router, TestComponentBuilder, Location], (router:Router, tcb:TestComponentBuilder, location:Location) => {
return new Promise((resolve,reject)=>{
tcb.createAsync(RootCmp).then(fixture=>{
router.navigateByUrl('/another-path').then(()=>{
expect(location.path()).toEqual('/another-path');
resolve()
})
})
})
}))