aboutsummaryrefslogtreecommitdiff
path: root/Timeline/ClientApp/src
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-03-06 23:14:45 +0800
committercrupest <crupest@outlook.com>2019-03-06 23:14:45 +0800
commit83672dcdced6e0d42fa570d69c91417b3ea88b51 (patch)
tree6f35150c47f5c7fa1d2be3177d84e728ce6dcf71 /Timeline/ClientApp/src
parent61844a348b2934321567b1457e6d05f318fc8b7e (diff)
downloadtimeline-83672dcdced6e0d42fa570d69c91417b3ea88b51.tar.gz
timeline-83672dcdced6e0d42fa570d69c91417b3ea88b51.tar.bz2
timeline-83672dcdced6e0d42fa570d69c91417b3ea88b51.zip
Write all unit tests.
Diffstat (limited to 'Timeline/ClientApp/src')
-rw-r--r--Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.spec.ts101
-rw-r--r--Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html2
-rw-r--r--Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.spec.ts18
-rw-r--r--Timeline/ClientApp/src/app/user/user-login/user-login.component.spec.ts43
-rw-r--r--Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts108
5 files changed, 256 insertions, 16 deletions
diff --git a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.spec.ts b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.spec.ts
index 884a3710..d24c0cd2 100644
--- a/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.spec.ts
+++ b/Timeline/ClientApp/src/app/user/user-dialog/user-dialog.component.spec.ts
@@ -1,25 +1,114 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { Component, Output, EventEmitter } from '@angular/core';
+import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { of } from 'rxjs';
+import { delay } from 'rxjs/operators';
+import { UserInfo } from '../user-info';
import { UserDialogComponent } from './user-dialog.component';
+import { UserService, UserLoginState } from '../user-service/user.service';
+import { LoginEvent } from '../user-login/user-login.component';
-xdescribe('UserDialogComponent', () => {
+@Component({
+ /* tslint:disable-next-line:component-selector*/
+ selector: 'mat-progress-spinner',
+ template: ''
+})
+class MatProgressSpinnerStubComponent { }
+
+@Component({
+ selector: 'app-user-login',
+ /* tslint:disable-next-line:use-input-property-decorator*/
+ inputs: ['message'],
+ template: ''
+})
+class UserLoginStubComponent {
+ @Output()
+ login = new EventEmitter<LoginEvent>();
+}
+
+@Component({
+ selector: 'app-user-login-success',
+ /* tslint:disable-next-line:use-input-property-decorator*/
+ inputs: ['userInfo', 'displayLoginSuccessMessage'],
+ template: ''
+})
+class UserLoginSuccessStubComponent { }
+
+describe('UserDialogComponent', () => {
let component: UserDialogComponent;
let fixture: ComponentFixture<UserDialogComponent>;
+ let mockUserService: jasmine.SpyObj<UserService>;
beforeEach(async(() => {
+ mockUserService = jasmine.createSpyObj('UserService', ['validateUserLoginState', 'tryLogin']);
+
TestBed.configureTestingModule({
- declarations: [ UserDialogComponent ]
+ declarations: [UserDialogComponent, MatProgressSpinnerStubComponent,
+ UserLoginStubComponent, UserLoginSuccessStubComponent],
+ providers: [{ provide: UserService, useValue: mockUserService }]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserDialogComponent);
component = fixture.componentInstance;
+ });
+
+ it('progress spinner should work well', fakeAsync(() => {
+ mockUserService.validateUserLoginState.and.returnValue(of(<UserLoginState>{ state: 'nologin' }).pipe(delay(10)));
+ fixture.detectChanges();
+ expect(fixture.debugElement.query(By.css('mat-progress-spinner'))).toBeTruthy();
+ tick(10);
fixture.detectChanges();
+ expect(fixture.debugElement.query(By.css('mat-progress-spinner'))).toBeFalsy();
+ }));
+
+ it('nologin should work well', () => {
+ mockUserService.validateUserLoginState.and.returnValue(of(<UserLoginState>{ state: 'nologin' }));
+
+ fixture.detectChanges();
+
+ expect(mockUserService.validateUserLoginState).toHaveBeenCalled();
+ expect(fixture.debugElement.query(By.css('app-user-login'))).toBeTruthy();
+ expect(fixture.debugElement.query(By.css('app-user-login-success'))).toBeFalsy();
});
- it('should create', () => {
- expect(component).toBeTruthy();
+ it('success should work well', () => {
+ mockUserService.validateUserLoginState.and.returnValue(of(<UserLoginState>{ state: 'success', userInfo: {} }));
+
+ fixture.detectChanges();
+
+ expect(mockUserService.validateUserLoginState).toHaveBeenCalled();
+ expect(fixture.debugElement.query(By.css('app-user-login'))).toBeFalsy();
+ expect(fixture.debugElement.query(By.css('app-user-login-success'))).toBeTruthy();
+ });
+
+ it('login should work well', () => {
+ mockUserService.validateUserLoginState.and.returnValue(of(<UserLoginState>{ state: 'nologin' }));
+
+ fixture.detectChanges();
+ expect(mockUserService.validateUserLoginState).toHaveBeenCalled();
+ expect(fixture.debugElement.query(By.css('app-user-login'))).toBeTruthy();
+ expect(fixture.debugElement.query(By.css('app-user-login-success'))).toBeFalsy();
+
+ mockUserService.tryLogin.withArgs('user', 'user').and.returnValue(of(<UserInfo>{
+ username: 'user',
+ roles: ['user']
+ }));
+
+ (fixture.debugElement.query(By.css('app-user-login')).componentInstance as
+ UserLoginStubComponent).login.emit(<LoginEvent>{
+ username: 'user',
+ password: 'user'
+ });
+
+ fixture.detectChanges();
+
+ expect(mockUserService.tryLogin).toHaveBeenCalledWith('user', 'user');
+
+ expect(fixture.debugElement.query(By.css('app-user-login'))).toBeFalsy();
+ expect(fixture.debugElement.query(By.css('app-user-login-success'))).toBeTruthy();
});
});
diff --git a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
index 943c137f..e156f0f8 100644
--- a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
+++ b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.html
@@ -2,4 +2,4 @@
Login succeeds!
</p>
<p class="mat-body">You have been login as <span class="username">{{ userInfo.username }}</span>.</p>
-<p class="mat-body">Your roles are {{ userInfo.roles.join(', ') }}.</p>
+<p class="mat-body">Your roles are <span class="roles">{{ userInfo.roles.join(', ') }}</span>.</p>
diff --git a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.spec.ts b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.spec.ts
index bdcd354b..ba015ae6 100644
--- a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.spec.ts
+++ b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.spec.ts
@@ -1,25 +1,39 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserLoginSuccessComponent } from './user-login-success.component';
+import { By } from '@angular/platform-browser';
describe('UserLoginSuccessComponent', () => {
let component: UserLoginSuccessComponent;
let fixture: ComponentFixture<UserLoginSuccessComponent>;
+ const mockUserInfo = {
+ username: 'crupest',
+ roles: ['superman', 'coder']
+ };
+
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ UserLoginSuccessComponent ]
+ declarations: [UserLoginSuccessComponent]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserLoginSuccessComponent);
component = fixture.componentInstance;
+ component.userInfo = mockUserInfo;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should work well', () => {
+ expect((fixture.debugElement.query(By.css('span.username')).nativeElement as HTMLSpanElement).textContent)
+ .toBe(mockUserInfo.username);
+ expect((fixture.debugElement.query(By.css('span.roles')).nativeElement as HTMLSpanElement).textContent)
+ .toBe(mockUserInfo.roles.join(', '));
+ });
});
diff --git a/Timeline/ClientApp/src/app/user/user-login/user-login.component.spec.ts b/Timeline/ClientApp/src/app/user/user-login/user-login.component.spec.ts
index b606b7b4..acd13721 100644
--- a/Timeline/ClientApp/src/app/user/user-login/user-login.component.spec.ts
+++ b/Timeline/ClientApp/src/app/user/user-login/user-login.component.spec.ts
@@ -1,6 +1,9 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { NO_ERRORS_SCHEMA } from '@angular/core';
+import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
+import { ReactiveFormsModule } from '@angular/forms';
+import { By } from '@angular/platform-browser';
-import { UserLoginComponent } from './user-login.component';
+import { UserLoginComponent, LoginEvent } from './user-login.component';
describe('UserLoginComponent', () => {
let component: UserLoginComponent;
@@ -8,9 +11,11 @@ describe('UserLoginComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [ UserLoginComponent ]
+ declarations: [UserLoginComponent],
+ imports: [ReactiveFormsModule],
+ schemas: [NO_ERRORS_SCHEMA]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
@@ -22,4 +27,34 @@ describe('UserLoginComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('reactive form should work well', () => {
+ const usernameInput = fixture.debugElement.query(By.css('input[type=text]')).nativeElement as HTMLInputElement;
+ const passwordInput = fixture.debugElement.query(By.css('input[type=password]')).nativeElement as HTMLInputElement;
+
+ usernameInput.value = 'user';
+ usernameInput.dispatchEvent(new Event('input'));
+ passwordInput.value = 'user';
+ passwordInput.dispatchEvent(new Event('input'));
+
+ fixture.detectChanges();
+
+ expect(component.form.value).toEqual({
+ username: 'user',
+ password: 'user'
+ });
+ });
+
+ it('login event should work well', fakeAsync(() => {
+ let userCredential: LoginEvent;
+ component.login.subscribe((e: LoginEvent) => { userCredential = e; });
+ fixture.detectChanges();
+ const mockValue = {
+ username: 'user',
+ password: 'user'
+ };
+ component.form.setValue(mockValue);
+ component.onLoginButtonClick();
+ expect(userCredential).toEqual(mockValue);
+ }));
});
diff --git a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts b/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts
index b9221b90..28cfefd7 100644
--- a/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts
+++ b/Timeline/ClientApp/src/app/user/user-service/user.service.spec.ts
@@ -1,12 +1,114 @@
import { TestBed } from '@angular/core/testing';
+import { HttpRequest } from '@angular/common/http';
+import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
-import { UserService } from './user.service';
+import { UserInfo } from '../user-info';
+import {
+ UserService, UserCredentials, CreateTokenResult,
+ UserLoginState, TokenValidationRequest, TokenValidationResult
+} from './user.service';
-xdescribe('UserService', () => {
- beforeEach(() => TestBed.configureTestingModule({}));
+describe('UserService', () => {
+ const tokenCreateUrl = '/api/User/CreateToken';
+
+ beforeEach(() => TestBed.configureTestingModule({
+ imports: [HttpClientTestingModule]
+ }));
it('should be created', () => {
const service: UserService = TestBed.get(UserService);
expect(service).toBeTruthy();
});
+
+ it('should be nologin at first', () => {
+ const service: UserService = TestBed.get(UserService);
+ service.validateUserLoginState().subscribe(result => {
+ expect(result.state).toBe('nologin');
+ });
+ });
+
+ it('login should work well', () => {
+ const service: UserService = TestBed.get(UserService);
+
+ const mockUserInfo: UserInfo = {
+ username: 'user',
+ roles: ['user', 'other']
+ };
+
+ service.tryLogin('user', 'user').subscribe(result => {
+ expect(result).toEqual(mockUserInfo);
+ });
+
+ const httpController = TestBed.get(HttpTestingController) as HttpTestingController;
+
+ httpController.expectOne((request: HttpRequest<UserCredentials>) =>
+ request.url === tokenCreateUrl &&
+ request.body.username === 'user' &&
+ request.body.password === 'user').flush(<CreateTokenResult>{
+ token: 'test-token',
+ userInfo: mockUserInfo
+ });
+
+ httpController.verify();
+ });
+
+ describe('validateUserLoginState', () => {
+ let service: UserService;
+ let httpController: HttpTestingController;
+
+ const mockUserInfo: UserInfo = {
+ username: 'user',
+ roles: ['user', 'other']
+ };
+
+ const mockToken = 'mock-token';
+
+ const tokenValidateRequestMatcher = (req: HttpRequest<TokenValidationRequest>) => {
+ return req.url === '/api/User/ValidateToken' && req.body.token === mockToken;
+ }
+
+ beforeEach(() => {
+ service = TestBed.get(UserService);
+ httpController = TestBed.get(HttpTestingController);
+
+ service.tryLogin('user', 'user').subscribe(); // subscribe to activate login
+
+ httpController.expectOne(tokenCreateUrl).flush(<CreateTokenResult>{
+ token: mockToken,
+ userInfo: mockUserInfo
+ });
+ });
+
+ it('success should work well', () => {
+ service.validateUserLoginState().subscribe((result: UserLoginState) => {
+ expect(result).toEqual(<UserLoginState>{
+ state: 'success',
+ userInfo: mockUserInfo
+ });
+ });
+
+ httpController.expectOne(tokenValidateRequestMatcher).flush(<TokenValidationResult>{
+ isValid: true,
+ userInfo: mockUserInfo
+ });
+
+ httpController.verify();
+ });
+
+ it('invalid should work well', () => {
+ service.validateUserLoginState().subscribe((result: UserLoginState) => {
+ expect(result).toEqual(<UserLoginState>{
+ state: 'invalidlogin'
+ });
+ });
+
+ httpController.expectOne(tokenValidateRequestMatcher).flush(<TokenValidationResult>{
+ isValid: false
+ });
+
+ httpController.verify();
+ });
+ });
+
+ // TODO: test on error situations.
});