aboutsummaryrefslogtreecommitdiff
path: root/Timeline/ClientApp/src/app/user/internal-user-service/internal-user.service.spec.ts
blob: 15755382fa54babaaf5116a359647678453f3887 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { HttpRequest } from '@angular/common/http';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { Router } from '@angular/router';
import { MatSnackBar } from '@angular/material';

import { Mock } from 'src/app/test-utilities/mock';
import { createMockStorage } from 'src/app/test-utilities/storage.mock';
import { WINDOW } from '../window-inject-token';

import { UserInfo, UserCredentials } from '../entities';
import {
  createTokenUrl, validateTokenUrl, CreateTokenRequest,
  CreateTokenResponse, ValidateTokenRequest, ValidateTokenResponse
} from './http-entities';
import { InternalUserService, SnackBarTextKey, snackBarText, TOKEN_STORAGE_KEY } from './internal-user.service';
import { repeat } from 'src/app/utilities/language-untilities';


describe('InternalUserService', () => {
  let mockLocalStorage: Mock<Storage>;
  let mockSnackBar: jasmine.SpyObj<MatSnackBar>;

  beforeEach(() => {
    mockLocalStorage = createMockStorage();
    mockSnackBar = jasmine.createSpyObj('MatSnackBar', ['open']);
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        { provide: WINDOW, useValue: { localStorage: mockLocalStorage } },
        { provide: Router, useValue: null },
        { provide: MatSnackBar, useValue: mockSnackBar }
      ]
    });
  });

  it('should be created', () => {
    const service: InternalUserService = TestBed.get(InternalUserService);
    expect(service).toBeTruthy();
  });

  const mockUserInfo: UserInfo = {
    username: 'user',
    roles: ['user', 'other']
  };

  const mockToken = 'mock-token';

  describe('validate token', () => {
    const validateTokenRequestMatcher = (req: HttpRequest<ValidateTokenRequest>): boolean =>
      req.url === validateTokenUrl && req.body !== null && req.body.token === mockToken;

    function createTest(
      expectSnackBarTextKey: SnackBarTextKey,
      setStorageToken: boolean,
      setHttpController?: (controller: HttpTestingController) => void
    ): () => void {
      return fakeAsync(() => {
        if (setStorageToken) {
          mockLocalStorage.setItem(TOKEN_STORAGE_KEY, mockToken);
        }
        TestBed.get(InternalUserService);
        const controller = TestBed.get(HttpTestingController) as HttpTestingController;
        if (setHttpController) {
          setHttpController(controller);
        }
        controller.verify();
        tick();
        expect(mockSnackBar.open).toHaveBeenCalledWith(snackBarText[expectSnackBarTextKey], jasmine.anything(), jasmine.anything());
      });
    }

    it('no login should work well', createTest('noLogin', false));
    it('already login should work well', createTest('alreadyLogin', true,
      controller => controller.expectOne(validateTokenRequestMatcher).flush(
        <ValidateTokenResponse>{ isValid: true, userInfo: mockUserInfo })));
    it('invalid login should work well', createTest('invalidLogin', true,
      controller => controller.expectOne(validateTokenRequestMatcher).flush(<ValidateTokenResponse>{ isValid: false })));
    it('check fail should work well', createTest('checkFail', true,
      controller => repeat(4, () => {
        controller.expectOne(validateTokenRequestMatcher).error(new ErrorEvent('Network error', { message: 'simulated network error' }));
      })));
  });

  describe('login should work well', () => {
    const mockUserCredentials: UserCredentials = {
      username: 'user',
      password: 'user'
    };

    function createTest(rememberMe: boolean) {
      return () => {
        const service: InternalUserService = TestBed.get(InternalUserService);

        service.tryLogin({ ...mockUserCredentials, rememberMe: rememberMe }).subscribe(result => {
          expect(result).toEqual(mockUserInfo);
        });

        const httpController = TestBed.get(HttpTestingController) as HttpTestingController;

        httpController.expectOne((request: HttpRequest<CreateTokenRequest>) =>
          request.url === createTokenUrl && request.body !== null &&
          request.body.username === mockUserCredentials.username &&
          request.body.password === mockUserCredentials.password).flush(<CreateTokenResponse>{
            success: true,
            token: mockToken,
            userInfo: mockUserInfo
          });

        expect(service.currentUserInfo).toEqual(mockUserInfo);

        httpController.verify();

        expect(mockLocalStorage.getItem(TOKEN_STORAGE_KEY)).toBe(rememberMe ? mockToken : null);
      };
    }

    it('remember me should work well', createTest(true));
    it('not remember me should work well', createTest(false));
  });

  // TODO: test on error situations.
});