Skip to content

Commit a2ff91e

Browse files
author
Juan Gabriel Guzman
committed
refactor: #452
Extracting time-entries table source as datasource objects Removing dead code Using types on unit tests Fixing unit tests
1 parent 552e7db commit a2ff91e

27 files changed

+345
-402
lines changed

src/app/modules/activities-management/components/activity-list/activity-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
</tr>
88
</thead>
99
<app-loading-bar *ngIf="(isLoading$ | async)"></app-loading-bar>
10-
<tbody *ngIf="((isLoading$ | async) === ( false || null || undefined))">
10+
<tbody *ngIf="(isLoading$ | async) === false">
1111
<tr class="d-flex" *ngFor="let activity of activities">
1212
<td class="col-sm-9">{{ activity.name }}</td>
1313
<td class="col-sm-3 text-center">

src/app/modules/activities-management/components/activity-list/activity-list.component.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
import { OnInit } from '@angular/core';
2-
import { Component } from '@angular/core';
3-
import { Store, select } from '@ngrx/store';
4-
5-
import { LoadActivities, DeleteActivity, SetActivityToEdit } from './../../store/activity-management.actions';
6-
import { ActivityState } from './../../store/activity-management.reducers';
7-
import { allActivities } from '../../store';
8-
import { Activity } from '../../../shared/models';
1+
import { Component, OnInit } from '@angular/core';
2+
import { select, Store } from '@ngrx/store';
93
import { Observable } from 'rxjs';
104
import { delay } from 'rxjs/operators';
115
import { getIsLoading } from 'src/app/modules/activities-management/store/activity-management.selectors';
6+
import { Activity } from '../../../shared/models';
7+
import { allActivities } from '../../store';
8+
import { DeleteActivity, LoadActivities, SetActivityToEdit } from './../../store/activity-management.actions';
9+
import { ActivityState } from './../../store/activity-management.reducers';
10+
1211

1312
@Component({
1413
selector: 'app-activity-list',
Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
import { createFeatureSelector, createSelector } from '@ngrx/store';
2-
32
import { ActivityState } from './activity-management.reducers';
43

54
const getActivityState = createFeatureSelector<ActivityState>('activities');
65

7-
export const allActivities = createSelector(getActivityState, (state: ActivityState) => {
8-
return state.data;
9-
});
6+
export const allActivities = createSelector(getActivityState, (state: ActivityState) => state?.data);
107

11-
export const activityIdToEdit = createSelector(getActivityState, (state: ActivityState) => {
12-
return state.activityIdToEdit;
13-
});
8+
export const activityIdToEdit = createSelector(getActivityState, (state: ActivityState) => state?.activityIdToEdit);
149

1510
export const getActivityById = createSelector(allActivities, activityIdToEdit, (activities, activityId) => {
1611
if (activities && activityId) {
@@ -20,6 +15,4 @@ export const getActivityById = createSelector(allActivities, activityIdToEdit, (
2015
}
2116
});
2217

23-
export const getIsLoading = createSelector(getActivityState, (state: ActivityState) => {
24-
return state.isLoading;
25-
});
18+
export const getIsLoading = createSelector(getActivityState, (state: ActivityState) => state?.isLoading);

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
</tr>
1313
</thead>
1414
<app-loading-bar *ngIf="(isLoading$ | async)"></app-loading-bar>
15-
<tbody *ngIf="((isLoading$ | async) === (false || null || undefined))">
15+
<tbody *ngIf="((isLoading$ | async) === false)">
1616
<tr class="d-flex" *ngFor="let customer of customers">
1717
<td class="col-sm-9">{{ customer.name }}</td>
1818
<td class="col-sm-3 text-center">

src/app/modules/customer-management/components/customer-info/components/customer-list/customer-list.component.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
import {Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild, AfterViewInit} from '@angular/core';
2-
import {ActionsSubject, select, Store} from '@ngrx/store';
3-
4-
import {Observable, Subject, Subscription} from 'rxjs';
1+
import { AfterViewInit, Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewChild } from '@angular/core';
2+
import { ActionsSubject, select, Store } from '@ngrx/store';
3+
import { DataTableDirective } from 'angular-datatables';
4+
import { Observable, Subject, Subscription } from 'rxjs';
5+
import { delay, filter } from 'rxjs/operators';
6+
import { getIsLoading } from 'src/app/modules/customer-management/store/customer-management.selectors';
7+
import { Customer } from './../../../../../shared/models/customer.model';
58
import {
69
CustomerManagementActionTypes,
710
DeleteCustomer,
811
LoadCustomers,
912
SetCustomerToEdit
1013
} from './../../../../store/customer-management.actions';
11-
import {Customer} from './../../../../../shared/models/customer.model';
12-
import {delay, filter} from 'rxjs/operators';
13-
import {DataTableDirective} from 'angular-datatables';
14-
import { getIsLoading } from 'src/app/modules/customer-management/store/customer-management.selectors';
15-
1614
@Component({
1715
selector: 'app-customer-list',
1816
templateUrl: './customer-list.component.html',
Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,12 @@
11
import { createFeatureSelector, createSelector } from '@ngrx/store';
2-
32
import { ProjectState } from './project.reducer';
43

54
const getProjectState = createFeatureSelector<ProjectState>('projects');
65

7-
export const getCustomerProjects = createSelector(getProjectState, (state: ProjectState) => {
8-
return state;
9-
});
6+
export const getCustomerProjects = createSelector(getProjectState, (state: ProjectState) => state);
107

11-
export const getProjects = createSelector(getProjectState, (state: ProjectState) => {
12-
return state.projects;
13-
});
8+
export const getProjects = createSelector(getProjectState, (state: ProjectState) => state?.projects);
149

15-
export const getProjectToEdit = createSelector(getProjectState, (state: ProjectState) => {
16-
return state.projectToEdit;
17-
});
10+
export const getProjectToEdit = createSelector(getProjectState, (state: ProjectState) => state?.projectToEdit);
1811

19-
export const getIsLoading = createSelector(getProjectState, (state: ProjectState) => {
20-
return state.isLoading;
21-
});
12+
export const getIsLoading = createSelector(getProjectState, (state: ProjectState) => state?.isLoading);

src/app/modules/customer-management/store/customer-management.selectors.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { createFeatureSelector, createSelector } from '@ngrx/store';
2-
32
import { CustomerState } from './customer-management.reducers';
3+
44
export const getCustomerState = createFeatureSelector<CustomerState>('customers');
55

66
export const getStatusMessage = createSelector(getCustomerState, (messageState) => {
@@ -35,7 +35,6 @@ export const getCustomerUnderEdition = createSelector(allCustomers, customerIdto
3535
}
3636
});
3737

38-
3938
export const getIsLoading = createSelector(getCustomerState, (state: CustomerState) => {
4039
return state.isLoading;
4140
});

src/app/modules/reports/components/time-entries-table/time-entries-table.component.html

Lines changed: 44 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,53 @@
55
datatable
66
[dtTrigger]="dtTrigger"
77
[dtOptions]="dtOptions"
8+
*ngIf="(reportDataSource$ | async) as dataSource"
89
>
910
<thead class="thead-blue">
10-
<tr class="d-flex">
11-
<th class="col md-col">ID</th>
12-
<th class="col md-col">User email</th>
13-
<th class="col sm-col">Date</th>
14-
<th class="col sm-col">Duration (hours)</th>
15-
<th class="col sm-col">Time in</th>
16-
<th class="col sm-col">Time out</th>
17-
<th class="col md-col">Project</th>
18-
<th class="col lg-col">Project ID</th>
19-
<th class="col md-col">Customer</th>
20-
<th class="col lg-col">Customer ID</th>
21-
<th class="col md-col">Activity</th>
22-
<th class="col lg-col">Ticket</th>
23-
<th class="col lg-col">Description</th>
24-
<th class="col lg-col">Technologies</th>
25-
</tr>
11+
<tr class="d-flex">
12+
<th class="col md-col">ID</th>
13+
<th class="col md-col">User email</th>
14+
<th class="col sm-col">Date</th>
15+
<th class="col sm-col">Duration (hours)</th>
16+
<th class="col sm-col">Time in</th>
17+
<th class="col sm-col">Time out</th>
18+
<th class="col md-col">Project</th>
19+
<th class="col lg-col">Project ID</th>
20+
<th class="col md-col">Customer</th>
21+
<th class="col lg-col">Customer ID</th>
22+
<th class="col md-col">Activity</th>
23+
<th class="col lg-col">Ticket</th>
24+
<th class="col lg-col">Description</th>
25+
<th class="col lg-col">Technologies</th>
26+
</tr>
2627
</thead>
27-
<app-loading-bar *ngIf="(isLoading$ | async)"></app-loading-bar>
28-
<tbody *ngIf="(isLoading$ | async) === false ">
29-
<tr
30-
class="d-flex"
31-
*ngFor="let entry of data"
32-
>
33-
<td class="col md-col multiline-col"> {{ entry.id }} </td>
34-
<td class="col md-col multiline-col"> {{ entry.owner_email }} </td>
35-
<td class="col sm-col"> {{ entry.start_date | date: 'MM/dd/yyyy' }} </td>
36-
<td class="col sm-col"> {{ entry.end_date | substractDate: entry.start_date }} </td>
37-
<td class="col sm-col"> {{ entry.start_date | date: 'HH:mm' }} </td>
38-
<td class="col sm-col"> {{ entry.end_date | date: 'HH:mm' }} </td>
39-
<td class="col md-col"> {{ entry.project_name }} </td>
40-
<td class="col md-col"> {{ entry.project_id }} </td>
41-
<td class="col md-col"> {{ entry.customer_name }} </td>
42-
<td class="col md-col"> {{ entry.customer_id }} </td>
43-
<td class="col md-col"> {{ entry.activity_name }} </td>
44-
<td class="col lg-col"> {{ entry.uri }} </td>
45-
<td class="col lg-col multiline-col"> {{ entry.description }} </td>
46-
<td class="col lg-col multiline-col"> {{ entry.technologies }} </td>
47-
</tr>
28+
<app-loading-bar
29+
*ngIf="dataSource.isLoading"
30+
></app-loading-bar>
31+
<tbody *ngIf="!dataSource.isLoading">
32+
<tr
33+
class="d-flex"
34+
*ngFor="let entry of dataSource.data"
35+
>
36+
<td class="col md-col multiline-col">{{ entry.id }}</td>
37+
<td class="col md-col multiline-col">{{ entry.owner_email }}</td>
38+
<td class="col sm-col">
39+
{{ entry.start_date | date: 'MM/dd/yyyy' }}
40+
</td>
41+
<td class="col sm-col">
42+
{{ entry.end_date | substractDate: entry.start_date }}
43+
</td>
44+
<td class="col sm-col">{{ entry.start_date | date: 'HH:mm' }}</td>
45+
<td class="col sm-col">{{ entry.end_date | date: 'HH:mm' }}</td>
46+
<td class="col md-col">{{ entry.project_name }}</td>
47+
<td class="col md-col">{{ entry.project_id }}</td>
48+
<td class="col md-col">{{ entry.customer_name }}</td>
49+
<td class="col md-col">{{ entry.customer_id }}</td>
50+
<td class="col md-col">{{ entry.activity_name }}</td>
51+
<td class="col lg-col">{{ entry.uri }}</td>
52+
<td class="col lg-col multiline-col">{{ entry.description }}</td>
53+
<td class="col lg-col multiline-col">{{ entry.technologies }}</td>
54+
</tr>
4855
</tbody>
4956
</table>
5057
</div>

src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,30 @@
1-
import { AsyncPipe } from '@angular/common';
21
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
32
import { MockStore, provideMockStore } from '@ngrx/store/testing';
3+
import { Entry } from 'src/app/modules/shared/models';
4+
import { SubstractDatePipe } from 'src/app/modules/shared/pipes/substract-date/substract-date.pipe';
5+
import { getReportDataSource } from 'src/app/modules/time-clock/store/entry.selectors';
46
import { EntryState } from '../../../time-clock/store/entry.reducer';
5-
import { entriesForReport } from '../../../time-clock/store/entry.selectors';
67
import { TimeEntriesTableComponent } from './time-entries-table.component';
78

89
describe('Reports Page', () => {
910
describe('TimeEntriesTableComponent', () => {
1011
let component: TimeEntriesTableComponent;
1112
let fixture: ComponentFixture<TimeEntriesTableComponent>;
1213
let store: MockStore<EntryState>;
13-
let geTimeEntriesSelectorMock;
14-
const timeEntry = {
14+
let getReportDataSourceSelectorMock;
15+
const timeEntry: Entry = {
1516
id: '123',
1617
start_date: new Date(),
1718
end_date: new Date(),
1819
activity_id: '123',
1920
technologies: ['react', 'redux'],
20-
comments: 'any comment',
21+
description: 'any comment',
2122
uri: 'custom uri',
22-
project_id: '123'
23+
project_id: '123',
24+
project_name: 'Time-Tracker'
2325
};
2426

25-
const state = {
27+
const state: EntryState = {
2628
active: timeEntry,
2729
isLoading: false,
2830
message: '',
@@ -42,34 +44,32 @@ describe('Reports Page', () => {
4244
beforeEach(async(() => {
4345
TestBed.configureTestingModule({
4446
imports: [],
45-
declarations: [TimeEntriesTableComponent, AsyncPipe],
46-
providers: [provideMockStore({initialState: state})],
47+
declarations: [TimeEntriesTableComponent, SubstractDatePipe],
48+
providers: [provideMockStore({ initialState: state })],
4749
}).compileComponents();
4850
store = TestBed.inject(MockStore);
4951

5052
}));
5153

52-
beforeEach(() => {
54+
beforeEach(async(() => {
5355
fixture = TestBed.createComponent(TimeEntriesTableComponent);
5456
component = fixture.componentInstance;
55-
fixture.detectChanges();
5657
store.setState(state);
57-
geTimeEntriesSelectorMock = store.overrideSelector(entriesForReport, state.reportDataSource.data);
58-
});
58+
getReportDataSourceSelectorMock = store.overrideSelector(getReportDataSource, state.reportDataSource);
59+
fixture.detectChanges();
60+
}));
5961

6062
it('component should be created', async () => {
6163
expect(component).toBeTruthy();
6264
});
6365

64-
it('on success load time entries, the report should be populated', async () => {
65-
component.ngOnInit();
66-
fixture.detectChanges();
67-
68-
expect(component.data).toEqual(state.reportDataSource.data);
66+
it('on success load time entries, the report should be populated', () => {
67+
component.reportDataSource$.subscribe(ds => {
68+
expect(ds.data).toEqual(state.reportDataSource.data);
69+
});
6970
});
7071

71-
it('after the component is initialized it should initialize the table', async () => {
72-
72+
it('after the component is initialized it should initialize the table', () => {
7373
spyOn(component.dtTrigger, 'next');
7474
component.ngAfterViewInit();
7575

0 commit comments

Comments
 (0)