Angular - How to test Guards with ActivatedRouteSnapshot RouterStateSnapshot and GlobalState
Answer a question I'm creating unit test for my Angular app but i don'k know create tests for my custom guard that use Redux. This is my code of the guard import { Injectable } from '@angular/core'; i
·
Answer a question
I'm creating unit test for my Angular app but i don'k know create tests for my custom guard that use Redux.
This is my code of the guard
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot, UrlSegment, UrlTree } from '@angular/router';
import { first, map, Observable, tap } from 'rxjs';
import { GlobalState } from '../state/app.reducer';
import { Store } from '@ngrx/store';
import { RolesAccount } from 'src/app/pages/auth/interfaces/auth.constant';
@Injectable({
providedIn: 'root'
})
export class AdministratorGuard implements CanActivate, CanLoad {
constructor(private route: Router,private store: Store<GlobalState>) {}
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.isAdmin()
}
canLoad( route: Route, segments: UrlSegment[]): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.isAdmin()
}
isAdmin():Observable<true | UrlTree>{
return this.store.select('authentication').pipe(
first(), // take of first value
map(userStore => userStore.userLogged?.role || ''),
//TODO we hardcode the email of administrator until role is in JWT
map(role => role === RolesAccount.ADMIN ? true : this.route.createUrlTree(['/home']))
);
}
}
I run npm run coverage
And this is the uncovered block (I need create unit test for canActivate, canLoad, and isAdmin
Uncovered block
And this is my unit testing file (default testing)
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { AuthComponent } from 'src/app/pages/auth/auth.component';
import { IUserState } from 'src/app/pages/auth/interfaces/auth.interfaces';
import { AdministratorGuard } from '../administrator.guard';
fdescribe('AdministratorGuard', () => {
let guard: AdministratorGuard;
let store: MockStore<IUserState>;
beforeEach(() => {
TestBed.configureTestingModule({
imports:[
RouterTestingModule.withRoutes(
[
{
path: 'auth',
component: AuthComponent
},
]
),
],
providers:[
provideMockStore({}),
]
});
guard = TestBed.inject(AdministratorGuard);
store = TestBed.inject(MockStore);
});
it('should be created', () => {
expect(guard).toBeTruthy();
});
});
Thanks in advance
Answers
Thanks Wesley for your comment. Here's the solution
This is my code of guard
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot, UrlSegment, UrlTree } from '@angular/router';
import { first, map, Observable, tap } from 'rxjs';
import { GlobalState } from '../state/app.reducer';
import { Store } from '@ngrx/store';
import { RolesAccount } from 'src/app/pages/auth/interfaces/auth.constant';
@Injectable({
providedIn: 'root'
})
export class AdministratorGuard implements CanActivate, CanLoad {
constructor(private route: Router,private store: Store<GlobalState>) {}
canActivate(): Observable<true | UrlTree> {
return this.isAdmin()
}
canLoad(): Observable<true | UrlTree>{
return this.isAdmin()
}
isAdmin():Observable<true | UrlTree>{
return this.store.select('authentication').pipe(
first(), // take of first value
map(userStore => userStore?.userLogged?.role || ''),
//TODO we hardcode the email of administrator until role is in JWT
map(role => role === RolesAccount.ADMIN ? true : this.route.createUrlTree(['/home']))
);
}
}
And this is the test
import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot, Router, RouterStateSnapshot } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { lastValueFrom, of } from 'rxjs';
import { AuthComponent } from 'src/app/pages/auth/auth.component';
import { RolesAccount } from 'src/app/pages/auth/interfaces/auth.constant';
import { IUserState } from 'src/app/pages/auth/interfaces/auth.interfaces';
import { AdministratorGuard } from '../administrator.guard';
describe('AdministratorGuard', () => {
let guard: AdministratorGuard;
let store: MockStore<IUserState>;
let defaultState:IUserState = {
authentication:{
userLogged:{
name:'',
email:'',
phone:'',
accessToken:'',
refreshToken:'',
role: RolesAccount.USER
},
}
}
beforeEach(() => {
const routerStub = {
events: of('/'),
createUrlTree: (commands: any, navExtras = {}) => {}
};
TestBed.configureTestingModule({
imports:[
RouterTestingModule.withRoutes(
[
{
path: 'auth',
component: AuthComponent
},
]
),
],
providers:[
provideMockStore({
initialState:defaultState
}),
{ provide: Router, useValue: routerStub}
]
});
guard = TestBed.inject(AdministratorGuard);
store = TestBed.inject(MockStore);
});
it('should be created', () => {
expect(guard).toBeTruthy();
});
it('can Activate to be True ', () => {
const storeSpy = spyOn(store, 'select').and.callThrough();
guard.canActivate()
expect(storeSpy).toHaveBeenCalledTimes(1);
});
it('can canLoad to be True ', () => {
const storeSpy = spyOn(store, 'select').and.callThrough();
guard.canLoad()
expect(storeSpy).toHaveBeenCalledTimes(1);
})
it('validate role ADMIN',async () => {
const nextState:IUserState = {
authentication:{
userLogged:{
name:'Test',
email:'mailTest@gmail.com',
phone:'+5411557788',
accessToken:'asfksakmfaskmfsakm',
refreshToken:'safla25l4235lllfs',
role: RolesAccount.ADMIN
},
}
}
store.setState(nextState);
const isAdmin = await lastValueFrom(guard.isAdmin())
expect(isAdmin).toBeTrue()
})
it('if is not admin,navigate home',async () => {
const nextState:IUserState = {
authentication:null
}
store.setState(nextState);
const isAdmin = await lastValueFrom(guard.isAdmin())
expect(isAdmin).toBeUndefined()
})
});
更多推荐
目录
所有评论(0)