Skip to content

Commit ac24beb

Browse files
authored
TT-259 Validate call to new customer structure on project (#694)
* feat: TT-259 validate call to new customer structure on project * fix: TT-259 Fixed bugs provided by sonarcloud
1 parent 3548107 commit ac24beb

File tree

8 files changed

+195
-141
lines changed

8 files changed

+195
-141
lines changed

src/app/modules/shared/components/details-fields/details-fields.component.html

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
<ng-template #itemTemplate let-item>
3131
<div class="d-flex container">
3232
<div class="mr-auto p-2">
33-
<span [innerHTML]="item.customer_name"></span> -
33+
<span [innerHTML]="item.customer.name"></span> -
3434
<strong><span [innerHTML]="item.name"></span></strong>
3535
</div>
3636
</div>
@@ -149,9 +149,7 @@
149149
<div class="form-group row" *ngIf="!goingToWorkOnThis || !canMarkEntryAsWIP">
150150
<label class="col-12 col-sm-2">Total Hours:</label>
151151
<div class="col-12 col-sm-4">
152-
<span class="border-tag"
153-
[class.border-tag--disabled]="!(project_id.value && project_name.value)"
154-
>
152+
<span class="border-tag" [class.border-tag--disabled]="!(project_id.value && project_name.value)">
155153
{{ this.getTimeDifference() }}
156154
</span>
157155
</div>

src/app/modules/shared/components/details-fields/details-fields.component.spec.ts

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ describe('DetailsFieldsComponent', () => {
3636
let formValues;
3737
const actionSub: ActionsSubject = new ActionsSubject();
3838
const toastrServiceStub = {
39-
error: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { },
40-
warning: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { }
39+
error: (message?: string, title?: string, override?: Partial<IndividualConfig>) => {},
40+
warning: (message?: string, title?: string, override?: Partial<IndividualConfig>) => {},
4141
};
4242

4343
const state = {
4444
projects: {
45-
projects: [{ id: 'id', name: 'name', project_type_id: '' }],
45+
projects: [{ id: 'id', name: 'name', project_type_id: '', customer: { name: 'Juan', description: 'sadsa' } }],
4646
customerProjects: [{ id: 'id', name: 'name', description: 'description', project_type_id: '123' }],
4747
isLoading: false,
4848
message: '',
@@ -53,10 +53,30 @@ describe('DetailsFieldsComponent', () => {
5353
isLoading: false,
5454
},
5555
activities: {
56-
data: [{ id: 'fc5fab41-a21e-4155-9d05-511b956ebd05', tenant_id: 'ioet', deleted: null, name: 'abc', status: 'active' },
57-
{ id: 'fc5fab41-a21e-4155-9d05-511b956ebd07', tenant_id: 'ioet_1', deleted: null, name: 'def', status: 'active' },
58-
{ id: 'fc5fab41-a21e-4155-9d05-511b956ebd08', tenant_id: 'ioet_2', deleted: null, name: 'ghi', status: 'inactive' },
59-
{ id: 'fc5fab41-a21e-4155-9d05-511b956ebd09', tenant_id: 'ioet_3', deleted: null, name: 'jkl', status: 'active' }],
56+
data: [
57+
{ id: 'fc5fab41-a21e-4155-9d05-511b956ebd05', tenant_id: 'ioet', deleted: null, name: 'abc', status: 'active' },
58+
{
59+
id: 'fc5fab41-a21e-4155-9d05-511b956ebd07',
60+
tenant_id: 'ioet_1',
61+
deleted: null,
62+
name: 'def',
63+
status: 'active',
64+
},
65+
{
66+
id: 'fc5fab41-a21e-4155-9d05-511b956ebd08',
67+
tenant_id: 'ioet_2',
68+
deleted: null,
69+
name: 'ghi',
70+
status: 'inactive',
71+
},
72+
{
73+
id: 'fc5fab41-a21e-4155-9d05-511b956ebd09',
74+
tenant_id: 'ioet_3',
75+
deleted: null,
76+
name: 'jkl',
77+
status: 'active',
78+
},
79+
],
6080
isLoading: false,
6181
message: 'Data fetch successfully!',
6282
activityIdToEdit: '',
@@ -82,22 +102,24 @@ describe('DetailsFieldsComponent', () => {
82102

83103
const mockCurrentDate = '2020-12-01T12:00:00';
84104

85-
beforeEach(waitForAsync(() => {
86-
TestBed.configureTestingModule({
87-
declarations: [DetailsFieldsComponent, TechnologiesComponent],
88-
providers: [
89-
provideMockStore({ initialState: state }),
90-
{ provide: ActionsSubject, useValue: actionSub },
91-
{ provide: ToastrService, useValue: toastrServiceStub }
92-
],
93-
imports: [FormsModule, ReactiveFormsModule, AutocompleteLibModule, NgxMaterialTimepickerModule],
94-
}).compileComponents();
95-
store = TestBed.inject(MockStore);
96-
mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies);
97-
mockProjectsSelector = store.overrideSelector(getCustomerProjects, state.projects);
98-
mockEntriesUpdateErrorSelector = store.overrideSelector(getUpdateError, state.Entries.updateError);
99-
mockEntriesCreateErrorSelector = store.overrideSelector(getCreateError, state.Entries.createError);
100-
}));
105+
beforeEach(
106+
waitForAsync(() => {
107+
TestBed.configureTestingModule({
108+
declarations: [DetailsFieldsComponent, TechnologiesComponent],
109+
providers: [
110+
provideMockStore({ initialState: state }),
111+
{ provide: ActionsSubject, useValue: actionSub },
112+
{ provide: ToastrService, useValue: toastrServiceStub },
113+
],
114+
imports: [FormsModule, ReactiveFormsModule, AutocompleteLibModule, NgxMaterialTimepickerModule],
115+
}).compileComponents();
116+
store = TestBed.inject(MockStore);
117+
mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies);
118+
mockProjectsSelector = store.overrideSelector(getCustomerProjects, state.projects);
119+
mockEntriesUpdateErrorSelector = store.overrideSelector(getUpdateError, state.Entries.updateError);
120+
mockEntriesCreateErrorSelector = store.overrideSelector(getCreateError, state.Entries.createError);
121+
})
122+
);
101123

102124
beforeEach(() => {
103125
fixture = TestBed.createComponent(DetailsFieldsComponent);
@@ -110,7 +132,7 @@ describe('DetailsFieldsComponent', () => {
110132
end_date: null,
111133
description: '',
112134
technologies: [],
113-
id: 'xyz'
135+
id: 'xyz',
114136
};
115137
formValues = {
116138
project_id: 'id',
@@ -143,7 +165,7 @@ describe('DetailsFieldsComponent', () => {
143165

144166
component.onSelectedProject({ id: 'id', search_field: 'foo' });
145167

146-
expect(component.entryForm.patchValue).toHaveBeenCalledWith({ project_id: 'id', project_name: 'foo', });
168+
expect(component.entryForm.patchValue).toHaveBeenCalledWith({ project_id: 'id', project_name: 'foo' });
147169
});
148170

149171
it('if form is invalid then saveEntry is not emited', () => {
@@ -154,23 +176,22 @@ describe('DetailsFieldsComponent', () => {
154176
expect(component.saveEntry.emit).toHaveBeenCalledTimes(0);
155177
});
156178

157-
[
158-
{ actionType: EntryActionTypes.CREATE_ENTRY_SUCCESS },
159-
{ actionType: EntryActionTypes.UPDATE_ENTRY_SUCCESS },
160-
].map((param) => {
161-
it(`cleanForm after an action type ${param.actionType} is received`, () => {
162-
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
163-
const action = {
164-
type: param.actionType,
165-
};
166-
spyOn(component, 'cleanForm');
179+
[{ actionType: EntryActionTypes.CREATE_ENTRY_SUCCESS }, { actionType: EntryActionTypes.UPDATE_ENTRY_SUCCESS }].forEach(
180+
(param) => {
181+
it(`cleanForm after an action type ${param.actionType} is received`, () => {
182+
const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject;
183+
const action = {
184+
type: param.actionType,
185+
};
186+
spyOn(component, 'cleanForm');
167187

168-
component.ngOnInit();
169-
actionSubject.next(action);
188+
component.ngOnInit();
189+
actionSubject.next(action);
170190

171-
expect(component.cleanForm).toHaveBeenCalled();
172-
});
173-
});
191+
expect(component.cleanForm).toHaveBeenCalled();
192+
});
193+
}
194+
);
174195

175196
it('on cleanFieldsForm the project_id and project_name should be kept', () => {
176197
const entryFormValueExpected = {
@@ -196,7 +217,7 @@ describe('DetailsFieldsComponent', () => {
196217
component.ngOnChanges();
197218
expect(component.shouldRestartEntry).toBeFalse();
198219
expect(component.entryForm.value).toEqual(initialData);
199-
component.activities$.subscribe(item => {
220+
component.activities$.subscribe((item) => {
200221
expect(item.length).not.toBe(null);
201222
expect(item.length).toBe(3);
202223
});
@@ -224,15 +245,15 @@ describe('DetailsFieldsComponent', () => {
224245

225246
const activitiesParams = [
226247
{ select_activity_id: 'fc5fab41-a21e-4155-9d05-511b956ebd07', expected_size_activities: 3, title: 'active' },
227-
{ select_activity_id: 'fc5fab41-a21e-4155-9d05-511b956ebd08', expected_size_activities: 4, title: 'inactive' }
248+
{ select_activity_id: 'fc5fab41-a21e-4155-9d05-511b956ebd08', expected_size_activities: 4, title: 'inactive' },
228249
];
229-
activitiesParams.map(param => {
250+
activitiesParams.forEach((param) => {
230251
it(`should emit ngOnChange to set ${param.expected_size_activities} activities for select (${param.title} time entry clicked)`, () => {
231252
component.entryToEdit = { ...entryToEdit, activity_id: param.select_activity_id };
232253
spyOn(component.entryForm, 'patchValue');
233254
component.ngOnChanges();
234255

235-
component.activities$.subscribe(items => {
256+
component.activities$.subscribe((items) => {
236257
expect(items.length).toBe(param.expected_size_activities);
237258
});
238259
});
@@ -241,7 +262,7 @@ describe('DetailsFieldsComponent', () => {
241262
it('selectActiveActivities should return 3 active activities', () => {
242263
const activeActivities = component.selectActiveActivities();
243264

244-
activeActivities.subscribe(item => {
265+
activeActivities.subscribe((item) => {
245266
expect(item.length).not.toBe(null);
246267
expect(item.length).toBe(3);
247268
});
@@ -293,7 +314,7 @@ describe('DetailsFieldsComponent', () => {
293314
uri: '',
294315
timezone_offset: new Date().getTimezoneOffset(),
295316
},
296-
shouldRestartEntry: false
317+
shouldRestartEntry: false,
297318
};
298319

299320
expect(component.saveEntry.emit).toHaveBeenCalledWith(data);
@@ -328,9 +349,10 @@ describe('DetailsFieldsComponent', () => {
328349

329350
component.onGoingToWorkOnThisChange({ currentTarget: { checked: false } });
330351

331-
expect(component.entryForm.patchValue).toHaveBeenCalledWith(
332-
{ end_date: '2020-12-30', end_hour: formatDate(new Date(), 'HH:mm', 'en'), }
333-
);
352+
expect(component.entryForm.patchValue).toHaveBeenCalledWith({
353+
end_date: '2020-12-30',
354+
end_hour: formatDate(new Date(), 'HH:mm', 'en'),
355+
});
334356
});
335357

336358
it('when creating a new entry, then the new entry should be marked as not run', () => {
@@ -390,7 +412,7 @@ describe('DetailsFieldsComponent', () => {
390412
uri: 'ticketUri',
391413
timezone_offset: new Date().getTimezoneOffset(),
392414
},
393-
shouldRestartEntry: false
415+
shouldRestartEntry: false,
394416
};
395417

396418
expect(component.saveEntry.emit).toHaveBeenCalledWith(data);
@@ -486,12 +508,12 @@ describe('DetailsFieldsComponent', () => {
486508
spyOn(component.projectSelected, 'emit');
487509
const item = {
488510
id: 'id',
489-
search_field: 'TimeTracker'
511+
search_field: 'TimeTracker',
490512
};
491513
component.onSelectedProject(item);
492514

493515
const data: ProjectSelectedEvent = {
494-
projectId: 'id'
516+
projectId: 'id',
495517
};
496518
expect(component.projectSelected.emit).toHaveBeenCalledWith(data);
497519
});
@@ -531,8 +553,9 @@ describe('DetailsFieldsComponent', () => {
531553
it('on the input with id #start_date we could get the id and max value', () => {
532554
fixture.detectChanges();
533555
const expectedDate = moment(new Date()).format(DATE_FORMAT_YEAR);
534-
const startDateInput: HTMLInputElement = fixture.debugElement.
535-
nativeElement.querySelector(`input[id="start_date"],input[max="${component.getCurrentDate()}"]`);
556+
const startDateInput: HTMLInputElement = fixture.debugElement.nativeElement.querySelector(
557+
`input[id="start_date"],input[max="${component.getCurrentDate()}"]`
558+
);
536559

537560
expect(startDateInput.id).toEqual('start_date');
538561
expect(startDateInput.max).toEqual(expectedDate);
@@ -569,7 +592,7 @@ describe('DetailsFieldsComponent', () => {
569592
expectedTimeDiff: '00:00',
570593
},
571594
];
572-
diffParams.map((param) => {
595+
diffParams.forEach((param) => {
573596
it(`if [start_date, start_hour] and [end_date, end_hour] diff is ${param.case}`, () => {
574597
component.entryForm.setValue({ ...formValues, ...param.entryDates });
575598
const timeDiff = component.getTimeDifference();
@@ -579,8 +602,13 @@ describe('DetailsFieldsComponent', () => {
579602
});
580603

581604
it('should find an activity with given id & status: inactive', () => {
582-
583-
const expectedActivity = { id: 'fc5fab41-a21e-4155-9d05-511b956ebd08', tenant_id: 'ioet_2', deleted: null, name: 'ghi', status: 'inactive' };
605+
const expectedActivity = {
606+
id: 'fc5fab41-a21e-4155-9d05-511b956ebd08',
607+
tenant_id: 'ioet_2',
608+
deleted: null,
609+
name: 'ghi',
610+
status: 'inactive',
611+
};
584612

585613
component.entryToEdit = { ...entryToEdit, activity_id: 'fc5fab41-a21e-4155-9d05-511b956ebd08' };
586614
spyOn(component.entryForm, 'patchValue');

src/app/modules/shared/components/details-fields/details-fields.component.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@ import * as moment from 'moment';
66
import { ToastrService } from 'ngx-toastr';
77
import { filter, map, mergeMap } from 'rxjs/operators';
88
import { getCreateError, getUpdateError } from 'src/app/modules/time-clock/store/entry.selectors';
9-
import { ActivityState, allActiveActivities, allActivities, LoadActivities } from '../../../activities-management/store';
9+
import {
10+
ActivityState,
11+
allActiveActivities,
12+
allActivities,
13+
LoadActivities,
14+
} from '../../../activities-management/store';
1015
import * as projectActions from '../../../customer-management/components/projects/components/store/project.actions';
1116
import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer';
1217
import { getProjects } from '../../../customer-management/components/projects/components/store/project.selectors';
@@ -73,7 +78,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
7378
this.listProjects = [];
7479
projects.forEach((project) => {
7580
const projectWithSearchField = { ...project };
76-
projectWithSearchField.search_field = `${project.customer_name} - ${project.name}`;
81+
projectWithSearchField.search_field = `${project.customer.name} - ${project.name}`;
7782
this.listProjects.push(projectWithSearchField);
7883
});
7984
}
@@ -162,13 +167,16 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
162167

163168
this.activities$ = this.store.pipe(
164169
select(allActiveActivities),
165-
mergeMap(activeActivities => this.store.pipe(
166-
select(allActivities),
167-
map(activities => this.findInactiveActivity(activities) !== undefined
168-
? [...activeActivities, this.findInactiveActivity(activities)]
169-
: activeActivities
170+
mergeMap((activeActivities) =>
171+
this.store.pipe(
172+
select(allActivities),
173+
map((activities) =>
174+
this.findInactiveActivity(activities) !== undefined
175+
? [...activeActivities, this.findInactiveActivity(activities)]
176+
: activeActivities
177+
)
170178
)
171-
))
179+
)
172180
);
173181
} else {
174182
this.cleanForm();
@@ -204,8 +212,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit {
204212
}
205213

206214
findInactiveActivity(activities) {
207-
return activities.find(activity => activity.status === 'inactive' &&
208-
activity.id === this.entryToEdit.activity_id
215+
return activities.find(
216+
(activity) => activity.status === 'inactive' && activity.id === this.entryToEdit.activity_id
209217
);
210218
}
211219

src/app/modules/shared/models/project.model.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1+
import { Customer } from '../models';
12
export interface Project {
23
id?: string;
34
customer_id?: string;
4-
customer_name?: string;
5+
customer?: Customer;
56
name: string;
67
description?: string;
78
project_type_id?: string;
89
search_field?: string;
910
status?: any;
1011
}
11-
1212
export interface ProjectUI {
1313
id?: string;
1414
customer_id?: string;
15-
customer_name?: string;
1615
name?: string;
1716
description?: string;
1817
project_type_id?: string;

0 commit comments

Comments
 (0)