Skip to content

Commit cacfee6

Browse files
Merge 40db859 into 9eae139
2 parents 9eae139 + 40db859 commit cacfee6

File tree

6 files changed

+68
-40
lines changed

6 files changed

+68
-40
lines changed

src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1+
import { Subscription } from 'rxjs';
12
import { LoadActiveEntry, EntryActionTypes, UpdateEntry } from './../../store/entry.actions';
23
import { ActivityManagementActionTypes } from './../../../activities-management/store/activity-management.actions';
34
import {waitForAsync, ComponentFixture, TestBed} from '@angular/core/testing';
45
import {MockStore, provideMockStore} from '@ngrx/store/testing';
56
import { FormsModule, ReactiveFormsModule, FormBuilder } from '@angular/forms';
6-
77
import {TechnologyState} from '../../../shared/store/technology.reducers';
88
import {allTechnologies} from '../../../shared/store/technology.selectors';
99
import {EntryFieldsComponent} from './entry-fields.component';
@@ -135,9 +135,7 @@ describe('EntryFieldsComponent', () => {
135135
};
136136

137137
spyOn(component.entryForm, 'patchValue');
138-
139138
component.setDataToUpdate(entry);
140-
141139
expect(component.entryForm.patchValue).toHaveBeenCalledTimes(1);
142140
expect(component.entryForm.patchValue).toHaveBeenCalledWith(
143141
{
@@ -156,6 +154,7 @@ describe('EntryFieldsComponent', () => {
156154
start_date : moment().format(DATE_FORMAT_YEAR),
157155
start_hour : moment().format('HH:mm')
158156
};
157+
159158
component.newData = mockEntry;
160159
component.activeEntry = mockEntry ;
161160
component.setDataToUpdate(mockEntry);
@@ -412,4 +411,18 @@ describe('EntryFieldsComponent', () => {
412411
expect(component.selectedTechnologies).toBe(initialTechnologies);
413412
});
414413

414+
it('calls unsubscribe on ngDestroy', () => {
415+
component.loadActivitiesSubscription = new Subscription();
416+
component.loadActiveEntrySubscription = new Subscription();
417+
component.actionSetDateSubscription = new Subscription();
418+
spyOn(component.loadActivitiesSubscription, 'unsubscribe');
419+
spyOn(component.loadActiveEntrySubscription, 'unsubscribe');
420+
spyOn(component.actionSetDateSubscription, 'unsubscribe');
421+
422+
component.ngOnDestroy();
423+
424+
expect(component.loadActivitiesSubscription.unsubscribe).toHaveBeenCalled();
425+
expect(component.loadActiveEntrySubscription.unsubscribe).toHaveBeenCalled();
426+
expect(component.actionSetDateSubscription.unsubscribe).toHaveBeenCalled();
427+
});
415428
});

src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { ActivityManagementActionTypes } from './../../../activities-management/store/activity-management.actions';
22
import { EntryActionTypes, LoadActiveEntry } from './../../store/entry.actions';
33
import { filter } from 'rxjs/operators';
4-
import { Component, OnInit } from '@angular/core';
4+
import { Component, OnDestroy, OnInit } from '@angular/core';
55
import { FormBuilder, FormGroup } from '@angular/forms';
66
import { Store, ActionsSubject, select } from '@ngrx/store';
77
import { Activity, NewEntry } from '../../../shared/models';
88
import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer';
99
import { TechnologyState } from '../../../shared/store/technology.reducers';
1010
import { ActivityState, LoadActivities } from '../../../activities-management/store';
11-
1211
import * as entryActions from '../../store/entry.actions';
1312
import { get } from 'lodash';
1413
import * as moment from 'moment';
1514
import { ToastrService } from 'ngx-toastr';
1615
import { formatDate } from '@angular/common';
1716
import { getTimeEntriesDataSource } from '../../store/entry.selectors';
1817
import { DATE_FORMAT } from 'src/environments/environment';
18+
import { Subscription } from 'rxjs';
1919

2020
type Merged = TechnologyState & ProjectState & ActivityState;
2121

@@ -24,14 +24,17 @@ type Merged = TechnologyState & ProjectState & ActivityState;
2424
templateUrl: './entry-fields.component.html',
2525
styleUrls: ['./entry-fields.component.scss'],
2626
})
27-
export class EntryFieldsComponent implements OnInit {
27+
export class EntryFieldsComponent implements OnInit, OnDestroy {
2828
entryForm: FormGroup;
2929
selectedTechnologies: string[] = [];
3030
activities: Activity[] = [];
3131
activeEntry;
3232
newData;
3333
lastEntry;
3434
showTimeInbuttons = false;
35+
loadActivitiesSubscription: Subscription;
36+
loadActiveEntrySubscription: Subscription;
37+
actionSetDateSubscription: Subscription;
3538

3639
constructor(
3740
private formBuilder: FormBuilder,
@@ -48,17 +51,16 @@ export class EntryFieldsComponent implements OnInit {
4851
});
4952
}
5053

51-
ngOnInit(): void {
54+
ngOnInit(): void {
5255
this.store.dispatch(new LoadActivities());
5356
this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1, new Date().getFullYear()));
54-
this.actionsSubject$
57+
this.loadActivitiesSubscription = this.actionsSubject$
5558
.pipe(filter((action: any) => action.type === ActivityManagementActionTypes.LOAD_ACTIVITIES_SUCCESS))
5659
.subscribe((action) => {
5760
this.activities = action.payload;
5861
this.store.dispatch(new LoadActiveEntry());
5962
});
60-
61-
this.actionsSubject$
63+
this.loadActiveEntrySubscription = this.actionsSubject$
6264
.pipe(
6365
filter(
6466
(action: any) =>
@@ -76,8 +78,7 @@ export class EntryFieldsComponent implements OnInit {
7678
this.store.dispatch(new entryActions.LoadEntriesSummary());
7779
}
7880
});
79-
80-
this.actionsSubject$
81+
this.actionSetDateSubscription = this.actionsSubject$
8182
.pipe(filter((action: any) => action.type === EntryActionTypes.LOAD_ACTIVE_ENTRY_SUCCESS))
8283
.subscribe((action) => {
8384
this.activeEntry = action.payload;
@@ -90,17 +91,14 @@ export class EntryFieldsComponent implements OnInit {
9091
start_date: this.activeEntry.start_date,
9192
start_hour: formatDate(this.activeEntry.start_date, 'HH:mm', 'en'),
9293
};
93-
});
94+
});
9495
}
95-
9696
get activity_id() {
9797
return this.entryForm.get('activity_id');
9898
}
99-
10099
get start_hour() {
101100
return this.entryForm.get('start_hour');
102101
}
103-
104102
setDataToUpdate(entryData: NewEntry) {
105103
if (entryData) {
106104
this.entryForm.patchValue({
@@ -174,4 +172,10 @@ export class EntryFieldsComponent implements OnInit {
174172
onTechnologyRemoved($event: string[]) {
175173
this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, technologies: $event }));
176174
}
175+
176+
ngOnDestroy(): void {
177+
this.loadActivitiesSubscription.unsubscribe();
178+
this.loadActiveEntrySubscription.unsubscribe();
179+
this.actionSetDateSubscription.unsubscribe();
180+
}
177181
}

src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.spec.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
55
import { provideMockStore, MockStore } from '@ngrx/store/testing';
66
import { HttpClientTestingModule } from '@angular/common/http/testing';
77
import { AutocompleteLibModule } from 'angular-ng-autocomplete';
8-
import { Subscription } from 'rxjs';
8+
import { Subscription, of } from 'rxjs';
99
import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer';
1010
import { getCustomerProjects } from '../../../customer-management/components/projects/components/store/project.selectors';
1111
import { FilterProjectPipe } from '../../../shared/pipes';
@@ -100,11 +100,17 @@ describe('ProjectListHoverComponent', () => {
100100

101101
it('calls unsubscribe on ngDestroy', () => {
102102
component.updateEntrySubscription = new Subscription();
103+
component.projectsSubscription = new Subscription();
104+
component.activeEntrySubscription = new Subscription();
103105
spyOn(component.updateEntrySubscription, 'unsubscribe');
106+
spyOn(component.projectsSubscription, 'unsubscribe');
107+
spyOn(component.activeEntrySubscription, 'unsubscribe');
104108

105109
component.ngOnDestroy();
106110

107111
expect(component.updateEntrySubscription.unsubscribe).toHaveBeenCalled();
112+
expect(component.projectsSubscription.unsubscribe).toHaveBeenCalled();
113+
expect(component.activeEntrySubscription.unsubscribe).toHaveBeenCalled();
108114
});
109115

110116
it('sets customer name and project name on setSelectedProject', () => {
@@ -115,10 +121,9 @@ describe('ProjectListHoverComponent', () => {
115121
component.setSelectedProject();
116122

117123
expect(component.projectsForm.setValue)
118-
.toHaveBeenCalledWith({ project_id: 'customer - xyz'});
124+
.toHaveBeenCalledWith({ project_id: 'customer - xyz'});
119125
});
120126

121-
122127
// TODO Fix this test since it is throwing this error
123128
// Expected spy dispatch to have been called with:
124129
// [CreateEntry({ payload: Object({ project_id: '1', start_date: '2020-07-27T22:30:26.743Z', timezone_offset: 300 }),
@@ -140,5 +145,4 @@ describe('ProjectListHoverComponent', () => {
140145
// })
141146
// );
142147
// });
143-
144148
});

src/app/modules/time-clock/components/project-list-hover/project-list-hover.component.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { FormBuilder, FormGroup } from '@angular/forms';
33
import { ActionsSubject, select, Store } from '@ngrx/store';
44
import { ToastrService } from 'ngx-toastr';
55
import { Observable, Subscription } from 'rxjs';
6-
import { delay, filter } from 'rxjs/operators';
6+
import { delay, filter, map } from 'rxjs/operators';
77
import { Project } from 'src/app/modules/shared/models';
88
import * as actions from '../../../customer-management/components/projects/components/store/project.actions';
99
import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer';
@@ -17,25 +17,26 @@ import { getActiveTimeEntry } from './../../store/entry.selectors';
1717
styleUrls: ['./project-list-hover.component.scss'],
1818
})
1919
export class ProjectListHoverComponent implements OnInit, OnDestroy {
20-
2120
keyword = 'search_field';
2221
listProjects: Project[] = [];
2322
activeEntry;
2423
projectsForm: FormGroup;
2524
showClockIn: boolean;
2625
updateEntrySubscription: Subscription;
2726
isLoading$: Observable<boolean>;
27+
projectsSubscription: Subscription;
28+
activeEntrySubscription: Subscription;
2829

2930
constructor(private formBuilder: FormBuilder, private store: Store<ProjectState>,
3031
private actionsSubject$: ActionsSubject, private toastrService: ToastrService) {
3132
this.projectsForm = this.formBuilder.group({ project_id: null, });
3233
this.isLoading$ = this.store.pipe(delay(0), select(getIsLoading));
3334
}
3435

35-
ngOnInit(): void {
36+
ngOnInit(): void {
3637
this.store.dispatch(new actions.LoadProjects());
3738
const projects$ = this.store.pipe(select(getProjects));
38-
projects$.subscribe((projects) => {
39+
this.projectsSubscription = projects$.subscribe((projects) => {
3940
this.listProjects = [];
4041
projects.forEach((project) => {
4142
const projectWithSearchField = {...project};
@@ -45,7 +46,6 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
4546
);
4647
this.loadActiveTimeEntry();
4748
});
48-
4949
this.updateEntrySubscription = this.actionsSubject$.pipe(
5050
filter((action: any) => (
5151
action.type === EntryActionTypes.UPDATE_ENTRY_SUCCESS
@@ -55,13 +55,12 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
5555
this.activeEntry = action.payload;
5656
this.setSelectedProject();
5757
});
58-
5958
}
6059

6160
loadActiveTimeEntry() {
6261
this.store.dispatch(new entryActions.LoadActiveEntry());
6362
const activeEntry$ = this.store.pipe(select(getActiveTimeEntry));
64-
activeEntry$.subscribe((activeEntry) => {
63+
this.activeEntrySubscription = activeEntry$.subscribe((activeEntry) => {
6564
this.activeEntry = activeEntry;
6665
if (activeEntry) {
6766
this.showClockIn = false;
@@ -72,13 +71,12 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
7271
}
7372
});
7473
}
75-
7674
setSelectedProject() {
7775
this.listProjects.forEach( (project) => {
7876
if (project.id === this.activeEntry.project_id) {
7977
this.projectsForm.setValue(
8078
{ project_id: `${project.customer_name} - ${project.name}`, }
81-
);
79+
);
8280
}
8381
});
8482
}
@@ -110,6 +108,8 @@ export class ProjectListHoverComponent implements OnInit, OnDestroy {
110108
}
111109

112110
ngOnDestroy(): void {
111+
this.projectsSubscription.unsubscribe();
112+
this.activeEntrySubscription.unsubscribe();
113113
this.updateEntrySubscription.unsubscribe();
114114
}
115115
}

src/app/modules/time-clock/pages/time-clock.component.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { of } from 'rxjs';
12
import { FormBuilder } from '@angular/forms';
23
import { StopTimeEntryRunning, EntryActionTypes, LoadEntriesSummary } from './../store/entry.actions';
34
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
@@ -95,12 +96,14 @@ describe('TimeClockComponent', () => {
9596
expect(component.reloadSummariesOnClockOut).toHaveBeenCalled();
9697
});
9798

98-
it('unsubscribe clockOutSubscription onDestroy', () => {
99+
it('unsubscribe clockOutSubscription, storeSubscription onDestroy', () => {
99100
spyOn(component.clockOutSubscription, 'unsubscribe');
101+
spyOn(component.storeSubscription, 'unsubscribe');
100102

101103
component.ngOnDestroy();
102104

103105
expect(component.clockOutSubscription.unsubscribe).toHaveBeenCalled();
106+
expect(component.storeSubscription.unsubscribe).toHaveBeenCalled();
104107
});
105108

106109
it('onInit checks if isLogin and gets the userName', () => {

src/app/modules/time-clock/pages/time-clock.component.ts

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
22
import { ActionsSubject, select, Store } from '@ngrx/store';
33
import { ToastrService } from 'ngx-toastr';
44
import { Subscription } from 'rxjs';
5-
import { filter } from 'rxjs/operators';
5+
6+
import { filter, map } from 'rxjs/operators';
7+
import { threadId } from 'worker_threads';
68
import { AzureAdB2CService } from '../../login/services/azure.ad.b2c.service';
79
import { EntryFieldsComponent } from '../components/entry-fields/entry-fields.component';
810
import { Entry } from './../../shared/models/entry.model';
@@ -20,7 +22,7 @@ export class TimeClockComponent implements OnInit, OnDestroy {
2022
areFieldsVisible = false;
2123
activeTimeEntry: Entry;
2224
clockOutSubscription: Subscription;
23-
25+
storeSubscription: Subscription;
2426

2527
constructor(
2628
private azureAdB2CService: AzureAdB2CService,
@@ -29,23 +31,17 @@ export class TimeClockComponent implements OnInit, OnDestroy {
2931
private actionsSubject$: ActionsSubject
3032
) {}
3133

32-
ngOnDestroy(): void {
33-
this.clockOutSubscription.unsubscribe();
34-
}
35-
36-
ngOnInit() {
34+
ngOnInit(): void {
3735
this.username = this.azureAdB2CService.isLogin() ? this.azureAdB2CService.getName() : '';
38-
this.store.pipe(select(getActiveTimeEntry)).subscribe((activeTimeEntry) => {
36+
this.storeSubscription = this.store.pipe(select(getActiveTimeEntry)).subscribe((activeTimeEntry) => {
3937
this.activeTimeEntry = activeTimeEntry;
4038
if (this.activeTimeEntry) {
4139
this.areFieldsVisible = true;
4240
} else {
4341
this.areFieldsVisible = false;
4442
}
4543
});
46-
4744
this.reloadSummariesOnClockOut();
48-
4945
}
5046

5147
reloadSummariesOnClockOut() {
@@ -72,4 +68,12 @@ export class TimeClockComponent implements OnInit, OnDestroy {
7268
this.toastrService.error('Activity is required');
7369
}
7470
}
71+
72+
ngOnDestroy(): void {
73+
this.clockOutSubscription.unsubscribe();
74+
this.storeSubscription.unsubscribe();
75+
}
76+
7577
}
78+
79+

0 commit comments

Comments
 (0)