Skip to content

Commit f9831c0

Browse files
committed
Merge branch 'master' into TT-466-Clock-Out
2 parents dcca5f3 + 7fd0975 commit f9831c0

30 files changed

+599
-51
lines changed

package-lock.json

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "time-tracker",
3-
"version": "1.57.1",
3+
"version": "1.58.0",
44
"scripts": {
55
"preinstall": "npx npm-force-resolutions",
66
"ng": "ng",
@@ -35,6 +35,7 @@
3535
"@types/datatables.net-buttons": "1.4.3",
3636
"angular-calendar": "0.28.26",
3737
"angular-datatables": "9.0.2",
38+
"angularx-social-login": "^3.5.7",
3839
"bootstrap": "4.4.1",
3940
"datatables.net": "1.10.22",
4041
"datatables.net-buttons": "1.6.2",

src/app/app.module.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ import { CalendarComponent } from './modules/time-entries/components/calendar/ca
8787
import { DropdownComponent } from './modules/shared/components/dropdown/dropdown.component';
8888
import { NgSelectModule } from '@ng-select/ng-select';
8989
import { DarkModeComponent } from './modules/shared/components/dark-mode/dark-mode.component';
90+
import { SocialLoginModule, SocialAuthServiceConfig } from 'angularx-social-login';
91+
import { GoogleLoginProvider } from 'angularx-social-login';
9092

9193
const maskConfig: Partial<IConfig> = {
9294
validation: false,
@@ -184,7 +186,8 @@ const maskConfig: Partial<IConfig> = {
184186
provide: DateAdapter,
185187
useFactory: adapterFactory,
186188
}),
187-
NgSelectModule
189+
NgSelectModule,
190+
SocialLoginModule
188191
],
189192
providers: [
190193
{
@@ -194,6 +197,20 @@ const maskConfig: Partial<IConfig> = {
194197
},
195198
DatePipe,
196199
CookieService,
200+
{
201+
provide: 'SocialAuthServiceConfig',
202+
useValue: {
203+
autoLogin: false,
204+
providers: [
205+
{
206+
id: GoogleLoginProvider.PROVIDER_ID,
207+
provider: new GoogleLoginProvider(
208+
'565556796659-hscrj9e6m2krc41cfng898793ocfnb8j.apps.googleusercontent.com'
209+
)
210+
}
211+
]
212+
} as SocialAuthServiceConfig,
213+
}
197214
],
198215
bootstrap: [AppComponent],
199216
})

src/app/guards/login-guard/login.guard.spec.ts

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { Router } from '@angular/router';
44

55
import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service';
66
import { LoginGuard } from './login.guard';
7+
import { LoginService } from '../../modules/login/services/login.service';
8+
import { HttpClientTestingModule } from '@angular/common/http/testing';
9+
import { SocialAuthService } from 'angularx-social-login';
710

811

912
describe('LoginGuard', () => {
@@ -15,29 +18,49 @@ describe('LoginGuard', () => {
1518
return true;
1619
}
1720
};
21+
let loginService: LoginService;
22+
const loginServiceStub = {
23+
isLogin() {
24+
return true;
25+
}
26+
};
27+
const socialAuthServiceStub = jasmine.createSpyObj('SocialAuthService', ['']);
1828
beforeEach(() => {
1929
TestBed.configureTestingModule({
20-
imports: [ RouterTestingModule ],
30+
imports: [ RouterTestingModule, HttpClientTestingModule ],
2131
providers: [
2232
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
33+
{ providers: LoginService, useValue: loginServiceStub},
34+
{ provide: SocialAuthService, useValue: socialAuthServiceStub }
2335
]
2436
});
2537
loginGuard = TestBed.inject(LoginGuard);
2638
azureAdB2CService = TestBed.inject(AzureAdB2CService);
39+
loginService = TestBed.inject(LoginService);
2740
});
2841

2942
it('should be created', () => {
3043
expect(loginGuard).toBeTruthy();
3144
});
3245

33-
it('can activate the route when user is logged-in', () => {
46+
it('can activate the route when user is logged-in on Production', () => {
47+
loginGuard.isProduction = true;
3448
spyOn(azureAdB2CService, 'isLogin').and.returnValue(true);
3549
const canActivate = loginGuard.canActivate();
3650
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
3751
expect(canActivate).toEqual(true);
3852
});
3953

40-
it('can not active the route and is redirected to login if user is not logged-in', inject([Router], (router: Router) => {
54+
it('can activate the route when user is logged-in Locally', () => {
55+
loginGuard.isProduction = false;
56+
spyOn(loginService, 'isLogin').and.returnValue(true);
57+
const canActivate = loginGuard.canActivate();
58+
expect(loginService.isLogin).toHaveBeenCalled();
59+
expect(canActivate).toEqual(true);
60+
});
61+
62+
it('can not active the route and is redirected to login if user is not logged-in on Production', inject([Router], (router: Router) => {
63+
loginGuard.isProduction = true;
4164
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
4265
spyOn(router, 'navigate').and.stub();
4366
const canActivate = loginGuard.canActivate();
@@ -46,4 +69,14 @@ describe('LoginGuard', () => {
4669
expect(router.navigate).toHaveBeenCalledWith(['login']);
4770
}));
4871

72+
it('can not active the route and is redirected to login if user is not logged-in Locally', inject([Router], (router: Router) => {
73+
loginGuard.isProduction = false;
74+
spyOn(loginService, 'isLogin').and.returnValue(false);
75+
spyOn(router, 'navigate').and.stub();
76+
const canActivate = loginGuard.canActivate();
77+
expect(loginService.isLogin).toHaveBeenCalled();
78+
expect(canActivate).toEqual(false);
79+
expect(router.navigate).toHaveBeenCalledWith(['login']);
80+
}));
81+
4982
});
Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,37 @@
11
import { Injectable } from '@angular/core';
22
import { Router, CanActivate } from '@angular/router';
33
import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service';
4+
import { LoginService } from '../../modules/login/services/login.service';
5+
import { environment } from 'src/environments/environment';
46

57
@Injectable({
6-
providedIn: 'root'
8+
providedIn: 'root',
79
})
810
export class LoginGuard implements CanActivate {
9-
10-
constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) { }
11+
isProduction = environment.production;
12+
constructor(
13+
private azureAdB2CService: AzureAdB2CService,
14+
private router: Router,
15+
private loginService: LoginService
16+
) {}
1117

1218
canActivate() {
13-
if (this.azureAdB2CService.isLogin()) {
19+
if (this.isProduction) {
20+
if (this.azureAdB2CService.isLogin()) {
1421
this.azureAdB2CService.setCookies();
1522
return true;
23+
} else {
24+
this.router.navigate(['login']);
25+
return false;
26+
}
1627
} else {
28+
if (this.loginService.isLogin()) {
29+
this.loginService.setCookies();
30+
return true;
31+
} else {
1732
this.router.navigate(['login']);
1833
return false;
34+
}
1935
}
2036
}
2137
}

src/app/modules/home/home.component.spec.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { MockStore, provideMockStore } from '@ngrx/store/testing';
33
import { AzureAdB2CService } from '../login/services/azure.ad.b2c.service';
44
import { LoadUser } from '../user/store/user.actions';
55
import { HomeComponent } from './home.component';
6+
import { LoginService } from '../login/services/login.service';
67

78
describe('HomeComponent', () => {
89
let component: HomeComponent;
@@ -13,6 +14,9 @@ describe('HomeComponent', () => {
1314
const azureB2CServiceStub = {
1415
getUserId: () => 'user_id',
1516
};
17+
const loginServiceStub = {
18+
getUserId: () => 'user_id',
19+
};
1620

1721
beforeEach(
1822
waitForAsync(() => {
@@ -21,6 +25,7 @@ describe('HomeComponent', () => {
2125
providers: [
2226
provideMockStore({ initialState }),
2327
{ provide: AzureAdB2CService, useValue: azureB2CServiceStub },
28+
{ provide: LoginService, useValue: loginServiceStub },
2429
],
2530
}).compileComponents();
2631
})
@@ -30,7 +35,6 @@ describe('HomeComponent', () => {
3035
fixture = TestBed.createComponent(HomeComponent);
3136
azureAdB2CService = TestBed.inject(AzureAdB2CService);
3237
store = TestBed.inject(MockStore);
33-
3438
component = fixture.componentInstance;
3539
fixture.detectChanges();
3640
store.setState(initialState);
@@ -41,6 +45,7 @@ describe('HomeComponent', () => {
4145
});
4246

4347
it('onInit, LoadUser action is dispatched', () => {
48+
component.isProduction = true;
4449
const userId = 'user_id';
4550
spyOn(azureAdB2CService, 'getUserId').and.returnValue(userId);
4651
spyOn(store, 'dispatch');
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
11
import { Component, OnInit } from '@angular/core';
22
import { Store } from '@ngrx/store';
33
import { LoadUser } from 'src/app/modules/user/store/user.actions';
4+
import { environment } from 'src/environments/environment';
45
import { AzureAdB2CService } from '../login/services/azure.ad.b2c.service';
6+
import { LoginService } from '../login/services/login.service';
57

68
@Component({
79
selector: 'app-home',
810
templateUrl: './home.component.html',
911
styleUrls: ['./home.component.scss'],
1012
})
1113
export class HomeComponent implements OnInit {
12-
14+
isProduction = environment.production;
1315
constructor(
1416
private azureAdB2CService: AzureAdB2CService,
17+
private loginService: LoginService,
1518
private store: Store
1619
) { }
1720

1821
ngOnInit(): void {
19-
const userId = this.azureAdB2CService.getUserId();
22+
const userId = this.isProduction ? this.azureAdB2CService.getUserId() : this.loginService.getUserId();
2023
this.store.dispatch(new LoadUser(userId));
2124
}
2225
}

src/app/modules/login/login.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ <h3>Please log in</h3>
88
</div>
99

1010
<div class="login-controls">
11-
<button (click)="login()" class="btn btn-primary">login</button>
11+
<button (click)="isProduction ? login() : loginWithGoogle() " class="btn btn-primary">login</button>
1212
</div>
1313

1414
</div>

src/app/modules/login/login.component.spec.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import { of } from 'rxjs';
55
import { LoginComponent } from './login.component';
66
import { Router } from '@angular/router';
77
import { FeatureToggleCookiesService } from '../shared/feature-toggles/feature-toggle-cookies/feature-toggle-cookies.service';
8+
import { LoginService } from './services/login.service';
9+
import { HttpClientTestingModule } from '@angular/common/http/testing';
10+
import { SocialAuthService } from 'angularx-social-login';
811

912
describe('LoginComponent', () => {
1013
let component: LoginComponent;
1114
let fixture: ComponentFixture<LoginComponent>;
1215
let azureAdB2CService: AzureAdB2CService;
16+
let loginService: LoginService;
1317
let featureToggleCookiesService: FeatureToggleCookiesService;
1418

1519
const azureAdB2CServiceStub = {
@@ -23,29 +27,45 @@ describe('LoginComponent', () => {
2327
}
2428
};
2529

30+
const loginServiceStub = {
31+
isLogin() {
32+
return true;
33+
},
34+
signIn() {
35+
return of();
36+
},
37+
setCookies() {
38+
}
39+
};
40+
2641
const featureToggleCookiesServiceStub = {
2742
setCookies() {
2843
return null;
2944
}
3045
};
3146

47+
const socialAuthServiceStub = jasmine.createSpyObj('SocialAuthService', ['signIn', 'authState']);
3248
beforeEach(waitForAsync(() => {
3349
TestBed.configureTestingModule({
34-
imports: [ RouterTestingModule ],
50+
imports: [ RouterTestingModule, HttpClientTestingModule],
3551
declarations: [ LoginComponent ],
3652
providers: [
3753
{ providers: AzureAdB2CService, useValue: azureAdB2CServiceStub},
38-
{ providers: FeatureToggleCookiesService, useValue: featureToggleCookiesServiceStub}
54+
{ providers: FeatureToggleCookiesService, useValue: featureToggleCookiesServiceStub},
55+
{ providers: LoginService, useValue: loginServiceStub},
56+
{ provide: SocialAuthService, useValue: socialAuthServiceStub }
3957
]
4058
})
4159
.compileComponents();
4260
}));
4361

4462
beforeEach(() => {
63+
socialAuthServiceStub.authState = of('some value');
4564
fixture = TestBed.createComponent(LoginComponent);
4665
component = fixture.componentInstance;
4766
fixture.detectChanges();
4867
azureAdB2CService = TestBed.inject(AzureAdB2CService);
68+
loginService = TestBed.inject(LoginService);
4969
featureToggleCookiesService = TestBed.inject(FeatureToggleCookiesService);
5070
});
5171

@@ -65,7 +85,7 @@ describe('LoginComponent', () => {
6585
expect(component).toBeTruthy();
6686
});
6787

68-
it('should sign up or login with google if is not logged-in into the app', inject([Router], (router: Router) => {
88+
it('should sign up or login with google if is not logged-in into the app on Production', inject([Router], (router: Router) => {
6989
spyOn(azureAdB2CService, 'isLogin').and.returnValue(false);
7090
spyOn(azureAdB2CService, 'setCookies').and.returnValue();
7191
spyOn(azureAdB2CService, 'signIn').and.returnValue(of(() => {}));
@@ -78,11 +98,35 @@ describe('LoginComponent', () => {
7898
expect(featureToggleCookiesService.setCookies).toHaveBeenCalled();
7999
}));
80100

81-
it('should not sign-up or login with google if is already logged-in into the app', inject([Router], (router: Router) => {
101+
it('should sign up or login with google if is not logged-in into the app Locally', inject([Router], (router: Router) => {
102+
spyOn(loginService, 'isLogin').and.returnValue(false);
103+
spyOn(loginService, 'setLocalStorage').and.returnValue();
104+
spyOn(loginService, 'getUser').and.returnValue(of(() => {}));
105+
spyOn(loginService, 'setCookies').and.returnValue();
106+
spyOn(loginService, 'signIn').and.returnValue();
107+
spyOn(featureToggleCookiesService, 'setCookies').and.returnValue(featureToggleCookiesService.setCookies());
108+
109+
component.ngOnInit();
110+
component.loginWithGoogle();
111+
112+
expect(loginService.signIn).toHaveBeenCalled();
113+
expect(loginService.setCookies).toHaveBeenCalled();
114+
expect(featureToggleCookiesService.setCookies).toHaveBeenCalled();
115+
}));
116+
117+
it('should not sign-up or login with google if is already logged-in into the app on Production', inject([Router], (router: Router) => {
82118
spyOn(azureAdB2CService, 'isLogin').and.returnValue(true);
83119
spyOn(router, 'navigate').and.stub();
84120
component.login();
85121
expect(azureAdB2CService.isLogin).toHaveBeenCalled();
86122
expect(router.navigate).toHaveBeenCalledWith(['']);
87123
}));
124+
125+
it('should not sign-up or login with google if is already logged-in into the app Locally', inject([Router], (router: Router) => {
126+
spyOn(loginService, 'isLogin').and.returnValue(true);
127+
spyOn(router, 'navigate').and.stub();
128+
component.loginWithGoogle();
129+
expect(loginService.isLogin).toHaveBeenCalled();
130+
expect(router.navigate).toHaveBeenCalledWith(['']);
131+
}));
88132
});

0 commit comments

Comments
 (0)