From be08f793a263f252523e6a1fe02f54cee5540ef1 Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Fri, 4 Dec 2020 14:19:59 -0500 Subject: [PATCH 01/23] TT-15 fix: Keep the user logged in the browser --- package.json | 1 + src/app/app.module.ts | 4 ++- src/app/guards/login-guard/login.guard.ts | 3 +- src/app/modules/login/login.component.ts | 1 + .../login/services/azure.ad.b2c.service.ts | 29 +++++++++++++++---- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index bde329221..ef0b24bb5 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "minimist": "^1.2.5", "moment": "^2.25.3", "msal": "^1.2.1", + "ngx-cookie-service": "^11.0.2", "ngx-mask": "^9.1.2", "ngx-pagination": "^5.0.0", "ngx-toastr": "^12.0.1", diff --git a/src/app/app.module.ts b/src/app/app.module.ts index a9a6778ac..eccd6efaf 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -16,6 +16,7 @@ import { AutocompleteLibModule } from 'angular-ng-autocomplete'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { CookieService } from 'ngx-cookie-service'; import { NavbarComponent } from './modules/shared/components/navbar/navbar.component'; import { UserComponent } from './modules/shared/components/user/user.component'; import { SidebarComponent } from './modules/shared/components/sidebar/sidebar.component'; @@ -159,7 +160,8 @@ const maskConfig: Partial = { useClass: InjectTokenInterceptor, multi: true, }, - DatePipe + DatePipe, + CookieService, ], bootstrap: [AppComponent], }) diff --git a/src/app/guards/login-guard/login.guard.ts b/src/app/guards/login-guard/login.guard.ts index 6041de936..162544da3 100644 --- a/src/app/guards/login-guard/login.guard.ts +++ b/src/app/guards/login-guard/login.guard.ts @@ -11,10 +11,11 @@ export class LoginGuard implements CanActivate { canActivate() { if (this.azureAdB2CService.isLogin()) { + this.azureAdB2CService.setCookies(); return true; } else { this.router.navigate(['login']); return false; } -} + } } diff --git a/src/app/modules/login/login.component.ts b/src/app/modules/login/login.component.ts index f3eb6e859..c41251ab9 100644 --- a/src/app/modules/login/login.component.ts +++ b/src/app/modules/login/login.component.ts @@ -17,6 +17,7 @@ export class LoginComponent { this.router.navigate(['']); } else { this.azureAdB2CService.signIn().subscribe(() => { + this.azureAdB2CService.setCookies(); this.router.navigate(['']); }); } diff --git a/src/app/modules/login/services/azure.ad.b2c.service.ts b/src/app/modules/login/services/azure.ad.b2c.service.ts index b6945f9de..5739d29aa 100644 --- a/src/app/modules/login/services/azure.ad.b2c.service.ts +++ b/src/app/modules/login/services/azure.ad.b2c.service.ts @@ -1,6 +1,7 @@ import { Injectable } from '@angular/core'; import { UserAgentApplication } from 'msal'; import { from, Observable } from 'rxjs'; +import { CookieService } from 'ngx-cookie-service'; import { AUTHORITY, CLIENT_ID, SCOPES } from '../../../../environments/environment'; @@ -8,12 +9,18 @@ import { AUTHORITY, CLIENT_ID, SCOPES } from '../../../../environments/environme providedIn: 'root', }) export class AzureAdB2CService { - msalConfig = { + + constructor(private cookieService: CookieService) {} + + msalConfig: any = { auth: { clientId: CLIENT_ID, authority: AUTHORITY, validateAuthority: false, }, + cache: { + cacheLocation: 'localStorage', + }, }; tokenRequest = { @@ -27,6 +34,8 @@ export class AzureAdB2CService { } logout() { + this.cookieService.delete('msal.idtoken'); + this.cookieService.delete('msal.idtoken'); this.msal.logout(); } @@ -39,22 +48,32 @@ export class AzureAdB2CService { } isLogin() { - return this.msal.getAccount() ? true : false; + return this.msal.getAccount() && this.cookieService.check('msal.idtoken') ? true : false; + } + + setCookies() { + this.cookieService.set('msal.client.info', this.getBearerClientInfo(), 2); + this.cookieService.set('msal.idtoken', this.getBearerToken(), 2); } setTenantId() { if (this.msal.getAccount() && this.msal.getAccount().idToken) { const pathArray = this.msal.getAccount().idToken.iss.split('/'); const tenantId = pathArray[3]; - sessionStorage.setItem('tenant_id', tenantId); + localStorage.setItem('tenant_id', tenantId); } } getTenantId(): string { - return sessionStorage.getItem('tenant_id'); + return localStorage.getItem('tenant_id'); + } + + getBearerClientInfo(): string { + return localStorage.getItem('msal.client.info'); } + getBearerToken(): string { - return sessionStorage.getItem('msal.idtoken'); + return localStorage.getItem('msal.idtoken'); } getUserEmail(): string { From 6022747a03000151fbb81d67a961e49742c5d636 Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Fri, 4 Dec 2020 14:28:58 -0500 Subject: [PATCH 02/23] TT-15 fix: unit test --- .../guards/login-guard/login.guard.spec.ts | 7 +++++- src/app/guards/login-guard/login.guard.ts | 5 +++-- .../services/azure.ad.b2c.service.spec.ts | 22 +++++++++---------- .../login/services/azure.ad.b2c.service.ts | 4 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/app/guards/login-guard/login.guard.spec.ts b/src/app/guards/login-guard/login.guard.spec.ts index 37d156541..c065dbb23 100644 --- a/src/app/guards/login-guard/login.guard.spec.ts +++ b/src/app/guards/login-guard/login.guard.spec.ts @@ -1,6 +1,7 @@ import { TestBed, inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Router } from '@angular/router'; +import { CookieService } from 'ngx-cookie-service'; import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service'; import { LoginGuard } from './login.guard'; @@ -10,6 +11,7 @@ describe('LoginGuard', () => { let loginGuard: LoginGuard; let azureAdB2CService: AzureAdB2CService; + let cookieService: CookieService; const azureAdB2CServiceStub = { isLogin() { return true; @@ -24,16 +26,19 @@ describe('LoginGuard', () => { }); loginGuard = TestBed.inject(LoginGuard); azureAdB2CService = TestBed.inject(AzureAdB2CService); + cookieService = TestBed.inject(CookieService); }); it('should be created', () => { expect(loginGuard).toBeTruthy(); }); - it('can activate the route when user is logged-in', () => { + it('can activate the route when user is logged-in && the token cookie exists', () => { spyOn(azureAdB2CService, 'isLogin').and.returnValue(true); + spyOn(cookieService, 'check').and.returnValue(true); const canActivate = loginGuard.canActivate(); expect(azureAdB2CService.isLogin).toHaveBeenCalled(); + expect(cookieService.check).toHaveBeenCalled(); expect(canActivate).toEqual(true); }); diff --git a/src/app/guards/login-guard/login.guard.ts b/src/app/guards/login-guard/login.guard.ts index 162544da3..09d46c94f 100644 --- a/src/app/guards/login-guard/login.guard.ts +++ b/src/app/guards/login-guard/login.guard.ts @@ -1,16 +1,17 @@ import { Injectable } from '@angular/core'; import { Router, CanActivate } from '@angular/router'; import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service'; +import { CookieService } from 'ngx-cookie-service'; @Injectable({ providedIn: 'root' }) export class LoginGuard implements CanActivate { - constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) { } + constructor(private azureAdB2CService: AzureAdB2CService, private router: Router, private cookieService: CookieService) { } canActivate() { - if (this.azureAdB2CService.isLogin()) { + if (this.azureAdB2CService.isLogin() && this.cookieService.check('msal.idtoken')) { this.azureAdB2CService.setCookies(); return true; } else { diff --git a/src/app/modules/login/services/azure.ad.b2c.service.spec.ts b/src/app/modules/login/services/azure.ad.b2c.service.spec.ts index 97c7f35c9..8d80b12cc 100644 --- a/src/app/modules/login/services/azure.ad.b2c.service.spec.ts +++ b/src/app/modules/login/services/azure.ad.b2c.service.spec.ts @@ -91,44 +91,44 @@ describe('AzureAdB2CService', () => { expect(isLogin).toEqual(false); }); - it('setTenantId should save a tenantId in session storage', () => { + it('setTenantId should save a tenantId in local storage', () => { spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(account); - spyOn(sessionStorage, 'setItem').withArgs('tenant_id', '12345'); + spyOn(localStorage, 'setItem').withArgs('tenant_id', '12345'); const isLogin = service.isLogin(); service.setTenantId(); expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); expect(isLogin).toEqual(true); - expect(sessionStorage.setItem).toHaveBeenCalledWith('tenant_id', '12345'); + expect(localStorage.setItem).toHaveBeenCalledWith('tenant_id', '12345'); }); it('setTenantId should not save tenantId if login is false ', () => { spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(null); - spyOn(sessionStorage, 'setItem'); + spyOn(localStorage, 'setItem'); const isLogin = service.isLogin(); expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); expect(isLogin).toEqual(false); - expect(sessionStorage.setItem).not.toHaveBeenCalled(); + expect(localStorage.setItem).not.toHaveBeenCalled(); }); - it('getTenantId should get the tenantId from session storage', () => { + it('getTenantId should get the tenantId from local storage', () => { const tenantId = '12345'; - spyOn(sessionStorage, 'getItem').and.returnValue(tenantId); + spyOn(localStorage, 'getItem').and.returnValue(tenantId); const resp = service.getTenantId(); - expect(sessionStorage.getItem).toHaveBeenCalled(); + expect(localStorage.getItem).toHaveBeenCalled(); expect(resp).toEqual(tenantId); }); - it('getBearerToken should get the bearer token from session storage', () => { + it('getBearerToken should get the bearer token from local storage', () => { const token = '12345abc'; - spyOn(sessionStorage, 'getItem').and.returnValue(token); + spyOn(localStorage, 'getItem').and.returnValue(token); const resp = service.getBearerToken(); - expect(sessionStorage.getItem).toHaveBeenCalled(); + expect(localStorage.getItem).toHaveBeenCalled(); expect(resp).toEqual(token); }); diff --git a/src/app/modules/login/services/azure.ad.b2c.service.ts b/src/app/modules/login/services/azure.ad.b2c.service.ts index 5739d29aa..defab9183 100644 --- a/src/app/modules/login/services/azure.ad.b2c.service.ts +++ b/src/app/modules/login/services/azure.ad.b2c.service.ts @@ -10,7 +10,7 @@ import { AUTHORITY, CLIENT_ID, SCOPES } from '../../../../environments/environme }) export class AzureAdB2CService { - constructor(private cookieService: CookieService) {} + constructor(private cookieService?: CookieService) {} msalConfig: any = { auth: { @@ -48,7 +48,7 @@ export class AzureAdB2CService { } isLogin() { - return this.msal.getAccount() && this.cookieService.check('msal.idtoken') ? true : false; + return this.msal.getAccount() ? true : false; } setCookies() { From 96418d4d1678da4ab8c3951b88f97684c2b46822 Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Tue, 8 Dec 2020 19:15:15 -0500 Subject: [PATCH 03/23] TT-15 fix: setCookies for sing up or login test --- src/app/modules/login/login.component.spec.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app/modules/login/login.component.spec.ts b/src/app/modules/login/login.component.spec.ts index 725dae4ce..b1ded62e1 100644 --- a/src/app/modules/login/login.component.spec.ts +++ b/src/app/modules/login/login.component.spec.ts @@ -17,6 +17,8 @@ describe('LoginComponent', () => { }, signIn() { return of(); + }, + setCookies() { } }; @@ -51,9 +53,11 @@ describe('LoginComponent', () => { it('should sign up or login with google if is not logged-in into the app', inject([Router], (router: Router) => { spyOn(azureAdB2CService, 'isLogin').and.returnValue(false); - spyOn(azureAdB2CService, 'signIn').and.returnValue(of()); + spyOn(azureAdB2CService, 'setCookies').and.returnValue(); + spyOn(azureAdB2CService, 'signIn').and.returnValue(of(() => {})); component.login(); expect(azureAdB2CService.signIn).toHaveBeenCalled(); + expect(azureAdB2CService.setCookies).toHaveBeenCalled(); })); it('should not sign-up or login with google if is already logged-in into the app', inject([Router], (router: Router) => { From 48447259f068c60132c9762aa4315988458080e2 Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Wed, 9 Dec 2020 14:23:29 -0500 Subject: [PATCH 04/23] TT-15 fix: add test for login when cookie does not exist --- .../guards/login-guard/login.guard.spec.ts | 7 +----- src/app/guards/login-guard/login.guard.ts | 5 ++-- .../services/azure.ad.b2c.service.spec.ts | 24 ++++++++++++++++--- .../login/services/azure.ad.b2c.service.ts | 6 ++--- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/app/guards/login-guard/login.guard.spec.ts b/src/app/guards/login-guard/login.guard.spec.ts index c065dbb23..37d156541 100644 --- a/src/app/guards/login-guard/login.guard.spec.ts +++ b/src/app/guards/login-guard/login.guard.spec.ts @@ -1,7 +1,6 @@ import { TestBed, inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { Router } from '@angular/router'; -import { CookieService } from 'ngx-cookie-service'; import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service'; import { LoginGuard } from './login.guard'; @@ -11,7 +10,6 @@ describe('LoginGuard', () => { let loginGuard: LoginGuard; let azureAdB2CService: AzureAdB2CService; - let cookieService: CookieService; const azureAdB2CServiceStub = { isLogin() { return true; @@ -26,19 +24,16 @@ describe('LoginGuard', () => { }); loginGuard = TestBed.inject(LoginGuard); azureAdB2CService = TestBed.inject(AzureAdB2CService); - cookieService = TestBed.inject(CookieService); }); it('should be created', () => { expect(loginGuard).toBeTruthy(); }); - it('can activate the route when user is logged-in && the token cookie exists', () => { + it('can activate the route when user is logged-in', () => { spyOn(azureAdB2CService, 'isLogin').and.returnValue(true); - spyOn(cookieService, 'check').and.returnValue(true); const canActivate = loginGuard.canActivate(); expect(azureAdB2CService.isLogin).toHaveBeenCalled(); - expect(cookieService.check).toHaveBeenCalled(); expect(canActivate).toEqual(true); }); diff --git a/src/app/guards/login-guard/login.guard.ts b/src/app/guards/login-guard/login.guard.ts index 09d46c94f..162544da3 100644 --- a/src/app/guards/login-guard/login.guard.ts +++ b/src/app/guards/login-guard/login.guard.ts @@ -1,17 +1,16 @@ import { Injectable } from '@angular/core'; import { Router, CanActivate } from '@angular/router'; import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service'; -import { CookieService } from 'ngx-cookie-service'; @Injectable({ providedIn: 'root' }) export class LoginGuard implements CanActivate { - constructor(private azureAdB2CService: AzureAdB2CService, private router: Router, private cookieService: CookieService) { } + constructor(private azureAdB2CService: AzureAdB2CService, private router: Router) { } canActivate() { - if (this.azureAdB2CService.isLogin() && this.cookieService.check('msal.idtoken')) { + if (this.azureAdB2CService.isLogin()) { this.azureAdB2CService.setCookies(); return true; } else { diff --git a/src/app/modules/login/services/azure.ad.b2c.service.spec.ts b/src/app/modules/login/services/azure.ad.b2c.service.spec.ts index 8d80b12cc..4cb71ef2c 100644 --- a/src/app/modules/login/services/azure.ad.b2c.service.spec.ts +++ b/src/app/modules/login/services/azure.ad.b2c.service.spec.ts @@ -1,11 +1,11 @@ import { inject, TestBed } from '@angular/core/testing'; import { Account, UserAgentApplication } from 'msal'; import { AzureAdB2CService } from './azure.ad.b2c.service'; - +import { CookieService } from 'ngx-cookie-service'; describe('AzureAdB2CService', () => { let service: AzureAdB2CService; - + let cookieService: CookieService; let account: Account; beforeEach(() => { @@ -13,6 +13,7 @@ describe('AzureAdB2CService', () => { imports: [], }); service = TestBed.inject(AzureAdB2CService); + cookieService = TestBed.inject(CookieService); account = { accountIdentifier: 'abc', homeAccountIdentifier: 'abc', @@ -75,30 +76,47 @@ describe('AzureAdB2CService', () => { expect(isAdmin).toBeTruthy(); }); - it('isLogin returns true if UserAgentApplication has a defined Account', () => { + it('isLogin returns true if UserAgentApplication has a defined Account and token cookie exist', () => { spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(account); + spyOn(cookieService, 'check').and.returnValue(true); const isLogin = service.isLogin(); expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); + expect(cookieService.check).toHaveBeenCalled(); expect(isLogin).toEqual(true); }); + it('isLogin returns false if UserAgentApplication has a defined Account and token cookie does not exist', () => { + spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(account); + spyOn(cookieService, 'check').and.returnValue(false); + + const isLogin = service.isLogin(); + + expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); + expect(cookieService.check).toHaveBeenCalled(); + expect(isLogin).toEqual(false); + }); + it('isLogin returns false if UserAgentApplication has a null value for Account', () => { spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(null); + const isLogin = service.isLogin(); + expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); expect(isLogin).toEqual(false); }); it('setTenantId should save a tenantId in local storage', () => { spyOn(UserAgentApplication.prototype, 'getAccount').and.returnValue(account); + spyOn(cookieService, 'check').and.returnValue(true); spyOn(localStorage, 'setItem').withArgs('tenant_id', '12345'); const isLogin = service.isLogin(); service.setTenantId(); expect(UserAgentApplication.prototype.getAccount).toHaveBeenCalled(); + expect(cookieService.check).toHaveBeenCalled(); expect(isLogin).toEqual(true); expect(localStorage.setItem).toHaveBeenCalledWith('tenant_id', '12345'); }); diff --git a/src/app/modules/login/services/azure.ad.b2c.service.ts b/src/app/modules/login/services/azure.ad.b2c.service.ts index defab9183..57aad18f9 100644 --- a/src/app/modules/login/services/azure.ad.b2c.service.ts +++ b/src/app/modules/login/services/azure.ad.b2c.service.ts @@ -35,7 +35,7 @@ export class AzureAdB2CService { logout() { this.cookieService.delete('msal.idtoken'); - this.cookieService.delete('msal.idtoken'); + this.cookieService.delete('msal.client.info'); this.msal.logout(); } @@ -48,12 +48,12 @@ export class AzureAdB2CService { } isLogin() { - return this.msal.getAccount() ? true : false; + return this.msal.getAccount() && this.cookieService.check('msal.idtoken') ? true : false; } setCookies() { - this.cookieService.set('msal.client.info', this.getBearerClientInfo(), 2); this.cookieService.set('msal.idtoken', this.getBearerToken(), 2); + this.cookieService.set('msal.client.info', this.getBearerClientInfo(), 2); } setTenantId() { From 2e9ab62ee7151fe9a5424f20e51af564fe2b4bee Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Thu, 10 Dec 2020 18:10:58 -0500 Subject: [PATCH 05/23] TT-69 fix: adding or editing an entry must not overlap the date of an active entry --- .../pages/time-entries.component.spec.ts | 21 +++++++++++++++++++ .../pages/time-entries.component.ts | 6 +++--- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/app/modules/time-entries/pages/time-entries.component.spec.ts b/src/app/modules/time-entries/pages/time-entries.component.spec.ts index 77511dae6..08e785621 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.spec.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.spec.ts @@ -240,6 +240,27 @@ describe('TimeEntriesComponent', () => { entry: { project_id: 'p-id', start_date: '2020-05-05T10:04', + end_date: '2020-05-05T11:04', + description: 'description', + technologies: [], + uri: 'abc', + }, shouldRestartEntry: false + }; + component.entryId = 'new-entry'; + spyOn(injectedToastrService, 'error'); + + component.saveEntry(newEntry); + + expect(injectedToastrService.error).toHaveBeenCalled(); + }); + + it('displays an error when end date of entry is > than active entry start date', async () => { + component.activeTimeEntry = entry; + const newEntry = { + entry: { + project_id: 'p-id', + start_date: '2020-01-05T10:04', + end_date: '2020-03-05T11:04', description: 'description', technologies: [], uri: 'abc', diff --git a/src/app/modules/time-entries/pages/time-entries.component.ts b/src/app/modules/time-entries/pages/time-entries.component.ts index 01b929fc2..d62e3ec7e 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.ts @@ -101,11 +101,11 @@ export class TimeEntriesComponent implements OnInit, OnDestroy { saveEntry(event: SaveEntryEvent): void { if (this.activeTimeEntry !== null && this.activeTimeEntry !== undefined) { - const entryDateAsIso = new Date(event.entry.start_date).toISOString(); - const entryDateAsLocalDate = new Date(entryDateAsIso); + const startDateAsLocalDate = new Date(event.entry.start_date); + const endDateAsLocalDate = new Date(event.entry.end_date); const activeEntryAsLocalDate = new Date(this.activeTimeEntry.start_date); const isEditingActiveEntry = this.entryId === this.activeTimeEntry.id; - if (!isEditingActiveEntry && entryDateAsLocalDate > activeEntryAsLocalDate) { + if (!isEditingActiveEntry && (startDateAsLocalDate > activeEntryAsLocalDate || endDateAsLocalDate > activeEntryAsLocalDate)) { this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.'); } else { this.doSave(event); From 5cbe799cb780c1f8b5e86f228acc596b192bfd82 Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Thu, 10 Dec 2020 18:13:55 -0500 Subject: [PATCH 06/23] TT-69 fix: refactor variables and conidtions --- .../pages/time-entries.component.spec.ts | 4 ++-- .../time-entries/pages/time-entries.component.ts | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/modules/time-entries/pages/time-entries.component.spec.ts b/src/app/modules/time-entries/pages/time-entries.component.spec.ts index 08e785621..c9bb75427 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.spec.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.spec.ts @@ -234,7 +234,7 @@ describe('TimeEntriesComponent', () => { expect(component.canMarkEntryAsWIP).toBe(true); }); - it('displays an error when start date of entry is > than active entry start date', async () => { + it('displays an error when start date of entry is greater than active entry start date', async () => { component.activeTimeEntry = entry; const newEntry = { entry: { @@ -254,7 +254,7 @@ describe('TimeEntriesComponent', () => { expect(injectedToastrService.error).toHaveBeenCalled(); }); - it('displays an error when end date of entry is > than active entry start date', async () => { + it('displays an error when end date of entry is greater than active entry start date', async () => { component.activeTimeEntry = entry; const newEntry = { entry: { diff --git a/src/app/modules/time-entries/pages/time-entries.component.ts b/src/app/modules/time-entries/pages/time-entries.component.ts index d62e3ec7e..95d8270b6 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.ts @@ -100,15 +100,17 @@ export class TimeEntriesComponent implements OnInit, OnDestroy { } saveEntry(event: SaveEntryEvent): void { - if (this.activeTimeEntry !== null && this.activeTimeEntry !== undefined) { + if (this.activeTimeEntry) { const startDateAsLocalDate = new Date(event.entry.start_date); const endDateAsLocalDate = new Date(event.entry.end_date); const activeEntryAsLocalDate = new Date(this.activeTimeEntry.start_date); - const isEditingActiveEntry = this.entryId === this.activeTimeEntry.id; - if (!isEditingActiveEntry && (startDateAsLocalDate > activeEntryAsLocalDate || endDateAsLocalDate > activeEntryAsLocalDate)) { - this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.'); - } else { + const isEditingEntryEqualToActiveEntry = this.entryId === this.activeTimeEntry.id; + const isStartDateLowerThanActiveEntry = startDateAsLocalDate < activeEntryAsLocalDate; + const isEndDateLowerThanActiveEntry = endDateAsLocalDate < activeEntryAsLocalDate; + if(isEditingEntryEqualToActiveEntry && (isStartDateLowerThanActiveEntry || isEndDateLowerThanActiveEntry)){ this.doSave(event); + } else { + this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.'); } } else { this.doSave(event); From 97a55177a87f0cd3e1617e88d74e07b507255c6f Mon Sep 17 00:00:00 2001 From: Guido Quezada Date: Fri, 11 Dec 2020 11:32:32 -0500 Subject: [PATCH 07/23] TT-00 fix: refactor condition --- .../time-entries/pages/time-entries.component.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app/modules/time-entries/pages/time-entries.component.ts b/src/app/modules/time-entries/pages/time-entries.component.ts index 95d8270b6..5116b3254 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.ts @@ -105,12 +105,12 @@ export class TimeEntriesComponent implements OnInit, OnDestroy { const endDateAsLocalDate = new Date(event.entry.end_date); const activeEntryAsLocalDate = new Date(this.activeTimeEntry.start_date); const isEditingEntryEqualToActiveEntry = this.entryId === this.activeTimeEntry.id; - const isStartDateLowerThanActiveEntry = startDateAsLocalDate < activeEntryAsLocalDate; - const isEndDateLowerThanActiveEntry = endDateAsLocalDate < activeEntryAsLocalDate; - if(isEditingEntryEqualToActiveEntry && (isStartDateLowerThanActiveEntry || isEndDateLowerThanActiveEntry)){ - this.doSave(event); - } else { + const isStartDateGreaterThanActiveEntry = startDateAsLocalDate > activeEntryAsLocalDate; + const isEndDateGreaterThanActiveEntry = endDateAsLocalDate > activeEntryAsLocalDate; + if(!isEditingEntryEqualToActiveEntry && (isStartDateGreaterThanActiveEntry || isEndDateGreaterThanActiveEntry)){ this.toastrService.error('You are on the clock and this entry overlaps it, try with earlier times.'); + } else { + this.doSave(event); } } else { this.doSave(event); From ace87e3c1eae5180095de2409d9c8cd7fb1db574 Mon Sep 17 00:00:00 2001 From: PaulRC-ioet Date: Thu, 10 Dec 2020 10:07:15 -0500 Subject: [PATCH 08/23] TT-65 feat: Change Design of Time In Fields and add waitForAsync in tests --- package-lock.json | 44 ++++++++++++++- package.json | 7 ++- src/app/app.component.spec.ts | 4 +- src/app/app.module.ts | 2 + .../activity-list.component.spec.ts | 4 +- .../create-activity.component.spec.ts | 4 +- .../activities-management.component.spec.ts | 4 +- .../create-customer/create-customer.spec.ts | 4 +- .../customer-list.component.spec.ts | 4 +- ...gement-customer-projects.component.spec.ts | 4 +- .../create-project-type.component.spec.ts | 4 +- .../project-type-list.component.spec.ts | 4 +- .../create-project.component.spec.ts | 4 +- .../pages/customer.component.spec.ts | 4 +- src/app/modules/home/home.component.spec.ts | 4 +- src/app/modules/login/login.component.spec.ts | 4 +- .../time-entries-table.component.spec.ts | 6 +- .../time-range.component.spec.ts | 4 +- .../reports/pages/reports.component.spec.ts | 6 +- .../components/clock/clock.component.spec.ts | 4 +- .../details-fields.component.html | 42 ++++---------- .../details-fields.component.spec.ts | 15 ++--- .../details-fields.component.ts | 8 +-- .../dialog/dialog.component.spec.ts | 4 +- .../empty-state/empty-state.component.spec.ts | 4 +- .../input-date/input-date.component.spec.ts | 4 +- .../input-label/input-label.component.spec.ts | 6 +- .../loading-bar/loading-bar.component.spec.ts | 4 +- .../month-picker.component.spec.ts | 4 +- .../navbar/navbar.component.spec.ts | 4 +- .../search/search.component.spec.ts | 4 +- .../sidebar/sidebar.component.spec.ts | 4 +- .../technologies.component.spec.ts | 4 +- .../components/user/user.component.spec.ts | 4 +- .../entry-fields/entry-fields.component.html | 36 ++++++------ .../entry-fields.component.spec.ts | 55 ++++++++++++++----- .../entry-fields/entry-fields.component.ts | 17 +++++- .../project-list-hover.component.spec.ts | 4 +- .../time-entries-summary.component.spec.ts | 4 +- .../pages/time-clock.component.spec.ts | 4 +- .../pages/time-entries.component.html | 2 +- .../pages/time-entries.component.spec.ts | 15 ++--- .../users-list/users-list.component.spec.ts | 4 +- .../users/pages/users.component.spec.ts | 4 +- src/styles.scss | 8 +++ 45 files changed, 232 insertions(+), 157 deletions(-) diff --git a/package-lock.json b/package-lock.json index fc2a348d6..6084b8d87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3652,6 +3652,11 @@ "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", "dev": true }, + "@types/luxon": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-1.11.1.tgz", + "integrity": "sha512-XBHQ7rzpOHyJudEQcMyoT67Np61FTb6S2jWqWQER/U7H2NAS+dpC8wv5T+6ygV5g/yJQdaojQbsJQiweool0Aw==" + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -10200,6 +10205,11 @@ "yallist": "^4.0.0" } }, + "luxon": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.24.0.tgz", + "integrity": "sha512-PNeB5cFbBtmuS137OuEdaJnCMTMPS2vz9hnM1Zl6tUIuYdtUgEhMqfVZ7yxX0jHEGx6rp757ECe7cdZxDgq2Tg==" + }, "macos-release": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.4.1.tgz", @@ -10879,6 +10889,21 @@ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, + "ngx-cookie-service": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/ngx-cookie-service/-/ngx-cookie-service-11.0.2.tgz", + "integrity": "sha512-nsjzdcjK+gNAweE/DDdnOyHo04jlxTeMXOL/oJNp8MHtOTvCXnOtIFYgq4Sb2JU6UXTovO9tHEMIf9TxjlsdgQ==", + "requires": { + "tslib": "^2.0.0" + }, + "dependencies": { + "tslib": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.3.tgz", + "integrity": "sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ==" + } + } + }, "ngx-mask": { "version": "9.1.4", "resolved": "https://registry.npmjs.org/ngx-mask/-/ngx-mask-9.1.4.tgz", @@ -10887,6 +10912,16 @@ "tslib": "^1.10.0" } }, + "ngx-material-timepicker": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/ngx-material-timepicker/-/ngx-material-timepicker-5.5.3.tgz", + "integrity": "sha512-Ua6eNNNneHS8S1/3Tn2dUOnLdZ4k6MhQqvLM/eFVoeF0WF+q/uK1DAH8eAki3HW1ogq2oDWnVRSeXvvZGJldhQ==", + "requires": { + "@types/luxon": "1.11.1", + "luxon": "1.24.0", + "tslib": "^1.9.0" + } + }, "ngx-pagination": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ngx-pagination/-/ngx-pagination-5.0.0.tgz", @@ -17148,7 +17183,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, "requires": { "safe-buffer": "^5.1.0" } @@ -21039,6 +21073,14 @@ "ajv-keywords": "^3.1.0" } }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "requires": { + "randombytes": "^2.1.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", diff --git a/package.json b/package.json index ef0b24bb5..837ebb0f2 100644 --- a/package.json +++ b/package.json @@ -21,13 +21,13 @@ "@angular/platform-browser": "~10.2.2", "@angular/platform-browser-dynamic": "~10.2.2", "@angular/router": "~10.2.2", + "@azure/app-configuration": "^1.1.0", + "@azure/identity": "^1.1.0", "@ngrx/effects": "^10.0.1", "@ngrx/store": "^10.0.1", "@ngrx/store-devtools": "^10.0.1", "@types/datatables.net-buttons": "^1.4.3", "angular-datatables": "^9.0.2", - "@azure/app-configuration": "^1.1.0", - "@azure/identity": "^1.1.0", "bootstrap": "^4.4.1", "datatables.net": "^1.10.21", "datatables.net-buttons": "^1.6.2", @@ -40,6 +40,7 @@ "msal": "^1.2.1", "ngx-cookie-service": "^11.0.2", "ngx-mask": "^9.1.2", + "ngx-material-timepicker": "^5.5.3", "ngx-pagination": "^5.0.0", "ngx-toastr": "^12.0.1", "rxjs": "~6.6.3", @@ -95,7 +96,7 @@ }, "config": { "commit-message-validator": { - "pattern": "^(fix: #|feat: #|perf: #|build: #|ci: #|docs: #|refactor: #|style: #|test: #)[0-9].*", + "pattern": "^(TT-)[0-9].*(fix: |feat: |perf: |build: |ci: |docs: |refactor: |style: |test: )", "errorMessage": "Your commit message needs to start with fix:, feat:, or perf: followed by issue number, e.g. fix: #43 any commit message" } }, diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts index 9b475cd88..701bf65b4 100644 --- a/src/app/app.component.spec.ts +++ b/src/app/app.component.spec.ts @@ -1,9 +1,9 @@ -import { TestBed, async } from '@angular/core/testing'; +import { TestBed, waitForAsync } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AppComponent } from './app.component'; describe('AppComponent', () => { - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule diff --git a/src/app/app.module.ts b/src/app/app.module.ts index eccd6efaf..a66e2dbe0 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -72,6 +72,7 @@ import { DialogComponent } from './modules/shared/components/dialog/dialog.compo import { LoadingBarComponent } from './modules/shared/components/loading-bar/loading-bar.component'; import { UsersComponent } from './modules/users/pages/users.component'; import { UsersListComponent } from './modules/users/components/users-list/users-list.component'; +import {NgxMaterialTimepickerModule} from 'ngx-material-timepicker'; const maskConfig: Partial = { validation: false, @@ -135,6 +136,7 @@ const maskConfig: Partial = { NgxPaginationModule, DataTablesModule, AutocompleteLibModule, + NgxMaterialTimepickerModule, StoreModule.forRoot(reducers, { metaReducers, }), diff --git a/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts b/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts index 1006dd9e6..0ebe48512 100644 --- a/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts +++ b/src/app/modules/activities-management/components/activity-list/activity-list.component.spec.ts @@ -1,5 +1,5 @@ import { provideMockStore, MockStore } from '@ngrx/store/testing'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { allActivities } from './../../store/activity-management.selectors'; import { ActivityState } from './../../store/activity-management.reducers'; @@ -19,7 +19,7 @@ describe('ActivityListComponent', () => { activityIdToEdit: '', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ActivityListComponent], providers: [provideMockStore({ initialState: state })], diff --git a/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts b/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts index 38f1fe8ce..7629e0c67 100644 --- a/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts +++ b/src/app/modules/activities-management/components/create-activity/create-activity.component.spec.ts @@ -1,5 +1,5 @@ import { FormBuilder } from '@angular/forms'; -import { async, TestBed, ComponentFixture } from '@angular/core/testing'; +import { waitForAsync, TestBed, ComponentFixture } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { CreateActivityComponent } from './create-activity.component'; @@ -36,7 +36,7 @@ describe('CreateActivityComponent', () => { description: 'It is good for learning', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [CreateActivityComponent], providers: [FormBuilder, provideMockStore({ initialState: state })], diff --git a/src/app/modules/activities-management/pages/activities-management.component.spec.ts b/src/app/modules/activities-management/pages/activities-management.component.spec.ts index 223e7999b..92f8a918a 100644 --- a/src/app/modules/activities-management/pages/activities-management.component.spec.ts +++ b/src/app/modules/activities-management/pages/activities-management.component.spec.ts @@ -1,11 +1,11 @@ -import { async, TestBed, ComponentFixture } from '@angular/core/testing'; +import { waitForAsync, TestBed, ComponentFixture } from '@angular/core/testing'; import { ActivitiesManagementComponent } from './activities-management.component'; describe('ActivitiesManagementComponent', () => { let component: ActivitiesManagementComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [], declarations: [ActivitiesManagementComponent] diff --git a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts index 7f003f092..df28e9d44 100644 --- a/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts +++ b/src/app/modules/customer-management/components/customer-info/components/create-customer/create-customer.spec.ts @@ -1,6 +1,6 @@ import { LoadCustomerProjects, CleanCustomerProjects } from './../../../projects/components/store/project.actions'; import { LoadProjectTypes, CleanProjectTypes } from './../../../projects-type/store/project-type.actions'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormBuilder } from '@angular/forms'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; @@ -27,7 +27,7 @@ describe('CreateCustomerComponent', () => { description: 'bb', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [CreateCustomerComponent], providers: [ diff --git a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts index 88851ae6b..ce7548086 100644 --- a/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts +++ b/src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { NgxPaginationModule } from 'ngx-pagination'; @@ -29,7 +29,7 @@ describe('CustomerTableListComponent', () => { customerId: '', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [NgxPaginationModule, DataTablesModule], declarations: [CustomerListComponent], diff --git a/src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.spec.ts b/src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.spec.ts index 3a730721d..697901557 100644 --- a/src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.spec.ts +++ b/src/app/modules/customer-management/components/management-customer-projects/management-customer-projects.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ManagementCustomerProjectsComponent } from './management-customer-projects.component'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; @@ -17,7 +17,7 @@ describe('ManagmentCustomerProjectsComponent', () => { customerId: '', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ManagementCustomerProjectsComponent], providers: [ diff --git a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts index d504ee667..10aca04b2 100644 --- a/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts +++ b/src/app/modules/customer-management/components/projects-type/components/create-project-type/create-project-type.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormBuilder } from '@angular/forms'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; @@ -38,7 +38,7 @@ describe('InputProjectTypeComponent', () => { description: 'It is good for learning', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [CreateProjectTypeComponent], providers: [FormBuilder, provideMockStore({ initialState: state })], diff --git a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts index dcc82f0c3..e6b23b93f 100644 --- a/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts +++ b/src/app/modules/customer-management/components/projects-type/components/project-type-list/project-type-list.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { NgxPaginationModule } from 'ngx-pagination'; @@ -19,7 +19,7 @@ describe('ProjectTypeTableListComponent', () => { projectTypeIdToEdit: '', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [NgxPaginationModule], declarations: [ProjectTypeListComponent], diff --git a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts index fa7325496..d4789cc79 100644 --- a/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts +++ b/src/app/modules/customer-management/components/projects/components/create-project/create-project.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { FormBuilder } from '@angular/forms'; import { Subscription } from 'rxjs'; @@ -35,7 +35,7 @@ describe('InputProjectComponent', () => { project_type_id: '123', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [CreateProjectComponent], providers: [FormBuilder, provideMockStore({ initialState: state })], diff --git a/src/app/modules/customer-management/pages/customer.component.spec.ts b/src/app/modules/customer-management/pages/customer.component.spec.ts index 7cddc30c2..4e37ac34c 100644 --- a/src/app/modules/customer-management/pages/customer.component.spec.ts +++ b/src/app/modules/customer-management/pages/customer.component.spec.ts @@ -1,7 +1,7 @@ import { SetCustomerToEdit } from 'src/app/modules/customer-management/store'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { Customer } from 'src/app/modules/shared/models'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { CustomerComponent } from './customer.component'; @@ -10,7 +10,7 @@ describe('CustomerComponent', () => { let fixture: ComponentFixture; let store: MockStore; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [CustomerComponent], providers: [provideMockStore({ initialState: {} })], diff --git a/src/app/modules/home/home.component.spec.ts b/src/app/modules/home/home.component.spec.ts index 86774ae21..a0ad3bf0b 100644 --- a/src/app/modules/home/home.component.spec.ts +++ b/src/app/modules/home/home.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { HomeComponent } from './home.component'; @@ -6,7 +6,7 @@ describe('HomeComponent', () => { let component: HomeComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ HomeComponent ] }) diff --git a/src/app/modules/login/login.component.spec.ts b/src/app/modules/login/login.component.spec.ts index b1ded62e1..ff90fa6a5 100644 --- a/src/app/modules/login/login.component.spec.ts +++ b/src/app/modules/login/login.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed, inject } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed, inject } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { AzureAdB2CService } from '../../modules/login/services/azure.ad.b2c.service'; import { of } from 'rxjs'; @@ -22,7 +22,7 @@ describe('LoginComponent', () => { } }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ LoginComponent ], diff --git a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts index 0c516befc..b58b13050 100644 --- a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts +++ b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { Entry } from 'src/app/modules/shared/models'; import { SubstractDatePipe } from 'src/app/modules/shared/pipes/substract-date/substract-date.pipe'; @@ -41,7 +41,7 @@ describe('Reports Page', () => { } }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [], declarations: [TimeEntriesTableComponent, SubstractDatePipe], @@ -51,7 +51,7 @@ describe('Reports Page', () => { })); - beforeEach(async(() => { + beforeEach(waitForAsync(() => { fixture = TestBed.createComponent(TimeEntriesTableComponent); component = fixture.componentInstance; store.setState(state); diff --git a/src/app/modules/reports/components/time-range-form/time-range.component.spec.ts b/src/app/modules/reports/components/time-range-form/time-range.component.spec.ts index 42c708e0b..8e78d3a00 100644 --- a/src/app/modules/reports/components/time-range-form/time-range.component.spec.ts +++ b/src/app/modules/reports/components/time-range-form/time-range.component.spec.ts @@ -1,5 +1,5 @@ import { ToastrService, IndividualConfig } from 'ngx-toastr'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { TimeRangeFormComponent } from './time-range-form.component'; import { EntryState } from '../../../time-clock/store/entry.reducer'; @@ -39,7 +39,7 @@ describe('Reports Page', () => { entriesForReport: [timeEntry], }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [FormsModule, ReactiveFormsModule], declarations: [TimeRangeFormComponent, InputDateComponent], diff --git a/src/app/modules/reports/pages/reports.component.spec.ts b/src/app/modules/reports/pages/reports.component.spec.ts index e60f52ad4..4a131f56e 100644 --- a/src/app/modules/reports/pages/reports.component.spec.ts +++ b/src/app/modules/reports/pages/reports.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ReportsComponent } from './reports.component'; @@ -6,7 +6,7 @@ describe('ReportsComponent', () => { let component: ReportsComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ReportsComponent], }).compileComponents(); @@ -23,7 +23,7 @@ describe('ReportsComponent', () => { expect(component).toBeTruthy(); }); - it('should have form and datatable components', async(() => { + it('should have form and datatable components', waitForAsync(() => { fixture.detectChanges(); const compile = fixture.debugElement.nativeElement; diff --git a/src/app/modules/shared/components/clock/clock.component.spec.ts b/src/app/modules/shared/components/clock/clock.component.spec.ts index 47455782f..a2ef16f41 100644 --- a/src/app/modules/shared/components/clock/clock.component.spec.ts +++ b/src/app/modules/shared/components/clock/clock.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { ClockComponent } from './clock.component'; @@ -6,7 +6,7 @@ describe('ClockComponent', () => { let component: ClockComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ ClockComponent ] }) diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.html b/src/app/modules/shared/components/details-fields/details-fields.component.html index 7e3949525..17679fc87 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.html +++ b/src/app/modules/shared/components/details-fields/details-fields.component.html @@ -88,22 +88,11 @@
- +
@@ -125,22 +114,11 @@
- +
diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts index 96c5cd9c6..fde879bd8 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts @@ -1,5 +1,5 @@ import { formatDate } from '@angular/common'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { ActionsSubject } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; @@ -18,6 +18,7 @@ import { TechnologiesComponent } from './../technologies/technologies.component' import { DetailsFieldsComponent } from './details-fields.component'; import { ProjectSelectedEvent } from './project-selected-event'; import { SaveEntryEvent } from './save-entry-event'; +import { NgxMaterialTimepickerModule } from 'ngx-material-timepicker'; describe('DetailsFieldsComponent', () => { @@ -68,13 +69,13 @@ describe('DetailsFieldsComponent', () => { uri: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), end_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), - start_hour: '00:00:00', - end_hour: '00:00:00', + start_hour: '00:00', + end_hour: '00:00', description: '', technology: '', }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [DetailsFieldsComponent, TechnologiesComponent], providers: [ @@ -82,7 +83,7 @@ describe('DetailsFieldsComponent', () => { { provide: ActionsSubject, useValue: actionSub }, { provide: ToastrService, useValue: toastrServiceStub } ], - imports: [FormsModule, ReactiveFormsModule, AutocompleteLibModule], + imports: [FormsModule, ReactiveFormsModule, AutocompleteLibModule, NgxMaterialTimepickerModule], }).compileComponents(); store = TestBed.inject(MockStore); mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies); @@ -180,8 +181,8 @@ describe('DetailsFieldsComponent', () => { uri: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), end_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), - start_hour: '00:00:00', - end_hour: '00:00:00', + start_hour: '00:00', + end_hour: '00:00', description: '', technology: '', }; diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.ts b/src/app/modules/shared/components/details-fields/details-fields.component.ts index a24baa4ba..d4a8c6616 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.ts @@ -133,8 +133,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { description: this.entryToEdit.description, start_date: formatDate(get(this.entryToEdit, 'start_date', '') , 'yyyy-MM-dd', 'en'), end_date: formatDate(get(this.entryToEdit, 'end_date'), 'yyyy-MM-dd', 'en'), - start_hour: formatDate(get(this.entryToEdit, 'start_date', '00:00:00'), 'HH:mm:ss', 'en'), - end_hour: formatDate(get(this.entryToEdit, 'end_date', '00:00:00'), 'HH:mm:ss', 'en'), + start_hour: formatDate(get(this.entryToEdit, 'start_date', '00:00'), 'HH:mm', 'en'), + end_hour: formatDate(get(this.entryToEdit, 'end_date', '00:00'), 'HH:mm', 'en'), uri: this.entryToEdit.uri, technology: '', }); @@ -152,8 +152,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { description: '', start_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), end_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), - start_hour: '00:00:00', - end_hour: '00:00:00', + start_hour: '00:00', + end_hour: '00:00', uri: '', technology: '', }); diff --git a/src/app/modules/shared/components/dialog/dialog.component.spec.ts b/src/app/modules/shared/components/dialog/dialog.component.spec.ts index c18602ec5..4a622c8f3 100644 --- a/src/app/modules/shared/components/dialog/dialog.component.spec.ts +++ b/src/app/modules/shared/components/dialog/dialog.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { DialogComponent } from './dialog.component'; @@ -6,7 +6,7 @@ describe('DialogComponent', () => { let component: DialogComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ DialogComponent ] }) diff --git a/src/app/modules/shared/components/empty-state/empty-state.component.spec.ts b/src/app/modules/shared/components/empty-state/empty-state.component.spec.ts index c5cd9ed4e..f3a00de92 100644 --- a/src/app/modules/shared/components/empty-state/empty-state.component.spec.ts +++ b/src/app/modules/shared/components/empty-state/empty-state.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { EmptyStateComponent } from './empty-state.component'; @@ -6,7 +6,7 @@ describe('EmptyStateComponent', () => { let component: EmptyStateComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ EmptyStateComponent ] }) diff --git a/src/app/modules/shared/components/input-date/input-date.component.spec.ts b/src/app/modules/shared/components/input-date/input-date.component.spec.ts index f9af5f1bc..fe0662d49 100644 --- a/src/app/modules/shared/components/input-date/input-date.component.spec.ts +++ b/src/app/modules/shared/components/input-date/input-date.component.spec.ts @@ -1,4 +1,4 @@ -import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; +import {waitForAsync, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {InputDateComponent} from './input-date.component'; describe('InputDateComponent', () => { @@ -6,7 +6,7 @@ describe('InputDateComponent', () => { let fixture: ComponentFixture; let input; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [InputDateComponent] }).compileComponents(); diff --git a/src/app/modules/shared/components/input-label/input-label.component.spec.ts b/src/app/modules/shared/components/input-label/input-label.component.spec.ts index 7582ed692..374587057 100644 --- a/src/app/modules/shared/components/input-label/input-label.component.spec.ts +++ b/src/app/modules/shared/components/input-label/input-label.component.spec.ts @@ -1,4 +1,4 @@ -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; import {InputLabelComponent} from './input-label.component'; @@ -6,7 +6,7 @@ describe('InputLabelComponent', () => { let component: InputLabelComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [InputLabelComponent] }).compileComponents(); @@ -22,7 +22,7 @@ describe('InputLabelComponent', () => { expect(component).toBeTruthy(); }); - it('should insert the provided text into the component', async(() => { + it('should insert the provided text into the component', waitForAsync(() => { const anyLabelText = 'Any random label'; component.text = anyLabelText; diff --git a/src/app/modules/shared/components/loading-bar/loading-bar.component.spec.ts b/src/app/modules/shared/components/loading-bar/loading-bar.component.spec.ts index 9ee4f6d0e..1dc3c0156 100644 --- a/src/app/modules/shared/components/loading-bar/loading-bar.component.spec.ts +++ b/src/app/modules/shared/components/loading-bar/loading-bar.component.spec.ts @@ -1,11 +1,11 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { LoadingBarComponent } from './loading-bar.component'; describe('LoadingBarComponent', () => { let component: LoadingBarComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [LoadingBarComponent] }).compileComponents(); diff --git a/src/app/modules/shared/components/month-picker/month-picker.component.spec.ts b/src/app/modules/shared/components/month-picker/month-picker.component.spec.ts index a81dc612c..c8d29053e 100644 --- a/src/app/modules/shared/components/month-picker/month-picker.component.spec.ts +++ b/src/app/modules/shared/components/month-picker/month-picker.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { MonthPickerComponent } from './month-picker.component'; @@ -6,7 +6,7 @@ describe('MonthPickerComponent', () => { let component: MonthPickerComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ MonthPickerComponent ] }) diff --git a/src/app/modules/shared/components/navbar/navbar.component.spec.ts b/src/app/modules/shared/components/navbar/navbar.component.spec.ts index 4e5f590eb..ca8f116c8 100644 --- a/src/app/modules/shared/components/navbar/navbar.component.spec.ts +++ b/src/app/modules/shared/components/navbar/navbar.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { NavbarComponent } from './navbar.component'; @@ -6,7 +6,7 @@ describe('NavbarComponent', () => { let component: NavbarComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ NavbarComponent ] }) diff --git a/src/app/modules/shared/components/search/search.component.spec.ts b/src/app/modules/shared/components/search/search.component.spec.ts index 6e93ca539..8c1298424 100644 --- a/src/app/modules/shared/components/search/search.component.spec.ts +++ b/src/app/modules/shared/components/search/search.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { SearchComponent } from './search.component'; @@ -6,7 +6,7 @@ describe('SearchComponent', () => { let component: SearchComponent; let fixture: ComponentFixture; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [SearchComponent], }).compileComponents(); diff --git a/src/app/modules/shared/components/sidebar/sidebar.component.spec.ts b/src/app/modules/shared/components/sidebar/sidebar.component.spec.ts index d6303868c..65c0bff28 100644 --- a/src/app/modules/shared/components/sidebar/sidebar.component.spec.ts +++ b/src/app/modules/shared/components/sidebar/sidebar.component.spec.ts @@ -1,5 +1,5 @@ import {AzureAdB2CService} from 'src/app/modules/login/services/azure.ad.b2c.service'; -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; import {SidebarComponent} from './sidebar.component'; import {RouterTestingModule} from '@angular/router/testing'; @@ -25,7 +25,7 @@ describe('SidebarComponent', () => { } }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [SidebarComponent], providers: [ diff --git a/src/app/modules/shared/components/technologies/technologies.component.spec.ts b/src/app/modules/shared/components/technologies/technologies.component.spec.ts index 8f9cf0de4..22abff7cf 100644 --- a/src/app/modules/shared/components/technologies/technologies.component.spec.ts +++ b/src/app/modules/shared/components/technologies/technologies.component.spec.ts @@ -1,4 +1,4 @@ -import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing'; import {MockStore, provideMockStore} from '@ngrx/store/testing'; import {FormsModule, ReactiveFormsModule} from '@angular/forms'; @@ -20,7 +20,7 @@ describe('Technologies component', () => { } }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [TechnologiesComponent], providers: [provideMockStore({initialState: state})], diff --git a/src/app/modules/shared/components/user/user.component.spec.ts b/src/app/modules/shared/components/user/user.component.spec.ts index 8a0bd0435..2d82a8c36 100644 --- a/src/app/modules/shared/components/user/user.component.spec.ts +++ b/src/app/modules/shared/components/user/user.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { of } from 'rxjs'; import { UserComponent } from './user.component'; import { AzureAdB2CService } from '../../../login/services/azure.ad.b2c.service'; @@ -18,7 +18,7 @@ describe('UserComponent', () => { }, }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [UserComponent], imports: [AppRoutingModule], diff --git a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.html b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.html index c358c4dcb..9c7821cf5 100644 --- a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.html +++ b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.html @@ -1,4 +1,4 @@ -
+
+ +
+
+ +
+
+ +
+
+ +
+
{ @@ -94,10 +95,10 @@ describe('EntryFieldsComponent', () => { description: 'description for active entry', uri: 'abc', start_date : moment().format('YYYY-MM-DD'), - start_hour : moment().format('HH:mm:ss'), + start_hour : moment().format('HH:mm'), }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [EntryFieldsComponent], providers: [ @@ -105,7 +106,7 @@ describe('EntryFieldsComponent', () => { { provide: ActionsSubject, useValue: actionSub }, { provide: ToastrService, useValue: toastrServiceStub } ], - imports: [FormsModule, ReactiveFormsModule], + imports: [FormsModule, ReactiveFormsModule, NgxMaterialTimepickerModule], }).compileComponents(); store = TestBed.inject(MockStore); entryForm = TestBed.inject(FormBuilder); @@ -141,7 +142,7 @@ describe('EntryFieldsComponent', () => { description: entryDataForm.description, uri: entryDataForm.uri, activity_id: entryDataForm.activity_id, - start_hour: formatDate(entry.start_date, 'HH:mm:ss', 'en'), + start_hour: formatDate(entry.start_date, 'HH:mm', 'en'), start_date : moment().format('YYYY-MM-DD'), } ); @@ -154,11 +155,12 @@ describe('EntryFieldsComponent', () => { component.setDataToUpdate(entry); spyOn(toastrServiceStub, 'error'); - const hourInTheFuture = moment().add(1, 'hours').format('HH:mm:ss'); + const hourInTheFuture = moment().add(1, 'hours').format('HH:mm'); component.entryForm.patchValue({ start_hour : hourInTheFuture}); component.onUpdateStartHour(); expect(toastrServiceStub.error).toHaveBeenCalled(); + expect(component.showtimeInbuttons).toEqual(false); }); it('Displays an error message when the active entry has start_time before the start_time of another entry', () => { @@ -167,11 +169,35 @@ describe('EntryFieldsComponent', () => { component.setDataToUpdate(entry); spyOn(toastrServiceStub, 'error'); - const hourInThePast = moment().subtract(6, 'hour').format('HH:mm:ss'); + const hourInThePast = moment().subtract(6, 'hour').format('HH:mm'); component.entryForm.patchValue({ start_hour : hourInThePast}); component.onUpdateStartHour(); expect(toastrServiceStub.error).toHaveBeenCalled(); + expect(component.showtimeInbuttons).toEqual(false); + }); + + it('should show time In buttons when time is modified', () => { + component.activeTimeInButtons(); + + expect(component.showtimeInbuttons).toEqual(true); + }); + + it('should go back to the starting time and disappear buttons', () => { + component.newData = entry; + component.activeEntry = entry ; + component.setDataToUpdate(entry); + const updatedTime = moment().format('HH:mm'); + component.entryForm.patchValue({ start_hour : updatedTime}); + spyOn(component.entryForm, 'patchValue'); + component.cancelTimeInUpdate(); + + expect(component.showtimeInbuttons).toEqual(false); + expect(component.entryForm.patchValue).toHaveBeenCalledWith( + { + start_hour: component.newData.start_hour + } + ); }); it('should reset to current start_date when start_date has an error', () => { @@ -179,7 +205,7 @@ describe('EntryFieldsComponent', () => { component.activeEntry = entry ; component.setDataToUpdate(entry); - const updatedTime = moment().subtract(6, 'hours').format('HH:mm:ss'); + const updatedTime = moment().subtract(6, 'hours').format('HH:mm'); component.entryForm.patchValue({ start_hour : updatedTime}); spyOn(component.entryForm, 'patchValue'); @@ -190,6 +216,7 @@ describe('EntryFieldsComponent', () => { start_hour: component.newData.start_hour } ); + expect(component.showtimeInbuttons).toEqual(false); }); it('If start hour is in the future, reset to initial start_date in form', () => { @@ -197,7 +224,7 @@ describe('EntryFieldsComponent', () => { component.activeEntry = entry ; component.setDataToUpdate(entry); - const hourInTheFuture = moment().add(1, 'hours').format('HH:mm:ss'); + const hourInTheFuture = moment().add(1, 'hours').format('HH:mm'); component.entryForm.patchValue({ start_hour : hourInTheFuture}); spyOn(component.entryForm, 'patchValue'); @@ -208,23 +235,25 @@ describe('EntryFieldsComponent', () => { start_hour: component.newData.start_hour } ); + expect(component.showtimeInbuttons).toEqual(false); }); it('when a start hour is updated, then dispatch UpdateActiveEntry', () => { component.activeEntry = entry ; component.setDataToUpdate(entry); - const updatedTime = moment().format('HH:mm:ss'); + const updatedTime = moment().format('HH:mm'); component.entryForm.patchValue({ start_hour : updatedTime}); spyOn(store, 'dispatch'); component.onUpdateStartHour(); expect(store.dispatch).toHaveBeenCalled(); + expect(component.showtimeInbuttons).toEqual(false); }); - it('When start_time is updated, component.last_entry is equal to time entry in the position 1', async(() => { + it('When start_time is updated, component.last_entry is equal to time entry in the position 1', waitForAsync(() => { component.activeEntry = entry ; component.setDataToUpdate(entry); - const updatedTime = moment().format('HH:mm:ss'); + const updatedTime = moment().format('HH:mm'); component.entryForm.patchValue({ start_hour : updatedTime}); component.onUpdateStartHour(); @@ -236,7 +265,7 @@ describe('EntryFieldsComponent', () => { component.activeEntry = entry ; component.setDataToUpdate(entry); const lastEntry = state.entries.timeEntriesDataSource.data[1]; - const updatedTime = moment().subtract(4, 'hours').format('HH:mm:ss'); + const updatedTime = moment().subtract(4, 'hours').format('HH:mm'); const lastStartHourEntryEnteredTest = new Date(`${lastDate}T${updatedTime.trim()}`).toISOString(); component.entryForm.patchValue({ start_hour : updatedTime}); spyOn(store, 'dispatch'); diff --git a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts index 4f4dae138..a4be95175 100644 --- a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts +++ b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts @@ -30,6 +30,7 @@ export class EntryFieldsComponent implements OnInit { activeEntry; newData; lastEntry; + showtimeInbuttons = false; constructor( private formBuilder: FormBuilder, @@ -82,7 +83,7 @@ export class EntryFieldsComponent implements OnInit { uri: this.activeEntry.uri, activity_id: this.activeEntry.activity_id, start_date: this.activeEntry.start_date, - start_hour: formatDate(this.activeEntry.start_date, 'HH:mm:ss', 'en'), + start_hour: formatDate(this.activeEntry.start_date, 'HH:mm', 'en'), }; }); } @@ -102,7 +103,7 @@ export class EntryFieldsComponent implements OnInit { uri: entryData.uri, activity_id: entryData.activity_id, start_date: entryData.start_date, - start_hour: formatDate(entryData.start_date, 'HH:mm:ss', 'en'), + start_hour: formatDate(entryData.start_date, 'HH:mm', 'en'), }); if (entryData.technologies) { this.selectedTechnologies = entryData.technologies; @@ -128,6 +129,7 @@ export class EntryFieldsComponent implements OnInit { if (isEntryDateInTheFuture) { this.toastrService.error('You cannot start a time-entry in the future'); this.entryForm.patchValue({ start_hour: this.newData.start_hour }); + this.showtimeInbuttons = false; return; } @@ -136,10 +138,12 @@ export class EntryFieldsComponent implements OnInit { if (isEntryDateInLastStartDate) { this.toastrService.error('There is another time entry registered in this time range'); this.entryForm.patchValue({ start_hour: this.newData.start_hour }); + this.showtimeInbuttons = false; return; } this.entryForm.patchValue({ start_date: newHourEntered }); this.dispatchEntries(newHourEntered); + this.showtimeInbuttons = false; } private dispatchEntries(newHourEntered) { @@ -158,6 +162,15 @@ export class EntryFieldsComponent implements OnInit { }); } + activeTimeInButtons(){ + this.showtimeInbuttons = true; + } + + cancelTimeInUpdate(){ + this.entryForm.patchValue({ start_hour: this.newData.start_hour }); + this.showtimeInbuttons = false; + } + onTechnologyAdded($event: string[]) { this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, technologies: $event })); } diff --git a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts index 16f0ab1eb..c7dd88ef4 100644 --- a/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts +++ b/src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts @@ -1,7 +1,7 @@ import { ToastrService, IndividualConfig } from 'ngx-toastr'; import { SwitchTimeEntry, ClockIn } from './../../store/entry.actions'; import { FormBuilder } from '@angular/forms'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { AutocompleteLibModule } from 'angular-ng-autocomplete'; @@ -41,7 +41,7 @@ describe('ProjectListHoverComponent', () => { }, }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ProjectListHoverComponent, FilterProjectPipe], providers: [FormBuilder, provideMockStore({ initialState: state }), diff --git a/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts b/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts index 6b54036ed..00b5c9fab 100644 --- a/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts +++ b/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts @@ -1,4 +1,4 @@ -import { async, ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, discardPeriodicTasks, fakeAsync, TestBed, tick } from '@angular/core/testing'; import { ActionsSubject } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { interval } from 'rxjs'; @@ -50,7 +50,7 @@ describe('TimeEntriesSummaryComponent', () => { } }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ TimeEntriesSummaryComponent, TimeDetailsPipe ], providers: [provideMockStore({ initialState: state }), { provide: ActionsSubject, useValue: actionSub }], diff --git a/src/app/modules/time-clock/pages/time-clock.component.spec.ts b/src/app/modules/time-clock/pages/time-clock.component.spec.ts index 218d1eea1..1fa2476ee 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.spec.ts +++ b/src/app/modules/time-clock/pages/time-clock.component.spec.ts @@ -1,6 +1,6 @@ import { FormBuilder } from '@angular/forms'; import { StopTimeEntryRunning, EntryActionTypes, LoadEntriesSummary } from './../store/entry.actions'; -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { provideMockStore, MockStore } from '@ngrx/store/testing'; import { TimeClockComponent } from './time-clock.component'; @@ -48,7 +48,7 @@ describe('TimeClockComponent', () => { }, }; - beforeEach(async(() => { + beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], declarations: [TimeClockComponent, ProjectListHoverComponent, FilterProjectPipe, EntryFieldsComponent], diff --git a/src/app/modules/time-entries/pages/time-entries.component.html b/src/app/modules/time-entries/pages/time-entries.component.html index f2914e5e5..8928eb656 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.html +++ b/src/app/modules/time-entries/pages/time-entries.component.html @@ -58,7 +58,7 @@