From 110f2ab8d7bf5cf5fefee2fadb89f0e548dc0f4d Mon Sep 17 00:00:00 2001
From: crupest
Date: Mon, 18 Mar 2019 21:21:56 +0800
Subject: Add logout. Fix a bug. The bug is it always goes to login page
whether you have login or not before when user is presented in url.
---
.../src/app/user/user-login-success/user-login-success.component.html | 1 +
1 file changed, 1 insertion(+)
(limited to 'Timeline/ClientApp/src/app/user/user-login-success')
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 e156f0f8..8599a91d 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
@@ -3,3 +3,4 @@
You have been login as {{ userInfo.username }}.
Your roles are {{ userInfo.roles.join(', ') }}.
+Logout
--
cgit v1.2.3
From eeba297d0764a7d9862e1bd84dc85f23528159c7 Mon Sep 17 00:00:00 2001
From: crupest
Date: Mon, 18 Mar 2019 21:47:19 +0800
Subject: Design login success UI.
---
.../user-login-success/user-login-success.component.css | 15 +++++++++++++++
.../user-login-success/user-login-success.component.html | 2 +-
2 files changed, 16 insertions(+), 1 deletion(-)
(limited to 'Timeline/ClientApp/src/app/user/user-login-success')
diff --git a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.css b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.css
index 6486142b..b1101e2a 100644
--- a/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.css
+++ b/Timeline/ClientApp/src/app/user/user-login-success/user-login-success.component.css
@@ -5,3 +5,18 @@
.username {
color: blue;
}
+
+:host {
+ display: flex;
+ flex-wrap: wrap;
+}
+
+:host p {
+ margin-top: 0.3em;
+ margin-bottom: 0.3em;
+ width: 100%;
+}
+
+.logout-button {
+ margin-left: auto;
+}
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 8599a91d..685f6299 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
@@ -3,4 +3,4 @@
You have been login as {{ userInfo.username }}.
Your roles are {{ userInfo.roles.join(', ') }}.
-Logout
+Logout
--
cgit v1.2.3
From e436cf9ebb4776e3c837f1b0935f3ea2bf254d79 Mon Sep 17 00:00:00 2001
From: crupest
Date: Tue, 26 Mar 2019 19:21:31 +0800
Subject: Add unit test.
---
.../src/app/test-utilities/router-link.mock.ts | 9 +++++++
Timeline/ClientApp/src/app/user/auth.guard.spec.ts | 30 ++++++++++++++--------
.../user-login-success.component.spec.ts | 12 +++++++--
.../user/user-logout/user-logout.component.html | 2 +-
.../user/user-logout/user-logout.component.spec.ts | 16 +++++++++---
.../app/user/user-logout/user-logout.component.ts | 3 +--
6 files changed, 53 insertions(+), 19 deletions(-)
create mode 100644 Timeline/ClientApp/src/app/test-utilities/router-link.mock.ts
(limited to 'Timeline/ClientApp/src/app/user/user-login-success')
diff --git a/Timeline/ClientApp/src/app/test-utilities/router-link.mock.ts b/Timeline/ClientApp/src/app/test-utilities/router-link.mock.ts
new file mode 100644
index 00000000..7f4cde4d
--- /dev/null
+++ b/Timeline/ClientApp/src/app/test-utilities/router-link.mock.ts
@@ -0,0 +1,9 @@
+import { Directive, Input } from '@angular/core';
+
+@Directive({
+ /* tslint:disable-next-line:directive-selector*/
+ selector: '[routerLink]'
+})
+export class RouterLinkStubDirective {
+ @Input('routerLink') linkParams: any;
+}
diff --git a/Timeline/ClientApp/src/app/user/auth.guard.spec.ts b/Timeline/ClientApp/src/app/user/auth.guard.spec.ts
index 42e35bf7..6a36fea6 100644
--- a/Timeline/ClientApp/src/app/user/auth.guard.spec.ts
+++ b/Timeline/ClientApp/src/app/user/auth.guard.spec.ts
@@ -1,3 +1,5 @@
+import { Observable, of } from 'rxjs';
+
import { AuthGuard, AuthStrategy } from './auth.guard';
import { UserInfo } from './entities';
@@ -8,10 +10,9 @@ describe('AuthGuard', () => {
}
authStrategy: AuthStrategy = 'all';
- onAuthFailed: () => void = () => { };
}
- let mockUserService: { currentUserInfo: UserInfo | null };
+ let mockUserService: { userInfo$: Observable };
let guard: ConfiurableAuthGuard;
let onAuthFialedSpy: jasmine.Spy;
@@ -28,19 +29,27 @@ describe('AuthGuard', () => {
return () => {
guard.authStrategy = authStrategy;
- mockUserService.currentUserInfo = null;
- expect(guard.canActivate(null, null)).toBe(result.nologin);
+ function testWith(userInfo: UserInfo | null, r: boolean) {
+ mockUserService.userInfo$ = of(userInfo);
- mockUserService.currentUserInfo = { username: 'user', roles: [] };
- expect(guard.canActivate(null, null)).toBe(result.loginWithNoRole);
+ const rawResult = guard.canActivate(null, null);
+ if (typeof rawResult === 'boolean') {
+ expect(rawResult).toBe(r);
+ } else if (rawResult instanceof Observable) {
+ rawResult.subscribe(next => expect(next).toBe(r));
+ } else {
+ throw new Error('Unsupported return type.');
+ }
+ }
- mockUserService.currentUserInfo = { username: 'user', roles: mockRoles };
- expect(guard.canActivate(null, null)).toBe(result.loginWithMockRoles);
+ testWith(null, result.nologin);
+ testWith({ username: 'user', roles: [] }, result.loginWithNoRole);
+ testWith({ username: 'user', roles: mockRoles }, result.loginWithMockRoles);
};
}
beforeEach(() => {
- mockUserService = { currentUserInfo: null };
+ mockUserService = { userInfo$: of(null) };
guard = new ConfiurableAuthGuard(mockUserService);
onAuthFialedSpy = spyOn(guard, 'onAuthFailed');
});
@@ -54,8 +63,7 @@ describe('AuthGuard', () => {
it('auth failed callback should be called', () => {
guard.authStrategy = 'requirelogin';
- mockUserService.currentUserInfo = null;
- guard.canActivate(null, null);
+ (>guard.canActivate(null, null)).subscribe();
expect(onAuthFialedSpy).toHaveBeenCalled();
});
});
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 ff253add..3eba2696 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
@@ -2,7 +2,8 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { ActivatedRoute } from '@angular/router';
-import { MockActivatedRoute } from 'src/app/test-utilities/activated-route.mock';
+import { RouterLinkStubDirective } from '../../test-utilities/router-link.mock';
+import { MockActivatedRoute } from '../../test-utilities/activated-route.mock';
import { createMockInternalUserService } from '../internal-user-service/internal-user.service.mock';
import { UserLoginSuccessComponent } from './user-login-success.component';
@@ -29,7 +30,7 @@ describe('UserLoginSuccessComponent', () => {
(mockInternalUserService).currentUserInfo = mockUserInfo;
TestBed.configureTestingModule({
- declarations: [UserLoginSuccessComponent],
+ declarations: [UserLoginSuccessComponent, RouterLinkStubDirective],
providers: [
{ provide: InternalUserService, useValue: mockInternalUserService },
{ provide: ActivatedRoute, useValue: mockActivatedRoute }
@@ -64,4 +65,11 @@ describe('UserLoginSuccessComponent', () => {
fixture.detectChanges();
expect((fixture.debugElement.query(By.css('p.login-success-message')))).toBeTruthy();
});
+
+ it('logout button should be set well', () => {
+ fixture.detectChanges();
+ const routerLinkDirective: RouterLinkStubDirective =
+ fixture.debugElement.query(By.css('a')).injector.get(RouterLinkStubDirective);
+ expect(routerLinkDirective.linkParams).toEqual(['..', 'logout']);
+ });
});
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html
index 56d96b83..309e5c83 100644
--- a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.html
@@ -1 +1 @@
-Log out succeeded!
+Logout successfully!
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts
index 91369e01..855ea4a1 100644
--- a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.spec.ts
@@ -1,25 +1,35 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { UserLogoutComponent } from './user-logout.component';
+import { InternalUserService } from '../internal-user-service/internal-user.service';
describe('UserLogoutComponent', () => {
let component: UserLogoutComponent;
let fixture: ComponentFixture;
+ let mockInternalUserService: jasmine.SpyObj;
+
beforeEach(async(() => {
+ mockInternalUserService = jasmine.createSpyObj('InternalUserService', ['logout']);
+
TestBed.configureTestingModule({
- declarations: [ UserLogoutComponent ]
+ declarations: [UserLogoutComponent],
+ providers: [{ provide: InternalUserService, useValue: mockInternalUserService }]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserLogoutComponent);
component = fixture.componentInstance;
- fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ it('should logout on init', () => {
+ fixture.detectChanges();
+ expect(mockInternalUserService.logout).toHaveBeenCalled();
+ });
});
diff --git a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts
index 24002c84..e004196f 100644
--- a/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts
+++ b/Timeline/ClientApp/src/app/user/user-logout/user-logout.component.ts
@@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
+
import { InternalUserService } from '../internal-user-service/internal-user.service';
@Component({
@@ -7,11 +8,9 @@ import { InternalUserService } from '../internal-user-service/internal-user.serv
styleUrls: ['./user-logout.component.css']
})
export class UserLogoutComponent implements OnInit {
-
constructor(private userService: InternalUserService) { }
ngOnInit() {
this.userService.logout();
}
-
}
--
cgit v1.2.3