Contenido del curso
Contenido del curso
Cesar Elías Armendariz Ruano
Ana Velez Ossa
Carlos Alejandro Hernández Mejía
Las pruebas a canActivate nos permitira ver como se ingresa a la ruta
Para poder hacer eso es necesario crear un archivo que simule fake Routes y fake states en nuestra carpeta testing
snapshot.ts
import { ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; export function fakeRouterStateSnapshot(options: Partial<RouterStateSnapshot>) { return options as RouterStateSnapshot; } export function fakeActivatedStateSnapshot(options: Partial<ActivatedRouteSnapshot>) { return options as ActivatedRouteSnapshot; }
para luego cargar esto en nuestro archivo de pruebas de guardianes
auth.guard.spec.ts
import { fakeActivatedStateSnapshot, fakeRouterStateSnapshot, mockObservable } from './../../testing'; import { generateOneUser } from '../models/user.mock'; it('should return true with session', (doneFn) => { const activatedRoute = fakeActivatedStateSnapshot({}); const routerState = fakeRouterStateSnapshot({}); const userMock = generateOneUser(); authService.getUser.and.returnValue(mockObservable(userMock)); guard.canActivate(activatedRoute, routerState) .subscribe(rta => { expect (rta).toBeTruthy(); doneFn(); }); }); it('should return true without session', (doneFn) => { const activatedRoute = fakeActivatedStateSnapshot({}); const routerState = fakeRouterStateSnapshot({}); authService.getUser.and.returnValue(mockObservable(null)); guard.canActivate(activatedRoute, routerState) .subscribe(rta => { expect (rta).toBeFalse(); expect (router.navigate).toHaveBeenCalledWith(['/home']); doneFn(); }); });
Al momento de realizar la prueba "should return true with session", estaba teniendo el siguiente problema con el .subscribe
Para solucionar el error de TypeScript, tuve que refactorizar el método canActivate para que siempre devuelva un Observable, ya que actualmente puede devolver un boolean o UrlTree directamente en algunas condiciones. De esta manera podemos usar en las pruebas el .suscribecanActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> { return this.authService.getUser().pipe( map(user => { if (!user) { this.router.navigate(['/home']); return this.router.createUrlTree(['/home']); } return true; }), catchError(() => { this.router.navigate(['/home']); return of(this.router.createUrlTree(['/home'])); }) ); }it('should return true with session', (doneFn) => { const activatedRoute = fakeActivatedStateSnapshot({}); const routerState = fakeRouterStateSnapshot({}); const userMock = generateOneUser(); authService.getUser.and.returnValue(mockObservable(userMock)); guard.canActivate(activatedRoute, routerState).subscribe((rta: boolean | UrlTree) => { expect(rta).toBeTrue(); doneFn(); }); });
Aca dejo el ajuste al código que realice en canActivate:
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> { return this.authService.getUser().pipe( map(user => { if (!user) { this.router.navigate(['/home']); return this.router.createUrlTree(['/home']); } return true; }), catchError(() => { this.router.navigate(['/home']); return of(this.router.createUrlTree(['/home'])); }) ); } ```Y asi quedaría la prueba: ```ts it('should return true with session', (doneFn) => { const activatedRoute = fakeActivatedStateSnapshot({}); const routerState = fakeRouterStateSnapshot({}); const userMock = generateOneUser(); authService.getUser.and.returnValue(mockObservable(userMock)); guard.canActivate(activatedRoute, routerState).subscribe((rta: boolean | UrlTree) => { expect(rta).toBeTrue(); doneFn(); }); });
Para poder hacer testing de propiedades en Jasmine, pueden hacer lo siguiente:
Definir las propiedades deseadas en el espía:
const authServiceSpyObj = jasmine.createSpyObj<AuthService>( 'AuthService', [// Mehods here], { user$: observableData(generateOneUser()), // Other properties with his value } );
Reemplazar el provider con nuestro espía:
TestBed.configureTestingModule({ providers: [ AuthGuard, { provide: AuthService, useValue: authServiceSpyObj, }, ], });
Inyectamos nuestro provider:
authServiceSpy = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
Definimos nuestras pruebas:
it('should return true if user is logged in', waitForAsync(() => { const route = fakeActivatedRouteSnapshot({}); const state = fakeRouterStateSnapshot({}); guard.canActivate(route, state).subscribe({ next: (value) => { expect(value).toBeTrue(); }, }); })); it("should return false if user isn't logged in", waitForAsync(() => { const route = fakeActivatedRouteSnapshot({}); const state = fakeRouterStateSnapshot({}); ( Object.getOwnPropertyDescriptor(authServiceSpy, 'user$')?.get as any ).and?.returnValue(observableData(null)); guard.canActivate(route, state).subscribe({ next: (value) => { expect(value).toBeTrue(); }, }); }));
Les dejo la documentación de Jasmine por si les interesa profundizar más. Espiando propiedades