Skip to content

Commit af4c561

Browse files
Copilotrenemadsen
andcommitted
Fix observable propagation to child tab components and add unit tests
- Changed child components to accept boolean values instead of observables - Parent component now subscribes to observables and passes resolved values - Added proper lifecycle management with OnDestroy - Created unit tests for GeneralTabComponent and ShiftTabComponent - Added tests for observable subscription and form group getters - This fixes the issue where tabs weren't rendering in Cypress e2e tests Co-authored-by: renemadsen <[email protected]>
1 parent 337ebf6 commit af4c561

File tree

9 files changed

+345
-27
lines changed

9 files changed

+345
-27
lines changed

eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/assigned-site/assigned-site-dialog.component.html

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<app-assigned-site-general-tab
99
[data]="data"
1010
[assignedSiteForm]="assignedSiteForm"
11-
[selectCurrentUserIsFirstUser$]="selectCurrentUserIsFirstUser$"
12-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$">
11+
[isFirstUser]="isFirstUser"
12+
[isAdmin]="isAdmin">
1313
</app-assigned-site-general-tab>
1414
</mat-tab>
1515
<mat-tab label="{{'Plan hours' | translate }} "
@@ -37,7 +37,7 @@
3737
[shiftForm]="getFirstShiftFormGroup()"
3838
[data]="data"
3939
[shiftSuffix]="''"
40-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$"
40+
[isAdmin]="isAdmin"
4141
(minutesSet)="setMinutes($event.event, $event.field)">
4242
</app-assigned-site-shift-tab>
4343
</div>
@@ -49,7 +49,7 @@
4949
[shiftForm]="getSecondShiftFormGroup()"
5050
[data]="data"
5151
[shiftSuffix]="'2NdShift'"
52-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$"
52+
[isAdmin]="isAdmin"
5353
(minutesSet)="setMinutes($event.event, $event.field)">
5454
</app-assigned-site-shift-tab>
5555
</div>
@@ -61,7 +61,7 @@
6161
[shiftForm]="getThirdShiftFormGroup()"
6262
[data]="data"
6363
[shiftSuffix]="'3RdShift'"
64-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$"
64+
[isAdmin]="isAdmin"
6565
(minutesSet)="setMinutes($event.event, $event.field)">
6666
</app-assigned-site-shift-tab>
6767
</div>
@@ -73,7 +73,7 @@
7373
[shiftForm]="getFourthShiftFormGroup()"
7474
[data]="data"
7575
[shiftSuffix]="'4ThShift'"
76-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$"
76+
[isAdmin]="isAdmin"
7777
(minutesSet)="setMinutes($event.event, $event.field)">
7878
</app-assigned-site-shift-tab>
7979
</div>
@@ -85,7 +85,7 @@
8585
[shiftForm]="getFifthShiftFormGroup()"
8686
[data]="data"
8787
[shiftSuffix]="'5ThShift'"
88-
[selectCurrentUserIsAdmin$]="selectCurrentUserIsAdmin$"
88+
[isAdmin]="isAdmin"
8989
(minutesSet)="setMinutes($event.event, $event.field)">
9090
</app-assigned-site-shift-tab>
9191
</div>

eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/assigned-site/assigned-site-dialog.component.spec.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,4 +287,81 @@ describe('AssignedSiteDialogComponent', () => {
287287
expect(component.data['endMonday']).toBe(30);
288288
});
289289
});
290+
291+
describe('User Role Observables', () => {
292+
it('should subscribe to selectCurrentUserIsAdmin$ and update isAdmin', (done) => {
293+
component.ngOnInit();
294+
295+
// The mock store returns of(true) for all selects
296+
setTimeout(() => {
297+
expect(component.isAdmin).toBe(true);
298+
done();
299+
}, 100);
300+
});
301+
302+
it('should subscribe to selectCurrentUserIsFirstUser$ and update isFirstUser', (done) => {
303+
component.ngOnInit();
304+
305+
// The mock store returns of(true) for all selects
306+
setTimeout(() => {
307+
expect(component.isFirstUser).toBe(true);
308+
done();
309+
}, 100);
310+
});
311+
312+
it('should unsubscribe on destroy', () => {
313+
component.ngOnInit();
314+
const destroySpy = jest.spyOn(component['destroy$'], 'next');
315+
const completeSpy = jest.spyOn(component['destroy$'], 'complete');
316+
317+
component.ngOnDestroy();
318+
319+
expect(destroySpy).toHaveBeenCalled();
320+
expect(completeSpy).toHaveBeenCalled();
321+
});
322+
});
323+
324+
describe('FormGroup Getters', () => {
325+
beforeEach(() => {
326+
component.ngOnInit();
327+
});
328+
329+
it('should return plan hours form group', () => {
330+
const planHoursGroup = component.getPlanHoursFormGroup();
331+
expect(planHoursGroup).toBeDefined();
332+
expect(planHoursGroup.get('monday')).toBeDefined();
333+
});
334+
335+
it('should return auto break settings form group', () => {
336+
const autoBreakGroup = component.getAutoBreakSettingsFormGroup();
337+
expect(autoBreakGroup).toBeDefined();
338+
expect(autoBreakGroup.get('monday')).toBeDefined();
339+
});
340+
341+
it('should return first shift form group', () => {
342+
const firstShiftGroup = component.getFirstShiftFormGroup();
343+
expect(firstShiftGroup).toBeDefined();
344+
expect(firstShiftGroup.get('monday')).toBeDefined();
345+
});
346+
347+
it('should return second shift form group', () => {
348+
const secondShiftGroup = component.getSecondShiftFormGroup();
349+
expect(secondShiftGroup).toBeDefined();
350+
});
351+
352+
it('should return third shift form group', () => {
353+
const thirdShiftGroup = component.getThirdShiftFormGroup();
354+
expect(thirdShiftGroup).toBeDefined();
355+
});
356+
357+
it('should return fourth shift form group', () => {
358+
const fourthShiftGroup = component.getFourthShiftFormGroup();
359+
expect(fourthShiftGroup).toBeDefined();
360+
});
361+
362+
it('should return fifth shift form group', () => {
363+
const fifthShiftGroup = component.getFifthShiftFormGroup();
364+
expect(fifthShiftGroup).toBeDefined();
365+
});
366+
});
290367
});

eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/assigned-site/assigned-site-dialog.component.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, DoCheck, OnInit,
1+
import {Component, DoCheck, OnInit, OnDestroy,
22
inject
33
} from '@angular/core';
44
import {
@@ -17,6 +17,7 @@ import {
1717
ReactiveFormsModule,
1818
FormControl,
1919
} from '@angular/forms';
20+
import { Subject, takeUntil } from 'rxjs';
2021

2122

2223
@Component({
@@ -25,7 +26,7 @@ import {
2526
styleUrls: ['./assigned-site-dialog.component.scss'],
2627
standalone: false
2728
})
28-
export class AssignedSiteDialogComponent implements DoCheck, OnInit {
29+
export class AssignedSiteDialogComponent implements DoCheck, OnInit, OnDestroy {
2930
private fb = inject(FormBuilder);
3031
public data = inject<AssignedSiteModel>(MAT_DIALOG_DATA);
3132
private timePlanningPnSettingsService = inject(TimePlanningPnSettingsService);
@@ -35,8 +36,11 @@ export class AssignedSiteDialogComponent implements DoCheck, OnInit {
3536

3637
public selectCurrentUserIsAdmin$ = this.store.select(selectCurrentUserIsAdmin);
3738
public selectCurrentUserIsFirstUser$ = this.store.select(selectCurrentUserIsFirstUser);
39+
public isAdmin: boolean = false;
40+
public isFirstUser: boolean = false;
3841
private previousData: AssignedSiteModel;
3942
private globalAutoBreakSettings: GlobalAutoBreakSettingsModel;
43+
private destroy$ = new Subject<void>();
4044

4145

4246

@@ -50,6 +54,16 @@ export class AssignedSiteDialogComponent implements DoCheck, OnInit {
5054
ngOnInit(): void {
5155
this.previousData = {...this.data};
5256
// this.calculateHours();
57+
58+
// Subscribe to observables to get boolean values for child components
59+
this.selectCurrentUserIsAdmin$.pipe(takeUntil(this.destroy$)).subscribe(isAdmin => {
60+
this.isAdmin = isAdmin;
61+
});
62+
63+
this.selectCurrentUserIsFirstUser$.pipe(takeUntil(this.destroy$)).subscribe(isFirstUser => {
64+
this.isFirstUser = isFirstUser;
65+
});
66+
5367
this.timePlanningPnSettingsService.getGlobalAutoBreakCalculationSettings().subscribe(result => {
5468
if (result && result.success) {
5569
this.globalAutoBreakSettings = result.model;
@@ -566,4 +580,9 @@ export class AssignedSiteDialogComponent implements DoCheck, OnInit {
566580
return this.assignedSiteForm.get('fifthShift') as FormGroup;
567581
}
568582

583+
ngOnDestroy(): void {
584+
this.destroy$.next();
585+
this.destroy$.complete();
586+
}
587+
569588
}

eform-client/src/app/plugins/modules/time-planning-pn/components/plannings/time-planning-actions/assigned-site/tabs/general-tab.component.html

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="d-flex flex-row" *ngIf="!data.resigned && selectCurrentUserIsFirstUser$ | async">
1+
<div class="d-flex flex-row" *ngIf="!data.resigned && isFirstUser">
22
<!-- data.useGoogleSheetAsDefault -->
33
<mat-checkbox class="p-1"
44
[id]="'useGoogleSheetAsDefault'"
@@ -12,7 +12,7 @@
1212

1313
</div>
1414
<div class="d-flex flex-row"
15-
*ngIf="!data.resigned && !data.useGoogleSheetAsDefault && selectCurrentUserIsFirstUser$ | async">
15+
*ngIf="!data.resigned && !data.useGoogleSheetAsDefault && isFirstUser">
1616
<!-- data.useOnlyPlanHours checkbox -->
1717
<mat-checkbox class="p-1"
1818
[id]="'useOnlyPlanHours'"
@@ -25,7 +25,7 @@
2525
</mat-checkbox>
2626
</div>
2727
<div class="d-flex flex-row"
28-
*ngIf="!data.resigned && data.globalAutoBreakCalculationActive && selectCurrentUserIsAdmin$ | async">
28+
*ngIf="!data.resigned && data.globalAutoBreakCalculationActive && isAdmin">
2929
<!-- data.autoBreakCalculationActive -->
3030
<mat-checkbox class="p-1"
3131
[id]="'autoBreakCalculationActive'"
@@ -37,7 +37,7 @@
3737
</div>
3838
</mat-checkbox>
3939
</div>
40-
<div class="d-flex flex-row" *ngIf="!data.resigned && selectCurrentUserIsAdmin$ | async">
40+
<div class="d-flex flex-row" *ngIf="!data.resigned && isAdmin">
4141
<!-- data.allowPersonalTimeRegistration -->
4242
<mat-checkbox class="p-1"
4343
[id]="'allowPersonalTimeRegistration'"
@@ -51,7 +51,7 @@
5151
</mat-checkbox>
5252
</div>
5353
<div class="d-flex flex-row"
54-
*ngIf="!data.daysBackInTimeAllowedEditingEnabled && !data.resigned && data.allowPersonalTimeRegistration && selectCurrentUserIsAdmin$ | async">
54+
*ngIf="!data.daysBackInTimeAllowedEditingEnabled && !data.resigned && data.allowPersonalTimeRegistration && isAdmin">
5555
<!-- data.allowEditOfRegistrations -->
5656
<mat-checkbox class="p-1"
5757
[id]="'allowEditOfRegistrations'"
@@ -65,7 +65,7 @@
6565
</mat-checkbox>
6666
</div>
6767
<div class="d-flex flex-row"
68-
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && !data.allowAcceptOfPlannedHours && selectCurrentUserIsAdmin$ | async">
68+
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && !data.allowAcceptOfPlannedHours && isAdmin">
6969
<!-- data.allowPersonalTimeRegistration -->
7070
<mat-checkbox class="p-1"
7171
[id]="'usePunchClock'"
@@ -79,7 +79,7 @@
7979
</mat-checkbox>
8080
</div>
8181
<div class="d-flex flex-row"
82-
*ngIf="!data.daysBackInTimeAllowedEditingEnabled && !data.resigned && data.allowPersonalTimeRegistration && !data.allowAcceptOfPlannedHours && data.usePunchClock && selectCurrentUserIsAdmin$ | async">
82+
*ngIf="!data.daysBackInTimeAllowedEditingEnabled && !data.resigned && data.allowPersonalTimeRegistration && !data.allowAcceptOfPlannedHours && data.usePunchClock && isAdmin">
8383
<!-- data.allowPersonalTimeRegistration -->
8484
<mat-checkbox class="p-1"
8585
[id]="'usePunchClockWithAllowRegisteringInHistory'"
@@ -93,7 +93,7 @@
9393
</mat-checkbox>
9494
</div>
9595
<div class="d-flex flex-row"
96-
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && !data.usePunchClock && selectCurrentUserIsAdmin$ | async">
96+
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && !data.usePunchClock && isAdmin">
9797
<!-- data.allowAcceptOfPlannedHours -->
9898
<mat-checkbox class="p-1"
9999
[id]="'allowAcceptOfPlannedHours'"
@@ -107,7 +107,7 @@
107107
</mat-checkbox>
108108
</div>
109109
<div class="d-flex flex-row"
110-
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && data.allowEditOfRegistrations && selectCurrentUserIsAdmin$ | async">
110+
*ngIf="!data.resigned && data.allowPersonalTimeRegistration && data.allowEditOfRegistrations && isAdmin">
111111
<!-- data.allowAcceptOfPlannedHours -->
112112
<mat-checkbox class="p-1"
113113
[id]="'daysBackInTimeAllowedEditingEnabled'"
@@ -120,21 +120,21 @@
120120
</div>
121121
</mat-checkbox>
122122
</div>
123-
<div class="d-flex flex-row" *ngIf="!data.resigned && selectCurrentUserIsAdmin$ | async">
123+
<div class="d-flex flex-row" *ngIf="!data.resigned && isAdmin">
124124
<mat-checkbox class="p-1"
125125
[id]="'thirdShiftActive'"
126126
[name]="'thirdShiftActive'"
127127
formControlName="thirdShiftActive">
128128
<div>{{ 'Enable third shift' | translate }}</div>
129129
</mat-checkbox>
130-
<mat-checkbox class="p-1" *ngIf="!data.resigned && data.thirdShiftActive && selectCurrentUserIsAdmin$ | async"
130+
<mat-checkbox class="p-1" *ngIf="!data.resigned && data.thirdShiftActive && isAdmin"
131131
[id]="'fourthShiftActive'"
132132
[name]="'fourthShiftActive'"
133133
formControlName="fourthShiftActive">
134134
<div>{{ 'Enable fourth shift' | translate }}</div>
135135
</mat-checkbox>
136136
<mat-checkbox class="p-1"
137-
*ngIf="!data.resigned && data.fourthShiftActive && data.thirdShiftActive && selectCurrentUserIsAdmin$ | async"
137+
*ngIf="!data.resigned && data.fourthShiftActive && data.thirdShiftActive && isAdmin"
138138
[id]="'fifthShiftActive'"
139139
[name]="'fifthShiftActive'"
140140
formControlName="fifthShiftActive">

0 commit comments

Comments
 (0)