How to pass Unit test after implementing ngx-bootstrap/datepicker? - unit-testing

I created independent component with ngx-bootstrap/datepicker on angular-cli project.
Everything works fine but Unit test is failing.
But I am new on Unit Testing, and I tried to test but it saying fails.
Here is Travic-CI build log.
https://travis-ci.org/webcat12345/webcat-black-page/builds/221961698
Here is my project version and code.
#angular/cli: 1.0.0
node: 7.6.0
os: linux x64
#angular/cli: 1.0.0
#angular/common: 4.0.2
#angular/compiler: 4.0.2
#angular/compiler-cli: 4.0.2
#angular/core: 4.0.2
#angular/forms: 4.0.2
#angular/http: 4.0.2
#angular/platform-browser: 4.0.2
#angular/platform-browser-dynamic: 4.0.2
#angular/router: 4.0.2
Template
<datepicker class="well well-sm main-calendar" [(ngModel)]="dt" [minDate]="minDate" [showWeeks]="false" [dateDisabled]="dateDisabled"></datepicker>
Component (sorry for posting full code. it is just sample code from ngx-bootstrap demo)
import { Component, OnInit } from '#angular/core';
import * as moment from 'moment';
#Component({
selector: 'app-sidebar-datepicker',
templateUrl: './sidebar-datepicker.component.html',
styleUrls: ['./sidebar-datepicker.component.scss']
})
export class SidebarDatepickerComponent implements OnInit {
public dt: Date = new Date();
public minDate: Date = void 0;
public events: any[];
public tomorrow: Date;
public afterTomorrow: Date;
public dateDisabled: {date: Date, mode: string}[];
public formats: string[] = ['DD-MM-YYYY', 'YYYY/MM/DD', 'DD.MM.YYYY',
'shortDate'];
public format: string = this.formats[0];
public dateOptions: any = {
formatYear: 'YY',
startingDay: 1
};
private opened: boolean = false;
constructor() {
(this.tomorrow = new Date()).setDate(this.tomorrow.getDate() + 1);
(this.afterTomorrow = new Date()).setDate(this.tomorrow.getDate() + 2);
(this.minDate = new Date()).setDate(this.minDate.getDate() - 1000);
(this.dateDisabled = []);
this.events = [
{date: this.tomorrow, status: 'full'},
{date: this.afterTomorrow, status: 'partially'}
];
}
ngOnInit() {
}
public getDate(): number {
return this.dt && this.dt.getTime() || new Date().getTime();
}
public today(): void {
this.dt = new Date();
}
public d20090824(): void {
this.dt = moment('2009-08-24', 'YYYY-MM-DD')
.toDate();
}
public disableTomorrow(): void {
this.dateDisabled = [{date: this.tomorrow, mode: 'day'}];
}
// todo: implement custom class cases
public getDayClass(date: any, mode: string): string {
if (mode === 'day') {
let dayToCheck = new Date(date).setHours(0, 0, 0, 0);
for (let event of this.events) {
let currentDay = new Date(event.date).setHours(0, 0, 0, 0);
if (dayToCheck === currentDay) {
return event.status;
}
}
}
return '';
}
public disabled(date: Date, mode: string): boolean {
return ( mode === 'day' && ( date.getDay() === 0 || date.getDay() === 6 ) );
}
public open(): void {
this.opened = !this.opened;
}
public clear(): void {
this.dt = void 0;
this.dateDisabled = undefined;
}
public toggleMin(): void {
this.dt = new Date(this.minDate.valueOf());
}
}
Test Code
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { DatepickerModule } from 'ngx-bootstrap/datepicker';
import { SidebarDatepickerComponent } from './sidebar-datepicker.component';
describe('SidebarDatepickerComponent', () => {
let component: SidebarDatepickerComponent;
let fixture: ComponentFixture<SidebarDatepickerComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SidebarDatepickerComponent ],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
imports: [DatepickerModule.forRoot()]
})
.compileComponents();
}));
beforeEach(async() => {
fixture = TestBed.createComponent(SidebarDatepickerComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
Please help me to figure out this issue.
Thank you!

1) Use NO_ERRORS_SCHEMA instead of CUSTOM_ELEMENTS_SCHEMA because:
CUSTOM_ELEMENTS_SCHEMA will allow:
any non-Angular elements with a - in their name,
any properties on elements with a - in their name which is the common rule for custom
but your component without -(datepicker)
NO_ERRORS_SCHEMA will allow any property on any element
TestBed.configureTestingModule({
declarations: [ SidebarDatepickerComponent ],
schemas: [NO_ERRORS_SCHEMA],
imports: [DatepickerModule.forRoot()]
})
2) Another option is importing FormsModule
TestBed.configureTestingModule({
declarations: [ SidebarDatepickerComponent ],
imports: [DatepickerModule.forRoot(), FormsModule]
})

Related

How to provide NgControl when testing custom field control components?

I have a simple custom control as below. Everything is working but the unit test is failing. How can I unit test this custom control? How can I pass a valid NgControl directive?
I have tried using providers:
[
{
provide: NgControl,
useValue: new FormGroup()
}
]
but I still get the same error.
core-edi.component.ts
import { Component, OnInit, Input, ViewChild, ElementRef, Self, Optional, forwardRef } from '#angular/core';
import {
ControlValueAccessor, NG_VALUE_ACCESSOR, Validator, AbstractControl,
ValidatorFn, Validators, NG_VALIDATORS, NgControl, NgForm
} from '#angular/forms';
import { Placeholder } from '#angular/compiler/src/i18n/i18n_ast';
#Component({
selector: 'app-core-edi',
templateUrl: './core-edi.component.html',
styleUrls: ['./core-edi.component.css'],
})
export class CoreEdiComponent implements ControlValueAccessor, Validator, OnInit {
#ViewChild('input') input: ElementRef;
disabled;
#Input() type = 'text';
#Input() isRequired: boolean = false;
#Input() pattern: string = null;
#Input() label: string = null;
#Input() placeholder: string;
#Input() errorMsg: string;
#Input() min: number;
#Input() minLength: number;
myhint: string = '10 digit number';
constructor(#Self() public controlDir: NgControl) {
this.controlDir.valueAccessor = this;
}
ngOnInit() {
const control = this.controlDir.control;
const validators: ValidatorFn[] = control.validator ? [control.validator] : [];
if (this.isRequired) {
validators.push(Validators.required);
}
if (this.pattern) {
validators.push(Validators.pattern(this.pattern));
}
if (this.min) {
validators.push(Validators.min(this.min));
}
control.setValidators(validators);
control.updateValueAndValidity();
this.placeholder = this.placeholder + (this.isRequired ? '*' : '');
}
onChange(event) {
}
onTouched() {
}
writeValue(obj: any): void {
this.input.nativeElement.value = obj;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.disabled = isDisabled;
}
validate(c: AbstractControl): { [key: string]: any; } {
const validators: ValidatorFn[] = [];
if (this.isRequired) {
validators.push(Validators.required);
}
if (this.pattern) {
validators.push(Validators.pattern(this.pattern));
}
if (this.min) {
validators.push(Validators.min(this.min));
}
return validators;
}
core-edi.component.html
<div class="form-label-group" fxLayout="column" fxLayoutGap="5px">
<mat-form-field class="edi-field-width">
<input matInput class="form-control"
[type]="type" #input
(input)="onChange($event.target.value)"
(blur)="onTouched()"
[disabled]="disabled"
[placeholder]="placeholder"
[min]="1111111111"
[minLength] = 10
(keyup)="mykeyup()">
<mat-hint>Hint: {{ myhint }}</mat-hint>
</mat-form-field>
<span class="error"
*ngIf="controlDir && !controlDir.control.valid
&& controlDir.control.touched">{{errorMsg}}</span>
</div>
core-edi.component.spec.ts
import { async, ComponentFixture, TestBed } from '#angular/core/testing';
import { CoreEdiComponent } from './core-edi.component';
import { FormsModule, ReactiveFormsModule, FormControl, NgControl, FormControlDirective } from '#angular/forms';
import { MaterialModule } from 'src/app/material/material.module';
fdescribe('CoreEdiComponent', () => {
let component: CoreEdiComponent;
let fixture: ComponentFixture<CoreEdiComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CoreEdiComponent ],
imports: [
FormsModule,
ReactiveFormsModule,
MaterialModule
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CoreEdiComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
No provider for NgControl ("[ERROR ->]<app-core-edi></app-core-edi>"): #0:0
at syntaxError (./node_modules/#angular/compiler/fesm5/compiler.js?:1275:17)
at TemplateParser.parse (./node_modules/#angular/compiler/fesm5/compiler.js?:15084:19)
at JitCompiler._parseTemplate (./node_modules/#angular/compiler/fesm5/compiler.js?:24272:37)
at JitCompiler._compileTemplate (./node_modules/#angular/compiler/fesm5/compiler.js?:24259:23)
at eval (./node_modules/#angular/compiler/fesm5/compiler.js?:24202:62)
at Set.forEach (<anonymous>)
at JitCompiler._compileComponents (./node_modules/#angular/compiler/fesm5/compiler.js?:24202:19)
at eval (./node_modules/#angular/compiler/fesm5/compiler.js?:24120:19)
at Object.then (./node_modules/#angular/compiler/fesm5/compiler.js?:1266:77)
at JitCompiler._compileModuleAndAllComponents (./node_modules/#angular/compiler/fesm5/compiler.js?:24118:26)
Expected undefined to be truthy.
at UserContext.eval (./src/app/core/core-edi/core-edi.component.spec.ts?:30:27)
at ZoneDelegate.invoke (./node_modules/zone.js/dist/zone.js?:390:26)
at ProxyZoneSpec.onInvoke (./node_modules/zone.js/dist/zone-testing.js?:288:39)
I have not been through understanding how to unit test in angular yet, but maybe its in the app.module that you need to add like the ReactiveFormsModule
The answer to this helped me out
Why do I get this Template parse errors in Angular
Just my 2cents

Angular 4/CLI Unit test issue How to test a method of component that contains input object variable

Could somebody guide me how can I implement a unit test for the component below? I'm going to test the next() method of this component.When I implement a unit test for this function I got an error.Actually I'm beginner in unit test so I appreciate if somebody implements a Professional unit test on this sample which be reference for me for other components.
component file:
import { Component, Input, OnInit } from '#angular/core';
import { Client, ClientMetadata } from '../../shared/clients/client.model';
import { ClientService } from '../../shared/clients/client.service';
import { HomeRoutingService } from '../home-routing/home-routing.service';
import { FormValidationService } from "../../shared/form-validation/form-
validation.service";
import { FormBuilder} from '#angular/forms';
#Component({
selector: 'email-form',
templateUrl: './email-form.component.html',
styleUrls: ['./email-form.component.css', '../home.component.css'],
})
export class EmailFormComponent implements OnInit{
#Input() client: Client;
isClickedIncognito: boolean;
isClickedNext: boolean;
constructor(
private clientService: ClientService,
private homeRoutingService: HomeRoutingService,
public fv: FormValidationService
) { }
ngOnInit() {
this.isClickedIncognito = false;
this.isClickedNext = false;
// form is builded in fv service
this.fv.buildFormEmail();
}
next(anonymous: boolean): void {
document.body.style.cursor = 'wait';
this.client.anonymous = anonymous === true ? 1 : 0;
// If client is anonymous go directly to measurement form
if (anonymous) {
this.isClickedIncognito = true;
this.saveClient();
this.homeRoutingService.next(this.constructor.name, { anonymous:
true });
}
// Check if client exists in DB ; check if has password ;
else {
this.isClickedNext = true;
this.clientService.checkExist(this.client.email)
.then(exists =>
this.handleExist(exists)
);
}
}
saveClient(): void {
let gender = new ClientMetadata('gender', environment.gender);
(this.client.clientMetadatas = this.client.clientMetadatas ?
this.client.clientMetadatas : []).push(gender);
if (this.client.anonymous === 1)
this.client.email = null;
else if (this.client.email === null) { return; }
this.clientService.addClient(this.client)
.then(client => this.client = client);
}
}
spec file :
import { ComponentFixture, TestBed, async } from '#angular/core/testing';
import { By } from '#angular/platform-browser';
import { DebugElement, NO_ERRORS_SCHEMA } from '#angular/core';
import { EmailFormComponent } from './email-form.component';
import { ClientService } from '../../shared/clients/client.service';
import { HomeRoutingService } from '../home-routing/home-routing.service';
import { FormValidationService } from "../../shared/form-validation/form-
validation.service";
import { FormBuilder } from '#angular/forms';
import { Client, ClientMetadata } from '../../shared/clients/client.model';
import { TranslateModule, TranslateStaticLoader, TranslatePipe,
TranslateLoader } from 'ng2-translate';
import { Http } from '#angular/http';
export function createTranslateLoader(http: Http) {
return new TranslateStaticLoader(http, '../../assets/i18n/', '.json');
}
describe('EmailFormComponent', () => {
let component: EmailFormComponent;
let fixture: ComponentFixture<EmailFormComponent>;
let de: DebugElement;
let el: HTMLElement;
let formService: FormValidationService;
let clientService: ClientService;
let ClientEl: Client;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [EmailFormComponent],
providers: [FormValidationService,
ClientService,
HomeRoutingService,
FormValidationService,
FormBuilder
// { provide: ClientService, useValue: ClientServiceStub },
// { provide: HomeRoutingService, useValue:
HomeRoutingServiceStub },
// { provide: FormValidationService, useValue: FormValidationServiceStub }
],
schemas: [NO_ERRORS_SCHEMA],
imports: [TranslateModule.forRoot({
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [Http]
})]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EmailFormComponent);
component = fixture.componentInstance;
// formService = fixture.debugElement.injector.get(FormValidationService);
// formService.buildFormEmail();
// clientService = fixture.debugElement.injector.get(ClientService);
// fixture.detectChanges();
});
it('should component works well', async(() => {
const fixture = TestBed.createComponent(EmailFormComponent);
const comp = fixture.debugElement.componentInstance;
expect(comp).toBeTruthy();
}));
it('should be correct', () => {
let anonymous = true;
component.next(anonymous);
//console.log(component.isClickedIncognito);
expect(component.isClickedIncognito).toBe(true);
//expect(true).toBe(true);
});
});
error (when I comment fixture.detectChanges()):
Cannot set property 'anonymous' of undefined
error (when I put fixture.detectChanges()):
Cannot read property 'email' of undefined

Ionic 2: Error testing with Karma/Jasmine/TestBed

I'm new with Ionic2 and I was following this tutorial and a simple test like
describe('Dummy test', () => {
it('should do nothing', () => {
expect(true).toBeTruthy();
expect(1 + 1).toBe(2);
});
});
works fine, but for some reason I keep getting this error when I try to follow the rest of the tutorial.
Component: Root Component
✖ initialises with a root page of LoginPage
Firefox 45.0.0 (Linux 0.0.0)
TypeError: win is undefined in src/test.ts (line 937)
My src/test.ts is the same as the tutorial and it doesn't have any win in it. My app.spec.ts is this
import { TestBed, ComponentFixture, async } from '#angular/core/testing';
import { IonicModule } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { UserData } from '../providers/user-data';
import { LoginPage } from '../pages/login/login';
import { Platform } from 'ionic-angular';
import { MyApp } from './app.component';
import { LoginPage } from '../pages/login/login';
let comp: MyApp;
let fixture: ComponentFixture<MyApp>;
describe('Component: Root Component', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyApp],
providers: [
StatusBar,
SplashScreen,
UserData,
Platform
],
imports: [
IonicModule.forRoot(MyApp)
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyApp);
comp = fixture.componentInstance;
});
afterEach(() => {
fixture.destroy();
comp = null;
});
it('initialises with a root page of LoginPage', () => {
expect(comp['rootPage']).toBe(LoginPage);
});
});
And my app.component.ts is this
import { Component } from '#angular/core';
import { Platform } from 'ionic-angular';
import { StatusBar } from '#ionic-native/status-bar';
import { SplashScreen } from '#ionic-native/splash-screen';
import { MenuSidePage } from '../pages/menu-side/menu-side';
import { LoginPage } from '../pages/login/login';
import { UserData } from '../providers/user-data';
#Component({
template: `<ion-nav #nav [root]="rootPage"></ion-nav>`
})
export class MyApp {
rootPage: any;
constructor(
public platform: Platform,
public statusBar: StatusBar,
public splashScreen: SplashScreen,
private userData: UserData,
) {
platform
.ready()
.then(() => {
//First - check if user is logged
if(this.userData.currentUser) {
this.rootPage = MenuSidePage;
} else {
this.rootPage = LoginPage;
}
statusBar.styleDefault();
splashScreen.hide();
});
}
}
I don't have yet the solution, but you shouldn't use compileComponents() 'cause you are using a template and not a templateUrl like said in this tutorial :
"We need to use compileComponents when we need to asynchronously compile a component, such as one that has an external template (one that is loaded through templateUrl and isn’t inlined with template). This is why the beforeEach block that this code runs in uses an async parameter – it sets up an asynchronous test zone for the compileComponents to run inside."
Hope it's a kind of helping :)
The win() function come from the Plaftorm, you have to mock it as follow :
export class PlatformMock {
public ready(): Promise<string> {
return new Promise((resolve) => {
resolve('READY');
});
}
public getQueryParam() {
return true;
}
public registerBackButtonAction(fn: Function, priority?: number): Function {
return (() => true);
}
public hasFocus(ele: HTMLElement): boolean {
return true;
}
public doc(): HTMLDocument {
return document;
}
public is(): boolean {
return true;
}
public getElementComputedStyle(container: any): any {
return {
paddingLeft: '10',
paddingTop: '10',
paddingRight: '10',
paddingBottom: '10',
};
}
public onResize(callback: any) {
return callback;
}
public registerListener(ele: any, eventName: string, callback: any): Function {
return (() => true);
}
public win(): Window {
return window;
}
public raf(callback: any): number {
return 1;
}
public timeout(callback: any, timer: number): any {
return setTimeout(callback, timer);
}
public cancelTimeout(id: any) {
// do nothing
}
public getActiveElement(): any {
return document['activeElement'];
}
}
Here is the link to see a project for real integration of this mock class.
Hope it helps :)

Angular2 Testing

Stuck on how to test a component that has alot of third party dependencies. Pretty sure I'm approaching it the wrong way, I'm not sure where to start on this. Here's the component:
import { Component, OnInit } from '#angular/core';
import { Http, Response } from '#angular/http';
import { GameService } from '../game.service';
import { environment } from '../../../environments/environment';
import { ActivatedRoute } from '#angular/router';
import { SlimLoadingBarService } from 'ng2-slim-loading-bar';
#Component({
selector: 'app-list',
templateUrl: 'list.component.html',
styleUrls: ['list.component.scss']
})
export class ListComponent implements OnInit {
config = environment.config;
games;
headers;
params = {
searchTerm: '',
searchOwner: '',
searchType: '',
order: 'name',
orderType: 'DESC',
currentPage: 1,
page: 1
};
pages;
totalRecords;
recordsPerPage = 25;
exportUrl;
personasPage = 1;
searchUrl = environment.config.apiUrl + 'personas/';
public buffer: any;
public personas: any;
buttonSpinner: string = 'none';
constructor(
private gameService: GameService,
private http: Http,
private route: ActivatedRoute,
private loadingBar: SlimLoadingBarService
) { }
ngOnInit() {
this.getListing();
this.getPersonas();
}
sort(e, order) {
e.preventDefault();
this.params.orderType = (order === this.params.order && this.params.orderType === 'DESC') ? 'ASC' : 'DESC';
this.params.order = order;
this.params.page = this.params.currentPage = 1;
this.getListing();
}
updateListing(page) {
this.params.page = this.params.currentPage = page;
this.getListing();
}
getListing() {
this.loadingBar.start();
this.gameService.getGames(this.params)
.subscribe((res) => {
this.loadingBar.complete();
this.buttonSpinner = 'none';
this.games = res.json();
this.headers = res.headers;
this.totalRecords = this.headers.get('x-total');
this.recordsPerPage = this.headers.get('x-limit');
this.exportUrl = this.gameService.getExportLink(this.params);
});
}
getPersonas() {
this.http.get(this.searchUrl + '?page=' + this.personasPage)
.map((res: Response) => res.json())
.subscribe((d: {}) => {
this.buffer = d;
if (this.personas === undefined) {
this.personas = this.buffer;
// console.log(this.personas);
this.personasPage += 1;
this.getPersonas();
} else {
for (let key in this.buffer) {
this.personas.push(this.buffer[key]);
}
this.personasPage += 1;
if (this.buffer.length === 25) {
this.getPersonas();
}
}
});
}
onSubmitSearch() {
this.buttonSpinner = 'searching';
this.params.page = this.params.currentPage = 1;
this.getListing();
}
clearSearch(e) {
e.preventDefault();
this.buttonSpinner = 'clearing';
this.params.searchTerm = '';
this.params.searchType = '';
this.params.searchOwner = '';
this.params.page = this.params.currentPage = 1;
this.getListing();
}
}
Here's the Test I've tried writing:
import { TestBed, async, ComponentFixture } from '#angular/core/testing';
import {} from 'jasmine';
import { Http } from '#angular/http';
import { ActivatedRoute, RouterModule } from '#angular/router';
import { CUSTOM_ELEMENTS_SCHEMA } from '#angular/core';
import { FormsModule } from '#angular/forms';
import { ListComponent } from './list.component';
import { GameService } from '../game.service';
import { PageitComponent } from '../../shared/pageit/pageit.component';
import { SlimLoadingBarService } from 'ng2-slim-loading-bar';
import { LaddaModule } from 'angular2-ladda';
describe('ListComponent', () => {
let gameService, http, route, loadingBar;
let component: ListComponent;
let fixture: ComponentFixture<ListComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ ListComponent, PageitComponent ],
providers: [
{ provide: GameService, useValue: gameService }, { provide: Http, useValue: http }, { provide: ActivatedRoute, useValue: route },
{ provide: SlimLoadingBarService, useValue: loadingBar }
],
imports: [FormsModule, LaddaModule, RouterModule]
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ListComponent);
component = fixture.componentInstance;
});
it('should create an instance of the component', () => {
component.ngOnInit();
expect(component).toBeDefined();
});
});
So far, I've got it to recognize the init, now it's breaking because of this.loadingBar.start(); inside the getListing function.
Just mock all the services and test the behavior of the component by checking that it makes the correct service class, by using expect(mockService.someMethod).toHaveBeenCalled().
For example
let loadingBar: SlimLoadingBarService;
let gameService: GameService;
beforeEach(() => {
loadingBar = {
start: jasmine.createSpy('start'),
complete: jasmine.createSpy('complete')
};
gameService = {
getGames: (params) => Observable.of(whatever)
};
TestBed.configureTestingModule({
providers: [
{ provide: SlimLoadingBarService, useValue: loadingBar },
{ provide: GameService, useValue: gameService }
]
})
})
it('..', () -> {
component.getListing();
expect(loadingBar.start).toHaveBeenCalled();
// component calls gameService.getGames is called, wait for async
// to finish by called fixture.whenStable
fixture.whenStable().then(() => {
expect(loadingBar.complete).toHaveBeedCalled();
})
})
For you Http call in the component, I would abstract that into a service so that you can mock that service.

angular 2 RC4- Cannot resolve all parameters for 'Router'

I have written a test for my component and it is failing with
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.
import { Component, OnInit } from '#angular/core';
import { Router, ActivatedRoute } from '#angular/router';
import { Supplier } from './supplier';
import { SupplierService } from './supplier.service';
import { AppService } from '../shared/app.service';
#Component({
moduleId: module.id,
selector: 'supplier-form',
templateUrl: './supplier-form.component.html',
styleUrls: ['./supplier-form.component.css']
})
export class SupplierFormComponent implements OnInit {
private countries: any;
private model: Supplier;
private errorMessage: string;
private submitted: boolean = false;
private active: boolean = true;
constructor(private appService: AppService, private supplierService: SupplierService, private router: Router, private route: ActivatedRoute) {
this.model = new Supplier();
this.route.params.subscribe(params => {
let id = +params['id']; // (+) converts string 'id' to a number
if (!isNaN(id))
this.supplierService.getSupplierById(id)
.subscribe(supplier => this.model = supplier, error => this.errorMessage = error);
});
}
ngOnInit() {
this.getCountries();
}
private getCountries() {
this.appService.getCountry()
.subscribe(countries => this.countries = countries.items,
error => this.errorMessage = error);
}
private navigateToHomePage(supplier) {
if (supplier) {
let link = [''];
this.router.navigate(link);
}
}
private onSubmit(): void {
this.submitted = true;
this.supplierService.saveSupplier(this.model).subscribe(
supplier => this.navigateToHomePage(supplier),
error => this.errorMessage = error);
}
}
very simple component all its doing is getting countries from a service which is using Http call and calling save method on another service which is also http call. I am mocking those services with my Mock classes. below is my test code.
import { By } from '#angular/platform-browser';
import { DebugElement, provide } from '#angular/core';
import { disableDeprecatedForms, provideForms } from '#angular/forms';
import { Router, ActivatedRoute } from '#angular/router';
import * as Rx from 'rxjs/Rx';
import {
beforeEach, beforeEachProviders,
describe, xdescribe,
expect, it, xit,
async, inject, addProviders,
TestComponentBuilder, ComponentFixture
} from '#angular/core/testing';
import { SupplierFormComponent } from './supplier-form.component';
import { SupplierService } from './supplier.service';
import { AppService } from '../shared/app.service';
describe('Component: Supplier', () => {
var builder;
beforeEachProviders(() => {
return [
disableDeprecatedForms(),
provideForms(),
Router, ActivatedRoute,
provide(AppService, { useClass: MockAppService }),
provide(SupplierService, { useClass: MockSupplierService })
];
});
beforeEach(inject([TestComponentBuilder], (tcb) => {
builder = tcb;
}));
it('should create Supplier Component', async(() => {
/*.overrideProviders(
SupplierFormComponent,
[{ provide: AppService, useClass: MockAppService }]
)*/
builder.createAsync(SupplierFormComponent)
.then((fixture: ComponentFixture<SupplierFormComponent>) => {
fixture.detectChanges
var compiled = fixture.debugElement.nativeElement;
console.log(compiled);
})
.catch((error) => {
console.log("error occured: " + error);
});
}));
});
class MockAppService {
public name = "Injected App Service";
public fakeResponse: any = [{ "id": 1, "name": "uk" }];
public getCountry() {
return this.fakeResponse;
}
}
class MockSupplierService {
public name = "Injected Supplier Service";
saveSupplier(supplier: any): boolean {
return true;
}
}
any idea how can i mock router properly with RC.4.