From 93bf82c84cafd4d620ab402d338403406f71edda Mon Sep 17 00:00:00 2001 From: Sandro Castillo Date: Thu, 19 Nov 2020 15:27:31 -0500 Subject: [PATCH] fix: #571 test coverage --- package-lock.json | 82 ++++-------- package.json | 4 +- .../time-entries-table.component.spec.ts | 1 - .../time-range-form.component.ts | 5 +- .../reports/pages/reports.component.spec.ts | 2 +- .../details-fields.component.spec.ts | 9 +- .../details-fields.component.ts | 5 +- .../input-date/input-date.component.spec.ts | 2 +- .../sidebar/sidebar.component.spec.ts | 4 +- .../technologies.component.spec.ts | 2 +- .../substract-date/substract-date.pipe.ts | 5 +- .../time-range-form.component.html | 26 ---- .../time-range-form.component.ts | 50 -------- .../time-range.component.spec.ts | 121 ------------------ .../technology-report-table/data.json | 55 ++++++-- .../technology-report-table.component.html | 31 +++-- .../technology-report-table.component.scss | 18 +-- .../technology-report-table.component.spec.ts | 68 ++-------- .../technology-report-table.component.ts | 113 ++++------------ .../pages/technology-report.component.spec.ts | 34 +++++ .../technology-report.component.spect.ts | 0 .../pages/technology-report.component.ts | 3 +- .../technology-report.component.scss | 0 .../entry-fields.component.spec.ts | 5 +- .../entry-fields/entry-fields.component.ts | 3 +- src/environments/environment.ts | 2 + tsconfig.json | 1 - 27 files changed, 189 insertions(+), 462 deletions(-) delete mode 100644 src/app/modules/shared/time-range-form/time-range-form.component.html delete mode 100644 src/app/modules/shared/time-range-form/time-range-form.component.ts delete mode 100644 src/app/modules/shared/time-range-form/time-range.component.spec.ts create mode 100644 src/app/modules/technology-report/pages/technology-report.component.spec.ts delete mode 100644 src/app/modules/technology-report/pages/technology-report.component.spect.ts delete mode 100644 src/app/modules/technology-report/technology-report.component.scss diff --git a/package-lock.json b/package-lock.json index 5c098cafb..6de85b60d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4605,16 +4605,6 @@ "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npm.taobao.org/bindings/download/bindings-1.5.0.tgz", - "integrity": "sha1-EDU8npRTNLwFEabZCzj7x8nFBN8=", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bl": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz", @@ -5954,6 +5944,15 @@ "p-try": "^2.0.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==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "ssri": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.0.tgz", @@ -6449,25 +6448,6 @@ "jquery": ">=1.7" } }, - "datatables.net-responsive": { - "version": "2.2.6", - "resolved": "https://registry.npm.taobao.org/datatables.net-responsive/download/datatables.net-responsive-2.2.6.tgz", - "integrity": "sha1-dKSsDadoHrQnO401nxmO8t7ylx4=", - "requires": { - "datatables.net": "^1.10.15", - "jquery": ">=1.7" - } - }, - "datatables.net-responsive-dt": { - "version": "2.2.6", - "resolved": "https://registry.npm.taobao.org/datatables.net-responsive-dt/download/datatables.net-responsive-dt-2.2.6.tgz", - "integrity": "sha1-kbkI3w+AWg59s5vPokXMD+uP9I8=", - "requires": { - "datatables.net-dt": "^1.10.15", - "datatables.net-responsive": "2.2.6", - "jquery": ">=1.7" - } - }, "date-format": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/date-format/-/date-format-3.0.0.tgz", @@ -7722,13 +7702,6 @@ "schema-utils": "^2.6.5" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npm.taobao.org/file-uri-to-path/download/file-uri-to-path-1.0.0.tgz", - "integrity": "sha1-VTp7hEb/b2hDWcRF8eN6BdrMM90=", - "dev": true, - "optional": true - }, "file-url": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/file-url/-/file-url-3.0.0.tgz", @@ -18397,15 +18370,6 @@ } } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-4.0.0.tgz?cache=0&sync_timestamp=1599742605902&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-4.0.0.tgz", - "integrity": "sha1-tSXhI4SJpez8Qq+sw/6Z5mb0sao=", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "serve-index": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", @@ -19880,9 +19844,9 @@ } }, "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-4.0.0.tgz?cache=0&sync_timestamp=1599742605902&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-4.0.0.tgz", - "integrity": "sha1-tSXhI4SJpez8Qq+sw/6Z5mb0sao=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", "dev": true, "requires": { "randombytes": "^2.1.0" @@ -20755,7 +20719,6 @@ "dev": true, "optional": true, "requires": { - "bindings": "^1.5.0", "nan": "^2.12.1" } }, @@ -21076,15 +21039,6 @@ "ajv-keywords": "^3.1.0" } }, - "serialize-javascript": { - "version": "4.0.0", - "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-4.0.0.tgz?cache=0&sync_timestamp=1599742605902&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-4.0.0.tgz", - "integrity": "sha1-tSXhI4SJpez8Qq+sw/6Z5mb0sao=", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -21117,6 +21071,17 @@ "terser": "^4.1.2", "webpack-sources": "^1.4.0", "worker-farm": "^1.7.0" + }, + "dependencies": { + "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==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + } } }, "to-regex-range": { @@ -21315,7 +21280,6 @@ "dev": true, "optional": true, "requires": { - "bindings": "^1.5.0", "nan": "^2.12.1" } }, diff --git a/package.json b/package.json index eed42c9b8..1ed1698e3 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", 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 b58b13050..e9ad695b6 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 @@ -48,7 +48,6 @@ describe('Reports Page', () => { providers: [provideMockStore({ initialState: state })], }).compileComponents(); store = TestBed.inject(MockStore); - })); beforeEach(waitForAsync(() => { diff --git a/src/app/modules/reports/components/time-range-form/time-range-form.component.ts b/src/app/modules/reports/components/time-range-form/time-range-form.component.ts index 2785b7e19..87be577e0 100644 --- a/src/app/modules/reports/components/time-range-form/time-range-form.component.ts +++ b/src/app/modules/reports/components/time-range-form/time-range-form.component.ts @@ -2,6 +2,7 @@ import { ToastrService } from 'ngx-toastr'; import { formatDate } from '@angular/common'; import { Component, OnInit } from '@angular/core'; import { FormControl, FormGroup } from '@angular/forms'; +import { DATE_FORMAT } from 'src/environments/environment'; import * as entryActions from '../../../time-clock/store/entry.actions'; import {Store} from '@ngrx/store'; import {EntryState} from '../../../time-clock/store/entry.reducer'; @@ -28,8 +29,8 @@ export class TimeRangeFormComponent implements OnInit { setInitialDataOnScreen() { this.reportForm.setValue({ - startDate: formatDate(moment().startOf('week').toString(), 'yyyy-MM-dd', 'en'), - endDate: formatDate(moment().endOf('week').toString(), 'yyyy-MM-dd', 'en') + startDate: formatDate(moment().startOf('week').toString(), DATE_FORMAT, 'en'), + endDate: formatDate(moment().endOf('week').toString(), DATE_FORMAT, 'en') }); this.onSubmit(); } diff --git a/src/app/modules/reports/pages/reports.component.spec.ts b/src/app/modules/reports/pages/reports.component.spec.ts index 0c2da9019..4a131f56e 100644 --- a/src/app/modules/reports/pages/reports.component.spec.ts +++ b/src/app/modules/reports/pages/reports.component.spec.ts @@ -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/details-fields/details-fields.component.spec.ts b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts index 8fb37bee3..6e60e84c0 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 @@ -18,7 +18,8 @@ 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 { DATE_FORMAT } from 'src/environments/environment'; +import { DATE_FORMAT_YEAR } from 'src/environments/environment'; describe('DetailsFieldsComponent', () => { type Merged = TechnologyState & ProjectState & EntryState; @@ -66,7 +67,7 @@ describe('DetailsFieldsComponent', () => { project_name: '', activity_id: '', uri: '', - entry_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), + entry_date: formatDate(new Date(), DATE_FORMAT, 'en'), start_hour: '00:00:00', end_hour: '00:00:00', description: '', @@ -176,7 +177,7 @@ describe('DetailsFieldsComponent', () => { project_name: '', activity_id: '', uri: '', - entry_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), + entry_date: formatDate(new Date(), DATE_FORMAT, 'en'), start_hour: '00:00:00', end_hour: '00:00:00', description: '', @@ -310,7 +311,7 @@ describe('DetailsFieldsComponent', () => { it('displays error message when the date selected is in the future', () => { spyOn(toastrServiceStub, 'error'); - const futureDate = moment().add(1, 'days').format('YYYY-MM-DD'); + const futureDate = moment().add(1, 'days').format(DATE_FORMAT_YEAR); component.entryForm.setValue({ ...formValues, entry_date: futureDate }); component.onSubmit(); 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 1c8e37711..1bd68ef33 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 @@ -17,6 +17,7 @@ import { TechnologyState } from '../../store/technology.reducers'; import { EntryActionTypes } from './../../../time-clock/store/entry.actions'; import { SaveEntryEvent } from './save-entry-event'; import { ProjectSelectedEvent } from './project-selected-event'; +import { DATE_FORMAT } from 'src/environments/environment'; type Merged = TechnologyState & ProjectState & ActivityState & EntryState; @@ -129,7 +130,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { project_id: this.entryToEdit.project_id, activity_id: this.entryToEdit.activity_id, description: this.entryToEdit.description, - entry_date: this.entryToEdit.start_date ? formatDate(this.entryToEdit.start_date, 'yyyy-MM-dd', 'en') : '', + entry_date: this.entryToEdit.start_date ? formatDate(this.entryToEdit.start_date, DATE_FORMAT, 'en') : '', start_hour: this.entryToEdit.start_date ? formatDate(this.entryToEdit.start_date, 'HH:mm:ss', 'en') : '00:00:00', end_hour: this.entryToEdit.end_date ? formatDate(this.entryToEdit.end_date, 'HH:mm:ss', 'en') : '00:00:00', uri: this.entryToEdit.uri, @@ -147,7 +148,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { project_id: '', activity_id: '', description: '', - entry_date: formatDate(new Date(), 'yyyy-MM-dd', 'en'), + entry_date: formatDate(new Date(), DATE_FORMAT, 'en'), start_hour: '00:00:00', end_hour: '00:00:00', uri: '', 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 ad08a01fb..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', () => { 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 884ef0529..1ccb0b7f2 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'; @@ -56,7 +56,7 @@ describe('SidebarComponent', () => { component.getSidebarItems(); const menuItems = component.itemsSidebar; - expect(menuItems.length).toBe(6); + expect(menuItems.length).toBe(7); }); it('non admin users have two menu items', () => { 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 d4fc12835..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'; diff --git a/src/app/modules/shared/pipes/substract-date/substract-date.pipe.ts b/src/app/modules/shared/pipes/substract-date/substract-date.pipe.ts index 6ca03db08..3bec888d0 100644 --- a/src/app/modules/shared/pipes/substract-date/substract-date.pipe.ts +++ b/src/app/modules/shared/pipes/substract-date/substract-date.pipe.ts @@ -1,6 +1,7 @@ import { NumberFormatter } from './../../formatters/number.formatter'; import { Pipe, PipeTransform } from '@angular/core'; import * as moment from 'moment'; +import { DATE_FORMAT_YEAR } from 'src/environments/environment'; @Pipe({ name: 'substractDate' }) @@ -12,8 +13,8 @@ export class SubstractDatePipe implements PipeTransform { return '--:--'; } - const startDate = moment(substractDate, 'YYYY-MM-DD HH:mm:ss'); - let endDate = moment(fromDate, 'YYYY-MM-DD HH:mm:ss'); + const startDate = moment(substractDate, `${DATE_FORMAT_YEAR} HH:mm:ss`); + let endDate = moment(fromDate, `${DATE_FORMAT_YEAR} HH:mm:ss`); let duration: moment.Duration = moment.duration(endDate.diff(startDate)); if (duration.asSeconds() > 60 && !displaySeconds) { diff --git a/src/app/modules/shared/time-range-form/time-range-form.component.html b/src/app/modules/shared/time-range-form/time-range-form.component.html deleted file mode 100644 index 83a8ab8fe..000000000 --- a/src/app/modules/shared/time-range-form/time-range-form.component.html +++ /dev/null @@ -1,26 +0,0 @@ -
- -
- -
- -
- - -
- -
- -
- -
-
-
diff --git a/src/app/modules/shared/time-range-form/time-range-form.component.ts b/src/app/modules/shared/time-range-form/time-range-form.component.ts deleted file mode 100644 index 870f862f4..000000000 --- a/src/app/modules/shared/time-range-form/time-range-form.component.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { ToastrService } from 'ngx-toastr'; -import { formatDate } from '@angular/common'; -import { Component, OnInit } from '@angular/core'; -import { FormControl, FormGroup } from '@angular/forms'; -import * as entryActions from '../../time-clock/store/entry.actions'; - -import {Store} from '@ngrx/store'; -import {EntryState} from '../../time-clock/store/entry.reducer'; -import * as moment from 'moment'; - -@Component({ - selector: 'app-time-range-form', - templateUrl: './time-range-form.component.html', -}) -export class TimeRangeFormComponent implements OnInit { - public reportForm: FormGroup; - private startDate = new FormControl(''); - private endDate = new FormControl(''); - - constructor(private store: Store, private toastrService: ToastrService) { - this.reportForm = new FormGroup({ - startDate: this.startDate, - endDate: this.endDate - }); - } - ngOnInit(): void { - this.setInitialDataOnScreen(); - } - - setInitialDataOnScreen() { - this.reportForm.setValue({ - startDate: formatDate(moment().startOf('week').toString(), 'yyyy-MM-dd', 'en'), - endDate: formatDate(moment().endOf('week').toString(), 'yyyy-MM-dd', 'en') - }); - this.onSubmit(); - } - - onSubmit() { - const endDate = moment(this.endDate.value).endOf('day'); - const startDate = moment(this.startDate.value).startOf('day'); - if (endDate.isBefore(startDate)) { - this.toastrService.error('The end date should be after the start date'); - } else { - this.store.dispatch(new entryActions.LoadEntriesByTimeRange({ - start_date: moment(this.startDate.value).startOf('day'), - end_date: moment(this.endDate.value).endOf('day'), - })); - } - } -} diff --git a/src/app/modules/shared/time-range-form/time-range.component.spec.ts b/src/app/modules/shared/time-range-form/time-range.component.spec.ts deleted file mode 100644 index 64e1491a7..000000000 --- a/src/app/modules/shared/time-range-form/time-range.component.spec.ts +++ /dev/null @@ -1,121 +0,0 @@ -import { ToastrService, IndividualConfig } from 'ngx-toastr'; -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'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { InputDateComponent } from '../../shared/components/input-date/input-date.component'; -import * as entryActions from '../../time-clock/store/entry.actions'; -import * as moment from 'moment'; - -describe('Reports Page', () => { - describe('TimeRangeFormComponent', () => { - let component: TimeRangeFormComponent; - let fixture: ComponentFixture; - let store: MockStore; - const toastrServiceStub = { - error: (message?: string, title?: string, override?: Partial) => { } - }; - - const timeEntry = { - id: '123', - start_date: new Date(), - end_date: new Date(), - activity_id: '123', - technologies: ['react', 'redux'], - comments: 'any comment', - uri: 'custom uri', - project_id: '123' - }; - - const state = { - active: timeEntry, - entryList: [timeEntry], - isLoading: false, - message: '', - createError: false, - updateError: false, - timeEntriesSummary: null, - entriesForReport: [timeEntry], - }; - - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - imports: [FormsModule, ReactiveFormsModule], - declarations: [TimeRangeFormComponent, InputDateComponent], - providers: [ - provideMockStore({ initialState: state }), - { provide: ToastrService, useValue: toastrServiceStub } - ], - }).compileComponents(); - store = TestBed.inject(MockStore); - - })); - - beforeEach(() => { - fixture = TestBed.createComponent(TimeRangeFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('component should be created', () => { - expect(component).toBeTruthy(); - }); - - it('LoadEntriesByTimeRange action is triggered when start date is before end date', () => { - const yesterday = moment(new Date()).subtract(1, 'days'); - const today = moment(new Date()); - spyOn(store, 'dispatch'); - component.reportForm.controls.startDate.setValue(yesterday); - component.reportForm.controls.endDate.setValue(today); - - component.onSubmit(); - - expect(store.dispatch).toHaveBeenCalledWith(new entryActions.LoadEntriesByTimeRange({ - start_date: yesterday.startOf('day'), - end_date: today.endOf('day') - })); - }); - - it('setInitialDataOnScreen on ngOnInit', () => { - spyOn(component, 'setInitialDataOnScreen'); - - component.ngOnInit(); - - expect(component.setInitialDataOnScreen).toHaveBeenCalled(); - }); - - it('shows an error when the end date is before the start date', () => { - spyOn(toastrServiceStub, 'error'); - const yesterday = moment(new Date()).subtract(1, 'days'); - const today = moment(new Date()); - spyOn(store, 'dispatch'); - component.reportForm.controls.startDate.setValue(today); - component.reportForm.controls.endDate.setValue(yesterday); - - component.onSubmit(); - - expect(toastrServiceStub.error).toHaveBeenCalled(); - }); - - it('setInitialDataOnScreen sets dates in form', () => { - spyOn(component.reportForm, 'setValue'); - - component.setInitialDataOnScreen(); - - expect(component.reportForm.setValue).toHaveBeenCalled(); - }); - - it('triggers onSubmit to set initial data', () => { - spyOn(component, 'onSubmit'); - - component.setInitialDataOnScreen(); - - expect(component.onSubmit).toHaveBeenCalled(); - }); - - afterEach(() => { - fixture.destroy(); - }); - }); -}); diff --git a/src/app/modules/technology-report/components/technology-report-table/data.json b/src/app/modules/technology-report/components/technology-report-table/data.json index 2149bfea4..e6e08e8cc 100644 --- a/src/app/modules/technology-report/components/technology-report-table/data.json +++ b/src/app/modules/technology-report/components/technology-report-table/data.json @@ -1,40 +1,71 @@ [ { "id": 1, - "name_technology": "Superman", + "name_technology": "Pascal", "users": [ { "id": 1, - "email_user": "junito@gmail.com", + "email_user": "dogman@gmail.com", + "time_spent": 30, + "projects": [ + { + "id": 1, + "project_name": "Time tracker", + "time_spent": 15 + }, + { + "id": 2, + "project_name": "New Project", + "time_spent": 10 + }, + { + "id": 3, + "project_name": "Old Project", + "time_spent": 5 + } + ] + }, { + "id": 2, + "email_user": "duckman@gmail.com", + "time_spent": 20, + "projects": [ + { + "id": 1, + "project_name": "Time tracker", + "time_spent": 20 + } + ] + }, { + "id": 3, + "email_user": "plantgirl@gmail.com", "time_spent": 10, - "project": [ + "projects": [ { "id": 1, "project_name": "Time tracker", - "time_spent": 8 + "time_spent": 10 } ] } ], - "time_spent": 10 - }, - { + "time_spent": 60 + }, { "id": 2, - "name_technology": "Tor", + "name_technology": "Pascual", "users": [ { "id": 1, - "email_user": "junito@gmail.com", + "email_user": "catgirl@gmail.com", "time_spent": 10, - "project": [ + "projects": [ { "id": 1, "project_name": "Time tracker", - "time_spent": 8 + "time_spent": 10 } ] } ], "time_spent": 10 } -] \ No newline at end of file +] diff --git a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.html b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.html index 51c8f60f1..45b28c280 100644 --- a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.html +++ b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.html @@ -3,26 +3,37 @@ - - + + + - - - + + +
TechnologyTime spendTechnologyTime spend
{{ data.name_technology || '' }}{{ data.time_spent || ''}}{{ tech.name_technology || '' }}{{ tech.time_spent || ''}} + +
+
+ + + + + + + + +
{{ user.email_user }}{{ user.time_spent || '' }}
{{ project.project_name }}{{ project.time_spent || '' }}
+
diff --git a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.scss b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.scss index 8246f2e3b..0659c2a7f 100644 --- a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.scss +++ b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.scss @@ -1,28 +1,16 @@ -.col{ +.col { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: small; } -.x-sm-col{ - width: 5em; - max-width: 7em; -} - -.sm-col{ - width: 6em; - max-width: 8em; -} -.md-col{ +.md-col { width: 9em; } -.lg-col{ +.lg-col { width: 12em; overflow: hidden; white-space: normal; } -.hidden-col{ - display: none; -} diff --git a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.spec.ts b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.spec.ts index 311e460fb..9ea4e00f0 100644 --- a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.spec.ts +++ b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.spec.ts @@ -1,77 +1,27 @@ 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'; -import { getReportDataSource } from 'src/app/modules/time-clock/store/entry.selectors'; -import { EntryState } from '../../../time-clock/store/entry.reducer'; + import { TechnologyReportTableComponent } from './technology-report-table.component'; -describe('Reports Page', () => { - describe('TimeEntriesTableComponent', () => { +describe('Technology Report Page', () => { + describe('TechnologyReportTableComponent', () => { let component: TechnologyReportTableComponent; let fixture: ComponentFixture; - let store: MockStore; - let getReportDataSourceSelectorMock; - const timeEntry: Entry = { - start_date: new Date(), - end_date: new Date(), - technologies: ['react', 'redux'], - }; - - const state: EntryState = { - active: timeEntry, - isLoading: false, - message: '', - createError: false, - updateError: false, - timeEntriesSummary: null, - timeEntriesDataSource: { - data: [timeEntry], - isLoading: false - }, - reportDataSource: { - data: [timeEntry], - isLoading: false - } - }; beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ - imports: [], - declarations: [TechnologyReportTableComponent, SubstractDatePipe], - providers: [provideMockStore({ initialState: state })], - }).compileComponents(); - store = TestBed.inject(MockStore); - + declarations: [TechnologyReportTableComponent], + }) + .compileComponents(); })); - beforeEach(waitForAsync(() => { + beforeEach(() => { fixture = TestBed.createComponent(TechnologyReportTableComponent); component = fixture.componentInstance; - store.setState(state); - getReportDataSourceSelectorMock = store.overrideSelector(getReportDataSource, state.reportDataSource); fixture.detectChanges(); - })); - - fit('component should be created', async () => { - expect(component).toBeTruthy(); }); - // it('on success load time entries, the report should be populated', () => { - // component.reportDataSource$.subscribe(ds => { - // expect(ds.data).toEqual(state.reportDataSource.data); - // }); - // }); - - // it('after the component is initialized it should initialize the table', () => { - // spyOn(component.dtTrigger, 'next'); - // component.ngAfterViewInit(); - - // expect(component.dtTrigger.next).toHaveBeenCalled(); - // }); - - afterEach(() => { - fixture.destroy(); + it('component should be created', () => { + expect(component).toBeTruthy(); }); }); }); diff --git a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.ts b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.ts index 1b5325a98..a17361541 100644 --- a/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.ts +++ b/src/app/modules/technology-report/components/technology-report-table/technology-report-table.component.ts @@ -1,14 +1,7 @@ import { formatDate } from '@angular/common'; -import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { select, Store } from '@ngrx/store'; -import { DataTableDirective } from 'angular-datatables'; +import { Component, OnInit } from '@angular/core'; import * as moment from 'moment'; -import { Observable, Subject } from 'rxjs'; -import { Entry } from 'src/app/modules/shared/models'; -import { DataSource } from 'src/app/modules/shared/models/data-source.model'; -import { EntryState } from '../../../time-clock/store/entry.reducer'; -import { getReportDataSource } from '../../../time-clock/store/entry.selectors'; -import * as dataMock from './data.json'; +import * as dataMock from './data.json'; @Component({ selector: 'app-technology-report-table', @@ -16,85 +9,33 @@ import * as dataMock from './data.json'; styleUrls: ['./technology-report-table.component.scss'] }) -export class TechnologyReportTableComponent implements OnInit, OnDestroy, AfterViewInit { - - dtOptions: any = { - scrollY: '600px', - paging: false, - dom: 'Bfrtip', - buttons: [ - { - extend: 'colvis', - columns: ':not(.hidden-col)', - - }, - 'print', - { - extend: 'excel', - exportOptions: { - format: { - body: (data, row, column, node) => { - return column === 3 ? - moment.duration(data).asHours().toFixed(4).slice(0, -1) : - data; - } - } - }, - text: 'Excel', - filename: `time-entries-${formatDate(new Date(), 'MM_dd_yyyy-HH_mm', 'en')}` - }, - { - extend: 'csv', - exportOptions: { - format: { - body: (data, row, column, node) => { - return column === 3 ? - moment.duration(data).asHours().toFixed(4).slice(0, -1) : - data; - } - } - }, - text: 'CSV', - filename: `time-entries-${formatDate(new Date(), 'MM_dd_yyyy-HH_mm', 'en')}` - } - ], - responsive: true - }; - dtTrigger: Subject = new Subject(); - @ViewChild(DataTableDirective, { static: false }) - dtElement: DataTableDirective; - isLoading$: Observable; - reportDataSource$: Observable>; - +export class TechnologyReportTableComponent implements OnInit { + dtOptions: any = {}; technologies: any = (dataMock as any).default; - constructor(private store: Store) { - this.reportDataSource$ = this.store.pipe(select(getReportDataSource)); - } - ngOnInit(): void { - this.reportDataSource$.subscribe((ds) => { - this.rerenderDataTable(); - }); - console.log('data', dataMock); - } - - ngAfterViewInit(): void { - this.rerenderDataTable(); - } - - ngOnDestroy(): void { - this.dtTrigger.unsubscribe(); - } - - private rerenderDataTable(): void { - if (this.dtElement && this.dtElement.dtInstance) { - this.dtElement.dtInstance.then((dtInstance: DataTables.Api) => { - dtInstance.destroy(); - this.dtTrigger.next(); - }); - } else { - this.dtTrigger.next(); - } + this.dtOptions = { + scrollY: '600px', + paging: false, + dom: 'Bfrtip', + buttons: [ + { + extend: 'colvis', + columns: ':not(.hidden-col)', + }, + 'print', + { + extend: 'excel', + text: 'Excel', + filename: `technologies-${formatDate(new Date(), 'MM_dd_yyyy-HH_mm', 'en')}` + }, + { + extend: 'csv', + text: 'CSV', + filename: `technologies-${formatDate(new Date(), 'MM_dd_yyyy-HH_mm', 'en')}` + } + ], + responsive: true + }; } } diff --git a/src/app/modules/technology-report/pages/technology-report.component.spec.ts b/src/app/modules/technology-report/pages/technology-report.component.spec.ts new file mode 100644 index 000000000..42828ecff --- /dev/null +++ b/src/app/modules/technology-report/pages/technology-report.component.spec.ts @@ -0,0 +1,34 @@ +import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TechnologyReportComponent } from './technology-report.component'; + +describe('TechnologyReportComponent', () => { + let component: TechnologyReportComponent; + let fixture: ComponentFixture; + + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [TechnologyReportComponent], + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TechnologyReportComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); + + it('should have form and datatable components', waitForAsync(() => { + fixture.detectChanges(); + + const compile = fixture.debugElement.nativeElement; + const timeRangeForm = compile.querySelector('app-time-range-form'); + const technologyReportDataTable = compile.querySelector('app-technology-report-table'); + expect(timeRangeForm).toBeTruthy(); + expect(technologyReportDataTable).toBeTruthy(); + })); +}); diff --git a/src/app/modules/technology-report/pages/technology-report.component.spect.ts b/src/app/modules/technology-report/pages/technology-report.component.spect.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/app/modules/technology-report/pages/technology-report.component.ts b/src/app/modules/technology-report/pages/technology-report.component.ts index 21e6f0183..3e57c0a02 100644 --- a/src/app/modules/technology-report/pages/technology-report.component.ts +++ b/src/app/modules/technology-report/pages/technology-report.component.ts @@ -2,8 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-technology-report', - templateUrl: './technology-report.component.html', -// styleUrls: ['./technology-report.component.scss'] + templateUrl: './technology-report.component.html' }) export class TechnologyReportComponent { } diff --git a/src/app/modules/technology-report/technology-report.component.scss b/src/app/modules/technology-report/technology-report.component.scss deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts index f6b78b742..f2d29ee96 100644 --- a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts +++ b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts @@ -13,6 +13,7 @@ import { ActionsSubject } from '@ngrx/store'; import { IndividualConfig, ToastrService } from 'ngx-toastr'; import { formatDate } from '@angular/common'; import * as moment from 'moment'; +import { DATE_FORMAT_YEAR } from 'src/environments/environment'; describe('EntryFieldsComponent', () => { type Merged = TechnologyState & ProjectState; @@ -66,7 +67,7 @@ describe('EntryFieldsComponent', () => { project_id: 'project-id-15', description: 'description for active entry', uri: 'abc', - start_date : moment().format('YYYY-MM-DD'), + start_date : moment().format(DATE_FORMAT_YEAR), start_hour : moment().format('HH:mm:ss'), }; @@ -115,7 +116,7 @@ describe('EntryFieldsComponent', () => { uri: entryDataForm.uri, activity_id: entryDataForm.activity_id, start_hour: formatDate(entry.start_date, 'HH:mm:ss', 'en'), - start_date : moment().format('YYYY-MM-DD'), + start_date : moment().format(DATE_FORMAT_YEAR), } ); expect(component.selectedTechnologies).toEqual([]); 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 5f52bc794..0b3762375 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 @@ -15,6 +15,7 @@ import * as entryActions from '../../store/entry.actions'; import * as moment from 'moment'; import { ToastrService } from 'ngx-toastr'; import { formatDate } from '@angular/common'; +import { DATE_FORMAT } from 'src/environments/environment'; type Merged = TechnologyState & ProjectState & ActivityState; @@ -118,7 +119,7 @@ export class EntryFieldsComponent implements OnInit { } onUpdateStartHour() { - const startDate = formatDate(this.activeEntry.start_date, 'yyyy-MM-dd', 'en'); + const startDate = formatDate(this.activeEntry.start_date, DATE_FORMAT, 'en'); const newHourEntered = new Date(`${startDate}T${this.entryForm.value.start_hour.trim()}`).toISOString(); const isEntryDateInTheFuture = moment(newHourEntered).isAfter(moment()); if (isEntryDateInTheFuture) { diff --git a/src/environments/environment.ts b/src/environments/environment.ts index 3c7b4716d..208e0a880 100644 --- a/src/environments/environment.ts +++ b/src/environments/environment.ts @@ -16,6 +16,8 @@ export const ITEMS_PER_PAGE = 5; export const STACK_EXCHANGE_ID = keys.STACK_EXCHANGE_ID; export const STACK_EXCHANGE_ACCESS_TOKEN = keys.STACK_EXCHANGE_ACCESS_TOKEN; export const AZURE_APP_CONFIGURATION_CONNECTION_STRING = keys.AZURE_APP_CONFIGURATION_CONNECTION_STRING; +export const DATE_FORMAT = 'yyyy-MM-dd'; +export const DATE_FORMAT_YEAR = 'YYYY-MM-DD'; /* * For easier debugging in development mode, you can import the following file diff --git a/tsconfig.json b/tsconfig.json index 8cc284df1..80a8e1cb8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,6 @@ "moduleResolution": "node", "importHelpers": true, "target": "es2015", - "resolveJsonModule": true, "allowSyntheticDefaultImports": false, "typeRoots": [ "node_modules/@types"