import { ComponentFixture, TestBed, waitForAsync, } from '@angular/core/testing'; import { FormsModule } from '@angular/forms'; import { Router } from '@angular/router'; import { TranslateModule } from '@ngx-translate/core'; import { utcToZonedTime, zonedTimeToUtc, } from 'date-fns-tz'; import { UiSwitchModule } from 'ngx-ui-switch'; import { RequestService } from '../../core/data/request.service'; import { SystemWideAlertDataService } from '../../core/data/system-wide-alert-data.service'; import { NotificationsService } from '../../shared/notifications/notifications.service'; import { createFailedRemoteDataObject$, createSuccessfulRemoteDataObject$, } from '../../shared/remote-data.utils'; import { NotificationsServiceStub } from '../../shared/testing/notifications-service.stub'; import { RouterStub } from '../../shared/testing/router.stub'; import { createPaginatedList } from '../../shared/testing/utils.test'; import { SystemWideAlert } from '../system-wide-alert.model'; import { SystemWideAlertFormComponent } from './system-wide-alert-form.component'; describe('SystemWideAlertFormComponent', () => { let comp: SystemWideAlertFormComponent; let fixture: ComponentFixture<SystemWideAlertFormComponent>; let systemWideAlertDataService: SystemWideAlertDataService; let systemWideAlert: SystemWideAlert; let requestService: RequestService; let notificationsService; let router; beforeEach(waitForAsync(() => { const countDownDate = new Date(); countDownDate.setDate(countDownDate.getDate() + 1); countDownDate.setHours(countDownDate.getHours() + 1); countDownDate.setMinutes(countDownDate.getMinutes() + 1); systemWideAlert = Object.assign(new SystemWideAlert(), { alertId: 1, message: 'Test alert message', active: true, countdownTo: utcToZonedTime(countDownDate, 'UTC').toISOString(), }); systemWideAlertDataService = jasmine.createSpyObj('systemWideAlertDataService', { findAll: createSuccessfulRemoteDataObject$(createPaginatedList([systemWideAlert])), put: createSuccessfulRemoteDataObject$(systemWideAlert), create: createSuccessfulRemoteDataObject$(systemWideAlert), }); requestService = jasmine.createSpyObj('requestService', ['setStaleByHrefSubstring']); notificationsService = new NotificationsServiceStub(); router = new RouterStub(); TestBed.configureTestingModule({ imports: [FormsModule, UiSwitchModule, TranslateModule.forRoot(), SystemWideAlertFormComponent], providers: [ { provide: SystemWideAlertDataService, useValue: systemWideAlertDataService }, { provide: NotificationsService, useValue: notificationsService }, { provide: Router, useValue: router }, { provide: RequestService, useValue: requestService }, ], }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(SystemWideAlertFormComponent); comp = fixture.componentInstance; spyOn(comp, 'createForm').and.callThrough(); spyOn(comp, 'initFormValues').and.callThrough(); fixture.detectChanges(); }); describe('init', () => { it('should init the comp', () => { expect(comp).toBeTruthy(); }); it('should create the form and init the values based on an existing alert', () => { expect(comp.createForm).toHaveBeenCalled(); expect(comp.initFormValues).toHaveBeenCalledWith(systemWideAlert); }); }); describe('createForm', () => { it('should create the form', () => { const now = new Date(); comp.createForm(); expect(comp.formMessage.value).toEqual(''); expect(comp.formActive.value).toEqual(false); expect(comp.time).toEqual({ hour: now.getHours(), minute: now.getMinutes() }); expect(comp.date).toEqual({ year: now.getFullYear(), month: now.getMonth() + 1, day: now.getDate() }); }); }); describe('initFormValues', () => { it('should fill in the form based on the provided system-wide alert', () => { comp.initFormValues(systemWideAlert); const countDownTo = zonedTimeToUtc(systemWideAlert.countdownTo, 'UTC'); expect(comp.formMessage.value).toEqual(systemWideAlert.message); expect(comp.formActive.value).toEqual(true); expect(comp.time).toEqual({ hour: countDownTo.getHours(), minute: countDownTo.getMinutes() }); expect(comp.date).toEqual({ year: countDownTo.getFullYear(), month: countDownTo.getMonth() + 1, day: countDownTo.getDate(), }); }); }); describe('setCounterEnabled', () => { it('should set the preview time on enable and update the behaviour subject', () => { spyOn(comp, 'updatePreviewTime'); comp.setCounterEnabled(true); expect(comp.updatePreviewTime).toHaveBeenCalled(); expect(comp.counterEnabled$.value).toBeTrue(); }); it('should reset the preview time on disable and update the behaviour subject', () => { spyOn(comp, 'updatePreviewTime'); comp.setCounterEnabled(false); expect(comp.updatePreviewTime).not.toHaveBeenCalled(); expect(comp.previewDays).toEqual(0); expect(comp.previewHours).toEqual(0); expect(comp.previewMinutes).toEqual(0); expect(comp.counterEnabled$.value).toBeFalse(); }); }); describe('updatePreviewTime', () => { it('should calculate the difference between the current date and the date configured in the form', () => { const countDownDate = new Date(); countDownDate.setDate(countDownDate.getDate() + 1); countDownDate.setHours(countDownDate.getHours() + 1); countDownDate.setMinutes(countDownDate.getMinutes() + 1); comp.time = { hour: countDownDate.getHours(), minute: countDownDate.getMinutes() }; comp.date = { year: countDownDate.getFullYear(), month: countDownDate.getMonth() + 1, day: countDownDate.getDate() }; comp.updatePreviewTime(); expect(comp.previewDays).toEqual(1); expect(comp.previewHours).toEqual(1); expect(comp.previewDays).toEqual(1); }); }); describe('setActive', () => { it('should set whether the alert is active and save the current alert', () => { spyOn(comp, 'save'); spyOn(comp.formActive, 'patchValue'); comp.setActive(true); expect(comp.formActive.patchValue).toHaveBeenCalledWith(true); expect(comp.save).toHaveBeenCalledWith(false); }); }); describe('save', () => { it('should update the exising alert with the form values and show a success notification on success and navigate back', () => { spyOn(comp, 'back'); comp.currentAlert = systemWideAlert; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; const expectedAlert = new SystemWideAlert(); expectedAlert.alertId = systemWideAlert.alertId; expectedAlert.message = 'New message'; expectedAlert.active = true; const countDownTo = new Date(2023, 0, 25, 4, 26); expectedAlert.countdownTo = utcToZonedTime(countDownTo, 'UTC').toUTCString(); comp.save(); expect(systemWideAlertDataService.put).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.success).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).toHaveBeenCalled(); }); it('should update the exising alert with the form values and show a success notification on success and not navigate back when false is provided to the save method', () => { spyOn(comp, 'back'); comp.currentAlert = systemWideAlert; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; const expectedAlert = new SystemWideAlert(); expectedAlert.alertId = systemWideAlert.alertId; expectedAlert.message = 'New message'; expectedAlert.active = true; const countDownTo = new Date(2023, 0, 25, 4, 26); expectedAlert.countdownTo = utcToZonedTime(countDownTo, 'UTC').toUTCString(); comp.save(false); expect(systemWideAlertDataService.put).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.success).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).not.toHaveBeenCalled(); }); it('should update the exising alert with the form values but add an empty countdown date when disabled and show a success notification on success', () => { spyOn(comp, 'back'); comp.currentAlert = systemWideAlert; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; comp.counterEnabled$.next(false); const expectedAlert = new SystemWideAlert(); expectedAlert.alertId = systemWideAlert.alertId; expectedAlert.message = 'New message'; expectedAlert.active = true; expectedAlert.countdownTo = null; comp.save(); expect(systemWideAlertDataService.put).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.success).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).toHaveBeenCalled(); }); it('should update the exising alert with the form values and show a error notification on error', () => { spyOn(comp, 'back'); (systemWideAlertDataService.put as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$()); comp.currentAlert = systemWideAlert; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; const expectedAlert = new SystemWideAlert(); expectedAlert.alertId = systemWideAlert.alertId; expectedAlert.message = 'New message'; expectedAlert.active = true; const countDownTo = new Date(2023, 0, 25, 4, 26); expectedAlert.countdownTo = utcToZonedTime(countDownTo, 'UTC').toUTCString(); comp.save(); expect(systemWideAlertDataService.put).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.error).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).not.toHaveBeenCalled(); }); it('should create a new alert with the form values and show a success notification on success', () => { spyOn(comp, 'back'); comp.currentAlert = undefined; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; const expectedAlert = new SystemWideAlert(); expectedAlert.message = 'New message'; expectedAlert.active = true; const countDownTo = new Date(2023, 0, 25, 4, 26); expectedAlert.countdownTo = utcToZonedTime(countDownTo, 'UTC').toUTCString(); comp.save(); expect(systemWideAlertDataService.create).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.success).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).toHaveBeenCalled(); }); it('should create a new alert with the form values and show a error notification on error', () => { spyOn(comp, 'back'); (systemWideAlertDataService.create as jasmine.Spy).and.returnValue(createFailedRemoteDataObject$()); comp.currentAlert = undefined; comp.formMessage.patchValue('New message'); comp.formActive.patchValue(true); comp.time = { hour: 4, minute: 26 }; comp.date = { year: 2023, month: 1, day: 25 }; const expectedAlert = new SystemWideAlert(); expectedAlert.message = 'New message'; expectedAlert.active = true; const countDownTo = new Date(2023, 0, 25, 4, 26); expectedAlert.countdownTo = utcToZonedTime(countDownTo, 'UTC').toUTCString(); comp.save(); expect(systemWideAlertDataService.create).toHaveBeenCalledWith(expectedAlert); expect(notificationsService.error).toHaveBeenCalled(); expect(requestService.setStaleByHrefSubstring).not.toHaveBeenCalledWith('systemwidealerts'); expect(comp.back).not.toHaveBeenCalled(); }); it('should not create the new alert when the enable button is clicked on an invalid the form', () => { spyOn(comp as any, 'handleResponse'); comp.formMessage.patchValue(''); comp.save(); expect((comp as any).handleResponse).not.toHaveBeenCalled(); }); }); describe('back', () => { it('should navigate back to the home page', () => { comp.back(); expect(router.navigate).toHaveBeenCalledWith(['/home']); }); }); });