Reputation: 6852
I have some guard like this guard.ts that just show error if webGl is disabled
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { NotificationService } from '../notification.service';
@Injectable()
export class WebGlGuard implements CanActivate {
text: string;
title: string;
webGl: WebGL2RenderingContext;
constructor(
private translate: TranslateService,
private notificationService: NotificationService) { }
canActivate(): boolean {
this.webGl = document.createElement('canvas').getContext('webgl2');
this.translate.get('Notification.Status.NoWebGl').subscribe((message: string) => {
this.title = this.translate.instant(message);
this.text = this.translate.instant('Notification.Message.NoWebGl');
if (!this.webGl) {
this.notificationService.error(this.text, this.title);
}
});
return true;
}
}
And I need to unit test that guard.spec.ts like this
import { TestBed, async } from '@angular/core/testing';
import { TranslateService } from '@ngx-translate/core';
import {
testingModule
} from '../utils/mocks';
import { WebGlGuard } from './web-gl.guard';
import { NotificationService } from '../notification.service';
let webGlGuard: WebGlGuard;
let notificationService: NotificationService;
let translateService: TranslateService;
// let spy: jasmine.Spy;
describe('WebGlGuard', () => {
beforeEach(async(() => {
const imports = testingModule.imports();
TestBed.configureTestingModule({
imports: [
imports
],
providers: [
WebGlGuard,
WebGL2RenderingContext,
NotificationService,
TranslateService
]
})
.compileComponents();
}));
beforeEach(() => {
webGlGuard = TestBed.inject(WebGlGuard);
notificationService = TestBed.inject(NotificationService);
translateService = TestBed.inject(TranslateService);
});
it('should show notification message if Web Gl is disabled', () => {
// GIVEN
const notification = spyOn(notificationService, 'error').and.callThrough();
const translate = spyOn(translateService, 'get').and.callThrough();
webGlGuard.webGl = null;
// WHEN
webGlGuard.canActivate();
// THEN
expect(translate).toHaveBeenCalled();
expect(notification).toHaveBeenCalledTimes(1);
});
it('should show notification message if Web Gl is not disabled', () => {
// GIVEN
const notification = spyOn(notificationService, 'error').and.callThrough();
const translate = spyOn(translateService, 'get').and.callThrough();
webGlGuard.webGl = new WebGL2RenderingContext();
// WHEN
// THEN
webGlGuard.canActivate();
expect(translate).toHaveBeenCalled();
expect(notification).toHaveBeenCalledTimes(0);
});
});
But all test fails liek this Expected spy error to have been called once. It was called 0 times. and the second like this TypeError: Illegal constructor
Does somebody knows how to unit test webGl guard, thanks
Upvotes: 0
Views: 206
Reputation: 18809
Your guard will always be returning true
and the whole point of a guard is to allow and not allow access. I think you can move this code into a service
and run it from there.
Check out the comments in both snippets, it should help I think.
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
import { NotificationService } from '../notification.service';
@Injectable()
export class WebGlGuard implements CanActivate {
text: string;
title: string;
webGl: WebGL2RenderingContext;
constructor(
private translate: TranslateService,
private notificationService: NotificationService) {
// !! move this line into the constructor so we can change it after
// this guard is constructed in the unit test !!
this.webGl = document.createElement('canvas').getContext('webgl2');
}
canActivate(): boolean {
this.translate.get('Notification.Status.NoWebGl').subscribe((message: string) => {
this.title = this.translate.instant(message);
this.text = this.translate.instant('Notification.Message.NoWebGl');
if (!this.webGl) {
this.notificationService.error(this.text, this.title);
}
});
return true;
}
}
import { TestBed, async } from '@angular/core/testing';
import { TranslateService } from '@ngx-translate/core';
import {
testingModule
} from '../utils/mocks';
import { WebGlGuard } from './web-gl.guard';
import { NotificationService } from '../notification.service';
let webGlGuard: WebGlGuard;
let notificationService: NotificationService;
let translateService: TranslateService;
// let spy: jasmine.Spy;
describe('WebGlGuard', () => {
beforeEach(async(() => {
const imports = testingModule.imports();
TestBed.configureTestingModule({
imports: [
imports
],
providers: [
WebGlGuard,
WebGL2RenderingContext,
NotificationService,
TranslateService
]
})
.compileComponents();
}));
beforeEach(() => {
webGlGuard = TestBed.inject(WebGlGuard);
notificationService = TestBed.inject(NotificationService);
translateService = TestBed.inject(TranslateService);
});
it('should show notification message if Web Gl is disabled', () => {
// GIVEN
// !! Don't call through, we don't need it
const notification = spyOn(notificationService, 'error');
// !! Change this line
const translate = spyOn(translateService, 'get').and.returnValue(of('Hello world'));
webGlGuard.webGl = null;
// WHEN
webGlGuard.canActivate();
// THEN
expect(translate).toHaveBeenCalled();
expect(notification).toHaveBeenCalledTimes(1);
});
it('should show notification message if Web Gl is not disabled', () => {
// GIVEN
// !! Don't call through, we don't need it
const notification = spyOn(notificationService, 'error');
// !! Change this line
const translate = spyOn(translateService, 'get').and.returnValue(of('Hello world'));
webGlGuard.webGl = new WebGL2RenderingContext();
// WHEN
// THEN
webGlGuard.canActivate();
expect(translate).toHaveBeenCalled();
expect(notification).toHaveBeenCalledTimes(0);
});
});
I am not sure how to fix illegal
constructor. I am thinking we can't do webGlGuard.webGl = null
. Maybe try = undefined
.
Upvotes: 0