I am using Angular Universal. I have a guard for a route that behaves differently depending on if I am running on the server or the browser platform. Here is the guard:
export class UniversalShellGuard implements CanActivate {
private isBrowser: boolean;
constructor(@Inject(PLATFORM_ID) private platformId: Object) {
console.log('PLATFORM_ID = ' + platformId);
this.isBrowser = isPlatformBrowser(this.platformId);
}
canActivate(): Observable<boolean> | Promise<boolean> | boolean {
return !this.isBrowser;
}
}
As you can see, the guard is injecting PLATFORM_ID
and uses it to determine if he canActivate()
or not.
Now, I wanted to write a simple unit test for the guard and did the following:
describe('UniversalShellGuard', () => {
let guard: UniversalShellGuard;
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
UniversalShellGuard,
// Idea: for now I just want to test the behaviour if I would be on the browser, so I would just use a fixed value for PLATFORM_ID
{ provide: PLATFORM_ID, useValue: PLATFORM_BROWSER_ID },
],
});
guard = TestBed.get(UniversalShellGuard);
});
it('should deny', () => {
expect(guard.canActivate()).toBe(false);
});
});
But it gives the following error:
ERROR in ./src/app/universal-shell.guard.spec.ts
Module not found: Error: Can't resolve '@angular/common/src/platform_id' in '/my-app-path/src/app'
@ ./src/app/universal-shell.guard.spec.ts 4:0-70 11:50-69
@ ./src sync \.spec\.ts$
@ ./src/test.ts
I even tried a simple and straight forward construction of the guard, without using the angular TestBed
:
it('should deny', () => {
const guard = new UniversalShellGuard(PLATFORM_BROWSER_ID);
expect(guard.canActivate()).toBe(false);
});
Same error.
Is there any way to provide a fixed value for PLATFORM_ID
for properly unit-testing such a guard?
Introduction. Mocking is a great idea for testing Angular apps because it makes maintenance easier and helps reduce future bugs. There are a few complex tools, such as XUnit, for mocking an Angular CLI project. You can execute the mocking methods described in this guide only if you use vanilla Jasmine + Angular Testbed ...
isPlatformBrowserlink function. Returns whether a platform id represents a browser platform. isPlatformBrowser(platformId: Object): boolean.
The value PLATFORM_BROWSER_ID
is not part of the public API, that's why it's importing it from a deep path, this is not allowed. Instead you could just put 'browser'
:
{ provide: PLATFORM_ID, useValue: 'browser' },
For any other platform, you can use these values:
export const PLATFORM_BROWSER_ID = 'browser';
export const PLATFORM_SERVER_ID = 'server';
export const PLATFORM_WORKER_APP_ID = 'browserWorkerApp';
export const PLATFORM_WORKER_UI_ID = 'browserWorkerUi';
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With