How can I test canActivate
function of angular that returns a function which in turn returns a boolean
value?.
I tried creating objects of ActivatedrouterSnapshot
and routerStateSnapshot
and passing it to canActivate
function but that didn't help.
export class AuthGuard implements CanActivate {
constructor(
private authService: AuthenticationService,
private loginService: LoginService,
private router: Router
) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
return this.checkLogin(state.url);
}
checkLogin(url: string): boolean {
if (this.authService.isLoggedIn()) { return true; }
// Store the attempted URL for redirecting
this.loginService.redirectUrl = url;
// Navigate to the login page with extras
this.router.navigate(['/login']);
return false;
}
}
Since the checklogin
returns true
,I want that to happen. But I don't know where to start?.
There are a lot of ways to do this. I would suggest something like the following. Just to show some variety I mocked one service with a class and another service with a spyObject.
Here is the suggested code:
class LoginMock implements Partial<LoginService> {
redirectUrl: string;
}
describe('AuthGuard', () => {
let authGuard: AuthGuard;
let loginService: LoginMock;
const routerMock = jasmine.createSpyObj('Router', ['navigate']);
const authMock = jasmine.createSpyObj('AuthenticationService', ['isLoggedIn']);
beforeEach(() => {
loginService = new LoginMock();
authGuard = new AuthGuard(authMock, loginService, routerMock);
});
it('should be createable', () => expect(authGuard).toBeTruthy());
it('should return true for canActivate() and not set loginService.redirectUrl when isLoggedIn === true', ()=> {
authMock.isLoggedIn.and.returnValue(true);
const result = authGuard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});
expect(result).toBe(true);
expect(loginService.redirectUrl).toBeUndefined();
});
it('should return false for canActivate() and set loginService.redirectUrl when isLoggedIn === false', ()=> {
authMock.isLoggedIn.and.returnValue(false);
const result = authGuard.canActivate(new ActivatedRouteSnapshot(), <RouterStateSnapshot>{url: 'testUrl'});
expect(result).toBe(false);
expect(loginService.redirectUrl).toEqual('testUrl');
});
});
I have put this together in a Stackblitz for you. Feel free to fork that into your own Stackblitz environment and modify.
Best of luck. :)