Skip to content
Snippets Groups Projects
auth.service.spec.ts 10.2 KiB
Newer Older
Giuseppe Digilio's avatar
Giuseppe Digilio committed
import { async, inject, TestBed } from '@angular/core/testing';
import { CommonModule } from '@angular/common';
import { ActivatedRoute, Router } from '@angular/router';

import { Store, StoreModule } from '@ngrx/store';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { of as observableOf } from 'rxjs';
Giuseppe Digilio's avatar
Giuseppe Digilio committed

import { authReducer, AuthState } from './auth.reducer';
import { NativeWindowRef, NativeWindowService } from '../services/window.service';
Giuseppe Digilio's avatar
Giuseppe Digilio committed
import { AuthService } from './auth.service';
import { RouterStub } from '../../shared/testing/router-stub';
import { ActivatedRouteStub } from '../../shared/testing/active-router-stub';

import { CookieService } from '../services/cookie.service';
Giuseppe Digilio's avatar
Giuseppe Digilio committed
import { AuthRequestServiceStub } from '../../shared/testing/auth-request-service-stub';
import { AuthRequestService } from './auth-request.service';
import { AuthStatus } from './models/auth-status.model';
import { AuthTokenInfo } from './models/auth-token-info.model';
lotte's avatar
lotte committed
import { EPerson } from '../eperson/models/eperson.model';
import { EPersonMock } from '../../shared/testing/eperson-mock';
Giuseppe Digilio's avatar
Giuseppe Digilio committed
import { AppState } from '../../app.reducer';
import { ClientCookieService } from '../services/client-cookie.service';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { getMockRemoteDataBuildService } from '../../shared/mocks/mock-remote-data-build.service';
import { routeServiceStub } from '../../shared/testing/route-service-stub';
import { RouteService } from '../services/route.service';
Giuseppe Digilio's avatar
Giuseppe Digilio committed

describe('AuthService test', () => {

lotte's avatar
lotte committed
  let mockStore: Store<AuthState>;
Giuseppe Digilio's avatar
Giuseppe Digilio committed
  let authService: AuthService;
lotte's avatar
lotte committed
  let authRequest;
lotte's avatar
lotte committed
  let window;
  let routerStub;
lotte's avatar
lotte committed
  let routeStub;
Giuseppe Digilio's avatar
Giuseppe Digilio committed
  let storage: CookieService;
lotte's avatar
lotte committed
  let token: AuthTokenInfo;
  let authenticatedState;
lotte's avatar
lotte committed
  let rdbService;
Giuseppe Digilio's avatar
Giuseppe Digilio committed

lotte's avatar
lotte committed
  function init() {
lotte's avatar
lotte committed
    mockStore = jasmine.createSpyObj('store', {
      dispatch: {},
      pipe: observableOf(true)
    });
    window = new NativeWindowRef();
lotte's avatar
lotte committed
    token = new AuthTokenInfo('test_token');
    token.expires = Date.now() + (1000 * 60 * 60);
    authenticatedState = {
      authenticated: true,
      loaded: true,
      loading: false,
      authToken: token,
      user: EPersonMock
    };
    authRequest = new AuthRequestServiceStub();
    routeStub = new ActivatedRouteStub();
lotte's avatar
lotte committed
    rdbService = getMockRemoteDataBuildService();
    spyOn(rdbService, 'build').and.returnValue({authenticated: true, eperson: observableOf({payload: {}})});
lotte's avatar
lotte committed

lotte's avatar
lotte committed
  }
lotte's avatar
lotte committed

  describe('', () => {
Giuseppe Digilio's avatar
Giuseppe Digilio committed
    beforeEach(() => {
lotte's avatar
lotte committed
      init();
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      TestBed.configureTestingModule({
        imports: [
          CommonModule,
lotte's avatar
lotte committed
          StoreModule.forRoot({ authReducer }),
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        ],
        declarations: [],
        providers: [
lotte's avatar
lotte committed
          { provide: AuthRequestService, useValue: authRequest },
          { provide: NativeWindowService, useValue: window },
          { provide: REQUEST, useValue: {} },
          { provide: Router, useValue: routerStub },
          { provide: RouteService, useValue: routeServiceStub },
lotte's avatar
lotte committed
          { provide: ActivatedRoute, useValue: routeStub },
Giuseppe Digilio's avatar
Giuseppe Digilio committed
          { provide: Store, useValue: mockStore },
lotte's avatar
lotte committed
          { provide: RemoteDataBuildService, useValue: rdbService },
Giuseppe Digilio's avatar
Giuseppe Digilio committed
          CookieService,
          AuthService
        ],
      });
      authService = TestBed.get(AuthService);
    });

    it('should return the authentication status object when user credentials are correct', () => {
      authService.authenticate('user', 'password').subscribe((status: AuthStatus) => {
        expect(status).toBeDefined();
      });
    });

    it('should throw an error when user credentials are wrong', () => {
      expect(authService.authenticate.bind(null, 'user', 'passwordwrong')).toThrow();
    });

    it('should return the authenticated user object when user token is valid', () => {
lotte's avatar
lotte committed
      authService.authenticatedUser(new AuthTokenInfo('test_token')).subscribe((user: EPerson) => {
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        expect(user).toBeDefined();
      });
    });

    it('should throw an error when user credentials when user token is not valid', () => {
      expect(authService.authenticatedUser.bind(null, new AuthTokenInfo('test_token_expired'))).toThrow();
    });

    it('should return a valid refreshed token', () => {
      authService.refreshAuthenticationToken(new AuthTokenInfo('test_token')).subscribe((tokenState: AuthTokenInfo) => {
        expect(tokenState).toBeDefined();
      });
    });

    it('should throw an error when is not possible to refresh token', () => {
      expect(authService.refreshAuthenticationToken.bind(null, new AuthTokenInfo('test_token_expired'))).toThrow();
    });

    it('should return true when logout succeeded', () => {
      authService.logout().subscribe((status: boolean) => {
        expect(status).toBe(true);
      });
    });

    it('should throw an error when logout is not succeeded', () => {
      expect(authService.logout.bind(null)).toThrow();
    });

  });

  describe('', () => {

    beforeEach(async(() => {
lotte's avatar
lotte committed
      init();
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      TestBed.configureTestingModule({
        imports: [
lotte's avatar
lotte committed
          StoreModule.forRoot({ authReducer })
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        ],
        providers: [
lotte's avatar
lotte committed
          { provide: AuthRequestService, useValue: authRequest },
          { provide: REQUEST, useValue: {} },
          { provide: Router, useValue: routerStub },
          { provide: RouteService, useValue: routeServiceStub },
lotte's avatar
lotte committed
          { provide: RemoteDataBuildService, useValue: rdbService },
lotte's avatar
lotte committed
          CookieService,
          AuthService
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        ]
      }).compileComponents();
    }));

    beforeEach(inject([CookieService, AuthRequestService, Store, Router, RouteService], (cookieService: CookieService, authReqService: AuthRequestService, store: Store<AppState>, router: Router, routeService: RouteService) => {
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      store
        .subscribe((state) => {
          (state as any).core = Object.create({});
          (state as any).core.auth = authenticatedState;
        });
      authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, rdbService);
Giuseppe Digilio's avatar
Giuseppe Digilio committed
    }));

    it('should return true when user is logged in', () => {
      authService.isAuthenticated().subscribe((status: boolean) => {
        expect(status).toBe(true);
      });
    });

    it('should return token object when it is valid', () => {
      authService.hasValidAuthenticationToken().subscribe((tokenState: AuthTokenInfo) => {
        expect(tokenState).toBe(token);
      });
    });

    it('should return a token object', () => {
      const result = authService.getToken();
      expect(result).toBe(token);
    });

    it('should return false when token is not expired', () => {
      const result = authService.isTokenExpired();
      expect(result).toBe(false);
    });

  });

  describe('', () => {
    beforeEach(async(() => {
lotte's avatar
lotte committed
      init();
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      TestBed.configureTestingModule({
        imports: [
lotte's avatar
lotte committed
          StoreModule.forRoot({ authReducer })
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        ],
        providers: [
lotte's avatar
lotte committed
          { provide: AuthRequestService, useValue: authRequest },
          { provide: REQUEST, useValue: {} },
          { provide: Router, useValue: routerStub },
          { provide: RouteService, useValue: routeServiceStub },
lotte's avatar
lotte committed
          { provide: RemoteDataBuildService, useValue: rdbService },
Giuseppe Digilio's avatar
Giuseppe Digilio committed
          ClientCookieService,
lotte's avatar
lotte committed
          CookieService,
          AuthService
Giuseppe Digilio's avatar
Giuseppe Digilio committed
        ]
      }).compileComponents();
    }));

    beforeEach(inject([ClientCookieService, AuthRequestService, Store, Router, RouteService], (cookieService: ClientCookieService, authReqService: AuthRequestService, store: Store<AppState>, router: Router, routeService: RouteService) => {
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      const expiredToken: AuthTokenInfo = new AuthTokenInfo('test_token');
      expiredToken.expires = Date.now() - (1000 * 60 * 60);
      authenticatedState = {
        authenticated: true,
        loaded: true,
        loading: false,
        authToken: expiredToken,
lotte's avatar
lotte committed
        user: EPersonMock
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      };
      store
        .subscribe((state) => {
          (state as any).core = Object.create({});
          (state as any).core.auth = authenticatedState;
        });
      authService = new AuthService({}, window, undefined, authReqService, router, routeService, cookieService, store, rdbService);
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      storage = (authService as any).storage;
      routeServiceMock = TestBed.get(RouteService);
      routerStub = TestBed.get(Router);
Giuseppe Digilio's avatar
Giuseppe Digilio committed
      spyOn(storage, 'get');
      spyOn(storage, 'remove');
      spyOn(storage, 'set');
Giuseppe Digilio's avatar
Giuseppe Digilio committed
    }));

    it('should throw false when token is not valid', () => {
      expect(authService.hasValidAuthenticationToken.bind(null)).toThrow();
    });

    it('should return true when token is expired', () => {
      const result = authService.isTokenExpired();
      expect(result).toBe(true);
    });

    it('should save token into storage', () => {
      authService.storeToken(token);
      expect(storage.set).toHaveBeenCalled();
    });

    it('should remove token from storage', () => {
      authService.removeToken();
      expect(storage.remove).toHaveBeenCalled();
    });

    it ('should set redirect url to previous page', () => {
      spyOn(routeServiceMock, 'getHistory').and.callThrough();
Michael W Spalti's avatar
Michael W Spalti committed
      authService.redirectAfterLoginSuccess(true);
      expect(routeServiceMock.getHistory).toHaveBeenCalled();
      expect(routerStub.navigate).toHaveBeenCalledWith(['/collection/123']);
    });

    it ('should set redirect url to current page', () => {
      spyOn(routeServiceMock, 'getHistory').and.callThrough();
Michael W Spalti's avatar
Michael W Spalti committed
      authService.redirectAfterLoginSuccess(false);
      expect(routeServiceMock.getHistory).toHaveBeenCalled();
      expect(routerStub.navigate).toHaveBeenCalledWith(['/home']);
    });

    it ('should redirect to / and not to /login', () => {
      spyOn(routeServiceMock, 'getHistory').and.returnValue(observableOf(['/login', '/login']));
Michael W Spalti's avatar
Michael W Spalti committed
      authService.redirectAfterLoginSuccess(true);
      expect(routeServiceMock.getHistory).toHaveBeenCalled();
      expect(routerStub.navigate).toHaveBeenCalledWith(['/']);
    });

    it ('should redirect to / when no redirect url is found', () => {
      spyOn(routeServiceMock, 'getHistory').and.returnValue(observableOf(['']));
Michael W Spalti's avatar
Michael W Spalti committed
      authService.redirectAfterLoginSuccess(true);
      expect(routeServiceMock.getHistory).toHaveBeenCalled();
      expect(routerStub.navigate).toHaveBeenCalledWith(['/']);
    });
Giuseppe Digilio's avatar
Giuseppe Digilio committed
  });
});