Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 5f70a32

Browse files
fix and write unit test cases
1 parent fdbf98e commit 5f70a32

16 files changed

+399
-45
lines changed

‎src/app/app.component.spec.ts‎

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import { TestBed } from '@angular/core/testing';
22
import { RouterTestingModule } from '@angular/router/testing';
33
import { AppComponent } from './app.component';
4+
import { MaterialModule } from './shared/material.module';
5+
import { CoreModule } from './core/core.module';
6+
import { SocialLoginModule } from '@abacritt/angularx-social-login';
7+
import { SocialAuthServiceConfigMock } from './testing/social-auth.mock';
8+
import { HttpClientTestingModule } from '@angular/common/http/testing';
49

510
describe('AppComponent', () => {
611
beforeEach(async () => {
712
await TestBed.configureTestingModule({
813
imports: [
9-
RouterTestingModule
10-
],
11-
declarations: [
12-
AppComponent
14+
RouterTestingModule,
15+
MaterialModule,
16+
CoreModule,
17+
SocialLoginModule,
18+
HttpClientTestingModule,
1319
],
20+
declarations: [AppComponent],
21+
providers: [SocialAuthServiceConfigMock],
1422
}).compileComponents();
1523
});
1624

@@ -19,17 +27,4 @@ describe('AppComponent', () => {
1927
const app = fixture.componentInstance;
2028
expect(app).toBeTruthy();
2129
});
22-
23-
it(`should have as title 'user-hub-angular'`, () => {
24-
const fixture = TestBed.createComponent(AppComponent);
25-
const app = fixture.componentInstance;
26-
expect(app.title).toEqual('user-hub-angular');
27-
});
28-
29-
it('should render title', () => {
30-
const fixture = TestBed.createComponent(AppComponent);
31-
fixture.detectChanges();
32-
const compiled = fixture.nativeElement as HTMLElement;
33-
expect(compiled.querySelector('.content span')?.textContent).toContain('user-hub-angular app is running!');
34-
});
3530
});
Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,66 @@
11
import { TestBed } from '@angular/core/testing';
2+
import { Router } from '@angular/router';
3+
import { AuthService } from './auth.service';
4+
import { AuthGuard } from './auth-guard.service';
5+
import { SocialLoginModule } from '@abacritt/angularx-social-login';
6+
import { HttpClientTestingModule } from '@angular/common/http/testing';
7+
import { SocialAuthServiceConfigMock } from 'src/app/testing/social-auth.mock';
28

3-
import{AuthGuardService}from'./auth-guard.service';
4-
5-
describe('AuthGuardService',()=>{
6-
let service: AuthGuardService;
9+
describe('AuthGuard',()=>{
10+
letguard: AuthGuard;
11+
letauthService: jasmine.SpyObj<AuthService>;
12+
let router: jasmine.SpyObj<Router>;
713

814
beforeEach(() => {
9-
TestBed.configureTestingModule({});
10-
service = TestBed.inject(AuthGuardService);
15+
const authServiceSpy = jasmine.createSpyObj('AuthService', [
16+
'isAuthenticated',
17+
]);
18+
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
19+
20+
TestBed.configureTestingModule({
21+
imports: [SocialLoginModule, HttpClientTestingModule],
22+
providers: [
23+
AuthGuard,
24+
{ provide: AuthService, useValue: authServiceSpy },
25+
{ provide: Router, useValue: routerSpy },
26+
SocialAuthServiceConfigMock,
27+
],
28+
});
29+
30+
guard = TestBed.inject(AuthGuard);
31+
authService = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
32+
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
1133
});
1234

1335
it('should be created', () => {
14-
expect(service).toBeTruthy();
36+
expect(guard).toBeTruthy();
37+
});
38+
39+
it('should return true and not navigate if user is authenticated', () => {
40+
// Arrange
41+
authService.isAuthenticated.and.returnValue(true);
42+
43+
// Act
44+
const canActivate = guard.canActivate();
45+
46+
// Assert
47+
canActivate.subscribe((result) => {
48+
expect(result).toBeTrue();
49+
expect(router.navigate).not.toHaveBeenCalled();
50+
});
51+
});
52+
53+
it('should return false and navigate to login if user is not authenticated', () => {
54+
// Arrange
55+
authService.isAuthenticated.and.returnValue(false);
56+
57+
// Act
58+
const canActivate = guard.canActivate();
59+
60+
// Assert
61+
canActivate.subscribe((result) => {
62+
expect(result).toBeFalse();
63+
expect(router.navigate).toHaveBeenCalledWith(['/login']);
64+
});
1565
});
1666
});

‎src/app/core/auth/auth-guard.service.ts‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import { CanActivate, Router } from '@angular/router';
33
import { Observable, of } from 'rxjs';
4-
import { map } from 'rxjs/operators';
54
import { AuthService } from './auth.service';
65

76
@Injectable()
@@ -12,7 +11,23 @@ export class AuthGuard implements CanActivate {
1211
const isAuthenticated = this.authService.isAuthenticated();
1312
if (!isAuthenticated) {
1413
this.router.navigate(['/login']);
14+
return of(false);
1515
}
1616
return of(isAuthenticated);
17+
/**
18+
* Need a server side API to validate token
19+
*/
20+
// return this.authService.validateToken().pipe(
21+
// switchMap((isValid: boolean) => {
22+
// if (isValid) {
23+
// // Token is valid, allow access
24+
// return of(true);
25+
// } else {
26+
// // Token is invalid, redirect to login or appropriate page
27+
// this.router.navigate(['/login']);
28+
// return of(false);
29+
// }
30+
// })
31+
// );
1732
}
1833
}
Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,85 @@
11
import { TestBed } from '@angular/core/testing';
2+
import {
3+
HttpClientTestingModule,
4+
HttpTestingController,
5+
} from '@angular/common/http/testing';
6+
import { SocialAuthService } from '@abacritt/angularx-social-login';
7+
import { RouterTestingModule } from '@angular/router/testing';
28
import { AuthService } from './auth.service';
9+
import { environment } from 'src/environments/environment';
10+
import { SocialAuthServiceConfigMock } from 'src/app/testing/social-auth.mock';
311

412
describe('AuthService', () => {
513
let service: AuthService;
14+
let httpMock: HttpTestingController;
615

716
beforeEach(() => {
8-
TestBed.configureTestingModule({});
17+
TestBed.configureTestingModule({
18+
imports: [HttpClientTestingModule, RouterTestingModule],
19+
providers: [AuthService, SocialAuthService, SocialAuthServiceConfigMock],
20+
});
21+
922
service = TestBed.inject(AuthService);
23+
httpMock = TestBed.inject(HttpTestingController);
24+
});
25+
26+
afterEach(() => {
27+
httpMock.verify();
1028
});
1129

1230
it('should be created', () => {
1331
expect(service).toBeTruthy();
1432
});
33+
34+
it('should call login and set isAuthenticatedSubject to true', () => {
35+
spyOn(service['isAuthenticatedSubject'], 'next');
36+
spyOn(localStorage, 'setItem');
37+
38+
const token = 'sampleToken';
39+
service.login(token);
40+
41+
expect(localStorage.setItem).toHaveBeenCalledWith('token', token);
42+
expect(service['isAuthenticatedSubject'].next).toHaveBeenCalledWith(true);
43+
});
44+
45+
it('should return true when token is present', () => {
46+
spyOn(localStorage, 'getItem').and.returnValue('sampleToken');
47+
48+
const result = service.isAuthenticated();
49+
50+
expect(result).toBe(true);
51+
});
52+
53+
it('should return false when token is not present', () => {
54+
spyOn(localStorage, 'getItem').and.returnValue(null);
55+
56+
const result = service.isAuthenticated();
57+
58+
expect(result).toBe(false);
59+
});
60+
61+
it('should return the token from localStorage', () => {
62+
const token = 'sampleToken';
63+
spyOn(localStorage, 'getItem').and.returnValue(token);
64+
65+
const result = service.getToken();
66+
67+
expect(result).toBe(token);
68+
});
69+
70+
it('should call the validateToken API and return the response', () => {
71+
const dummyResponse = true;
72+
73+
service.validateToken().subscribe((result) => {
74+
expect(result).toBe(dummyResponse);
75+
});
76+
77+
const req = httpMock.expectOne(
78+
`${environment.auth_uri}?id_token=${encodeURIComponent(
79+
service.getToken()
80+
)}`
81+
);
82+
expect(req.request.method).toBe('GET');
83+
req.flush(dummyResponse);
84+
});
1585
});

‎src/app/core/auth/auth.service.ts‎

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
SocialAuthService,
44
SocialUser,
55
} from '@abacritt/angularx-social-login';
6+
import { HttpClient } from '@angular/common/http';
67
import { Injectable } from '@angular/core';
78
import { Router } from '@angular/router';
8-
import { BehaviorSubject, Observable } from 'rxjs';
9+
import { BehaviorSubject, Observable, map } from 'rxjs';
10+
import { environment } from 'src/environments/environment';
911

1012
@Injectable({
1113
providedIn: 'root',
@@ -21,7 +23,11 @@ export class AuthService {
2123
public loginUser$: Observable<SocialUser> =
2224
this.loginUserSubject.asObservable();
2325

24-
constructor(private authService: SocialAuthService, private router: Router) {
26+
constructor(
27+
private authService: SocialAuthService,
28+
private router: Router,
29+
private http: HttpClient
30+
) {
2531
this.authService.authState.subscribe((user) => {
2632
console.log('user', user);
2733
this.loginUserSubject.next(user);
@@ -54,8 +60,26 @@ export class AuthService {
5460
return localStorage.getItem('token') || '';
5561
}
5662

57-
refreshToken(): void {
58-
this.authService.signIn(GoogleLoginProvider.PROVIDER_ID);
59-
// this.authService.refreshAuthToken(GoogleLoginProvider.PROVIDER_ID);
63+
refreshToken() {
64+
const encodedIdToken = encodeURIComponent(this.getToken());
65+
return this.http
66+
.get<any>(
67+
`https://oauth2.googleapis.com/tokeninfo?id_token=${encodedIdToken}`
68+
)
69+
.pipe(
70+
map((user) => {
71+
console.log(user);
72+
this.loginUserSubject.next(user);
73+
return user;
74+
})
75+
);
76+
}
77+
78+
// Method to validate the token
79+
public validateToken(): Observable<boolean> {
80+
const encodedIdToken = encodeURIComponent(this.getToken());
81+
return this.http.get<boolean>(
82+
`${environment.auth_uri}?id_token=${encodedIdToken}`
83+
);
6084
}
6185
}
Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,77 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { LoginComponent } from './login.component';
4+
import { HttpClientTestingModule } from '@angular/common/http/testing';
5+
import { AuthService } from '../auth.service';
6+
import { SocialAuthServiceConfigMock } from 'src/app/testing/social-auth.mock';
7+
import { MaterialModule } from 'src/app/shared/material.module';
8+
import {
9+
GoogleSigninButtonModule,
10+
SocialAuthService,
11+
SocialLoginModule,
12+
} from '@abacritt/angularx-social-login';
13+
import { Router } from '@angular/router';
414

515
describe('LoginComponent', () => {
616
let component: LoginComponent;
717
let fixture: ComponentFixture<LoginComponent>;
18+
let socialAuthService: jasmine.SpyObj<SocialAuthService>;
19+
let authService: jasmine.SpyObj<AuthService>;
20+
let router: jasmine.SpyObj<Router>;
821

922
beforeEach(async () => {
1023
await TestBed.configureTestingModule({
11-
declarations: [ LoginComponent ]
12-
})
13-
.compileComponents();
24+
declarations: [LoginComponent],
25+
imports: [
26+
SocialLoginModule,
27+
GoogleSigninButtonModule,
28+
HttpClientTestingModule,
29+
MaterialModule,
30+
],
31+
providers: [
32+
HttpClientTestingModule,
33+
AuthService,
34+
SocialAuthServiceConfigMock,
35+
],
36+
}).compileComponents();
1437

1538
fixture = TestBed.createComponent(LoginComponent);
1639
component = fixture.componentInstance;
40+
41+
socialAuthService = TestBed.inject(
42+
SocialAuthService
43+
) as jasmine.SpyObj<SocialAuthService>;
44+
authService = TestBed.inject(AuthService) as jasmine.SpyObj<AuthService>;
45+
router = TestBed.inject(Router) as jasmine.SpyObj<Router>;
1746
fixture.detectChanges();
1847
});
1948

2049
it('should create', () => {
2150
expect(component).toBeTruthy();
2251
});
52+
53+
it('should navigate to /users when user is logged in via social authentication', () => {
54+
const routingSpy = spyOn(router, 'navigate');
55+
const user = { idToken: 'some-id-token' };
56+
authService.login(user.idToken);
57+
component.checkIsLogin();
58+
expect(routingSpy).toHaveBeenCalledWith(['/users']);
59+
});
60+
61+
it('should navigate to /users when user is logged in via regular authentication', () => {
62+
const routingSpy = spyOn(router, 'navigate');
63+
const user = { idToken: 'some-id-token' };
64+
authService.login(user.idToken);
65+
66+
component.checkIsLogin();
67+
expect(routingSpy).toHaveBeenCalledWith(['/users']);
68+
});
69+
70+
it('should navigate to /users when user is already authenticated', () => {
71+
const routingSpy = spyOn(router, 'navigate');
72+
spyOn(authService, 'isAuthenticated').and.returnValue(true);
73+
74+
component.checkIsLogin();
75+
expect(routingSpy).toHaveBeenCalledWith(['/users']);
76+
});
2377
});

‎src/app/core/http/auth-interceptor.service.spec.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import { TestBed } from '@angular/core/testing';
22
import { AuthInterceptor } from './auth-interceptor.service';
3+
import { SocialAuthServiceConfigMock } from 'src/app/testing/social-auth.mock';
4+
import { HttpClientTestingModule } from '@angular/common/http/testing';
35

46
describe('AuthInterceptor', () => {
57
let service: AuthInterceptor;
68

79
beforeEach(() => {
8-
TestBed.configureTestingModule({});
10+
TestBed.configureTestingModule({
11+
imports: [HttpClientTestingModule],
12+
providers: [AuthInterceptor, SocialAuthServiceConfigMock],
13+
});
914
service = TestBed.inject(AuthInterceptor);
1015
});
1116

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /