Angular unit testing Error: "Keyboard" plugin is not implemented on web - unit-testing

app.component.ts:->
`if (Capacitor.isPluginAvailable('Keyboard')) {
this.keypadOpenListner = Keyboard.addListener('keyboardDidShow', () => {
this.zone.run(() => {
this.isKeyboardShowing = true;
})
});
this.keypadOffListner = Keyboard.addListener('keyboardDidHide', () => {
this.zone.run(() => {
this.isKeyboardShowing = false;
})
});
}`
`
app.component.spec.ts:->
` describe('app compenent', () => {
let fixture: ComponentFixture<AppComponent>;
let component: AppComponent;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [AppComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
spyOn(Capacitor, 'isNativePlatform').and.returnValue(true);
fixture.detectChanges();
});`
to cover if condition I added spyOn(Capacitor, 'isNativePlatform').and.returnValue(true); in beforeEach condition is this correct? if yes I got warning "Keyboard" plugin is not implemented on web how can I overcomethe warning ?.

Related

Testing angular components with dependencies

Hellow. I trying to test a component but i still doind it in the right way and i would like some help. This is the component:
export class ModalLoadingComponent implements OnInit {
#ViewChild('loading') loading: LoadingComponent;
constructor(public dialogRef: MatDialogRef<ModalLoadingComponent>, #Inject(MAT_DIALOG_DATA) public data: any) { }
ngOnInit(): void {}
close() {
this.dialogRef.close();
}
and this is my test
fdescribe('CardsComponent', () => {
let component: ModalLoadingComponent;
let fixture: ComponentFixture<ModalLoadingComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ModalLoadingComponent],
providers: [MatDialogRef],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ModalLoadingComponent);
component = fixture.componentInstance;
fixture.whenStable();
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

How to test router.navigate with subscribe ? Angular2

I'm pretty new in unit testing in Angular 2 so i'm asking your help.
My logout function :
logOut() {
this.authService.logOut().subscribe(() => {
this.router.navigate(['login']);
});
}
And my unit test :
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
let authenticationService: AuthenticationService;
let mockLogOut = {
logOut: () => { }
};
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
HttpModule,
CommonModule,
ReactiveFormsModule,
TranslateModule,
RouterTestingModule.withRoutes([
{ path: 'login', component: LoginComponent }
])
],
declarations: [HomeComponent, LoginComponent],
providers: [
{ provide: AuthenticationService, useValue: mockLogOut },
TranslateService,
TRANSLATION_PROVIDERS
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
authenticationService = TestBed.get(AuthenticationService);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
describe('Authentication Tests', () => {
it('should log out the user', inject([AuthenticationService], (mockLogin: AuthenticationService) => {
fakeAsync(() => {
spyOn(authenticationService, 'logOut');
let navigateSpy = spyOn((<any>component).router, 'navigate');
component.logOut();
expect(mockLogin.logOut).toHaveBeenCalled();
expect(navigateSpy).toHaveBeenCalledWith(['/log1n']);
});
}));
});
});
I want to check if the user is redirected to the route /login but this test always success even if I put something else than /login

Angular 2 testing components with observables

I am testing a angular component and the code is
ngOnInit(): void {
this.getNar();
}
getNar(): void {
let self = this;
this.dashboardService.getNar().subscribe(
res => self.narIds = res.narIds,
error => self.error = error,
function () {
self.narIds.forEach(element => {
// Some Code
});
}
);
}
The Service provider for this i.e Dashboard Service is
getNar(): Observable<any> {
return this.http.get(Config.Api.GetNar + '1/nar').map((res: Response) => res.json());
}
And my Test cases are:
let res = '"narIds":[{"id":1,"narId":"104034-1","narName":"SDLC Platform"},{"id":2,"narId":"64829-1","narName":"EMS-EMS"}]';
describe('Application Health Component', () => {
beforeEach( async(() => {
TestBed.configureTestingModule({
providers: [MockBackend, DashboardService],
imports: [ChartsModule, SlimScrollModule, HttpModule],
declarations: [CompletedFilterPipe, ApplicationHealthComponent]
})
.compileComponents()
.then(createComponent);
}));
it('should call the getNar when ngOnInit is called', async(() => {
spyOn(dashboardService, 'getNar').and.returnValue(Observable.of(res));
comp.ngOnInit();
expect(dashboardService.getNar).toHaveBeenCalled();
}));
});
function createComponent() {
fixture = TestBed.createComponent(ApplicationHealthComponent);
comp = fixture.componentInstance;
dashboardService = fixture.debugElement.injector.get(DashboardService);
};
The problem I am getting is the test case gives an error that forEach is undefined.
The error message is not that forEach function is not defined, it's that your object "self.narIds" is undefined. Fairly sure this is due to the way you declared your onComplete function in Observable.subscribe
related to this Rx Subscribe OnComplete fires but cannot use the data
change your
function () {
self.narIds.forEach(element => {
// Some Code
});
code to
() => {
self.narIds.forEach(element => {
// Some Code
});

Angular 2 Observable testing Error: Cannot use setInterval from within an async zone test

I'm trying to test a component, which uses a service that makes async http calls. The service returns an Observable, which the component subscribes on.
Service code snippet:
getRecentMachineTemperatures(_machine_Id): Observable<IDeviceReadings[]> {
return this.http.get(TemperatureService.URL + _machine_Id)
.map(response => { return response.json(); })
.map((records: Array<any>) => {
let result = new Array<IDeviceReadings>();
if (records) {
records.forEach((record) => {
let device = new IDeviceReadings();
device.device_id = record.device_id;
if (record.d) {
record.d.forEach((t) => {
let temperature = new ITemperature();
temperature.timestamp = t.timestamp;
temperature.value = t.temperature;
device.temperatures.push(temperature);
});
}
result.push(device);
});
}
return result;
});
}
Component code snippet:
ngOnInit() {
this.getRecentTemperatures();
}
getRecentTemperatures() {
this.temperatureService.getRecentMachineTemperatures(this.machine_id)
.subscribe(
res => {
let device1 = res[0];
this.deviceId = device1.device_id;
this.initTemperatures(device1.temperatures);
this.updateChart();
},
error => console.log(error));
}
My Test sets up dependencies, spies on the service 'getRecentMachineTemperatures' and sets i to return some stub data. I've been googling around for ways to test this, thus resulting in 3 different test, trying to test the same thing. Each giving me a different error.
temperature.component.spec.ts:
let machine_id = 1;
let comp: TemperatureComponent;
let fixture: ComponentFixture<TemperatureComponent>;
let de: DebugElement;
let el: HTMLElement;
let temperatureService: TemperatureService;
let stubDevices: IDeviceReadings[];
let stubTemperatures: ITemperature[];
let spyRecentTemps: Function;
describe('Component: Temperature', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [TemperatureComponent],
imports: [ ChartsModule ],
providers: [
MockBackend,
BaseRequestOptions,
{ provide: Http,
useFactory: (backend, defaultOptions) => {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]},
TemperatureService
]
});
stubDevices = new Array<IDeviceReadings>();
let stubDevice = new IDeviceReadings();
stubDevice.device_id = 'stub device';
stubDevice.temperatures = new Array<ITemperature>();
let stubTemp = new ITemperature();
stubTemp.timestamp = new Date().getTime();
stubTemp.value = 10;
stubDevice.temperatures.push(stubTemp);
stubDevices.push(stubDevice);
stubTemperatures = new Array<ITemperature>();
let stubTemp2 = new ITemperature();
stubTemp.timestamp = new Date().getTime() + 1;
stubTemp.value = 11;
stubTemperatures.push(stubTemp2);
fixture = TestBed.createComponent(TemperatureComponent);
comp = fixture.componentInstance;
temperatureService = fixture.debugElement.injector.get(TemperatureService);
spyRecentTemps = spyOn(temperatureService, 'getRecentMachineTemperatures')
.and.returnValue(Observable.of(stubDevices).delay(1));
// get the "temperature-component" element by CSS selector (e.g., by class name)
de = fixture.debugElement.query(By.css('.temperature-component'));
el = de.nativeElement;
});
it('should show device readings after getRecentTemperatures subscribe (fakeAsync)', fakeAsync(() => {
fixture.detectChanges();
expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');
tick(1000);
fixture.detectChanges();
expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
}));
it('should show device readings after getRecentTemperatures subscribe (async)', async(() => {
fixture.detectChanges();
expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
});
}));
it('should show device readings after getRecentTemperatures subscribe (async) (done)', (done) => {
async(() => {
fixture.detectChanges();
expect(spyRecentTemps.calls.any()).toBe(true, 'getRecentTemperatures called');
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(el.textContent).toContain(stubDevices[0].temperatures[0].timestamp);
expect(el.textContent).toContain(stubDevices[0].temperatures[0].value);
}).then(done);
});
});
});
fakeAsync fails with: 'Error: 1 timer(s) still in the queue.'
async fails with: 'Error: Cannot use setInterval from within an async zone test.'
async (done) fails with: 'Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.'
How would I go about testing components with a async service dependency?
From what I understand it might be something about the AsyncScheduler within the Rx library using Date().now instead of faked time (https://github.com/angular/angular/issues/10127). If so has this been fixed? Or anyone found a workaround?
I'm using angular-cli: 1.0.0-beta.16. node: 4.4.2. npm: 3.10.6. webpack 2.1.0-beta.22.
I had ..
import 'rxjs/add/operator/timeout';
return this.http[method](url, emit, this.options)
.timeout(Config.http.timeout, new Error('timeout'))
Which was causing this error. I believe under the hood RXJS .timeout is calling setInterval.
I fixed this by switching ...
it('blah', async(() => {
to
it('blah', (done) => {

Angular2, test directive, undefined-error

I'm trying to test a directive, called AceDirective (I'm using the ace-editor).
So first I've build a TestComponent called MockSearchDirective which has got this directive:
#Component({
selector: '[testAce]',
directives: [AceDirective],
template: '<div ace-editor></div>',
}) class TestAce {}
class MockSearchDirective {
}
Now if got my beforeEach and beforeEachProviders with the needed Injections:
beforeEachProviders( () => [
provide(SearchDirective, {useClass: MockSearchDirective}),
TestComponentBuilder,
provide(DataTransportService, {useClass: MockDataTransportService}),
]);
beforeEach( inject( [TestComponentBuilder], (_tcb : TestComponentBuilder) => {
this.searchDirective = new MockSearchDirective();
this._dataTransportService = new MockDataTransportService();
_tcb
.createAsync(TestAce)
.then( (fixture : ComponentFixture<TestAce>)=> {
console.log(fixture);
this.fixture = fixture;
});
}));
This console.log prints the correct fixture containing the Ace-Editor. But, in the specific test:
it('Check if editor will be initiated correctly', (done) => {
console.log(this.fixture);
// let testAce = this.fixture.componentInstance;
// let element = this.fixture.nativeElement;//.querySelector('div')
// let elementRef = this.fixture.elementRef;
//editor exists
expect(this.fixture.elementRef).toBeDefined();
done();
});
It fails. The console.log says, that this.fixture is undefined.
I also tried to inject the TextComponentBuilder in the test (and not via beforeEach):
it('Check if editor will be initiated correctly', inject( [TestComponentBuilder], (_tcb : TestComponentBuilder) => {
_tcb
.createAsync(TestAce)
.then( (fixture : ComponentFixture<TestAce>)=> {
console.log(fixture);
// let testAce = this.fixture.componentInstance;
// let element = this.fixture.nativeElement;//.querySelector('div')
// let elementRef = this.fixture.elementRef;
//editor exists
expect(fixture.elementRef).toBeDefined();
});
}));
but then I've got some timeout:
zone.js:461 Unhandled Promise rejection: 'expect' was used when there was no current spec, this could be because an asynchronous test timed out
Does anyone know this error? And how to deal with it?
Thanks!
Update
You still have to use the return-statement, like:
beforeEach( inject( [TestComponentBuilder], (_tcb : TestComponentBuilder) => {
this.searchDirective = new MockSearchDirective();
this._dataTransportService = new MockDataTransportService();
return _tcb
.createAsync(TestAce)
.then( (fixture : ComponentFixture<TestAce>)=> {
this.fixture = fixture;
});
}));