From 47dbab0941cf26e149aa92128134a66d6abd0ce4 Mon Sep 17 00:00:00 2001 From: Katie Kroell Date: Fri, 3 Apr 2026 10:21:56 -0400 Subject: [PATCH] unit tests --- src/helpers/recal-helper.js | 1 - .../schedule-page/schedule-page.spec.js | 138 ++++++++++++++++-- src/layouts/schedule-page/schedule-page.vue | 6 +- 3 files changed, 126 insertions(+), 19 deletions(-) diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index d7d244e0..5ad9c390 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -80,4 +80,3 @@ export function anyPartWithRequiresRecalFlag(lineItems) { return lineItems.some((li) => li.requiresRecalibration === true); } - diff --git a/src/layouts/schedule-page/schedule-page.spec.js b/src/layouts/schedule-page/schedule-page.spec.js index a418f35e..9c939503 100644 --- a/src/layouts/schedule-page/schedule-page.spec.js +++ b/src/layouts/schedule-page/schedule-page.spec.js @@ -12,6 +12,8 @@ jest.mock('@/helpers/cms-content-helper', () => ({ fetchCmsContentForPage: jest.fn() })); +const RECAL_ACK_MODAL_REF_NAME = 'recalAckModal'; + const mockMixin = { methods: { getCmsContent: jest.fn().mockImplementation(() => ''), @@ -55,6 +57,22 @@ const loadingModalStub = { } }; +const serviceLocationStub = { + render: () => {}, + methods: { + forwardButtonAction: jest.fn(), + initializeComponent: jest.fn() + } +}; + +const recalAckModalStub = { + template: '
', + methods: { + openModal: jest.fn(), + footerButtonClick: jest.fn() + } +}; + function getShallowMountedComponent(initialData = {}, methodToRun = () => {}) { const mountOptions = getMountOptions({ router: { @@ -64,7 +82,9 @@ function getShallowMountedComponent(initialData = {}, methodToRun = () => {}) { mountOptions.global.stubs = { siteFooter: footerStub, - loadingModal: loadingModalStub + loadingModal: loadingModalStub, + serviceLocation: serviceLocationStub, + recalAckModal: recalAckModalStub }; methodToRun(); @@ -75,6 +95,27 @@ function getShallowMountedComponent(initialData = {}, methodToRun = () => {}) { ); const wrapper = shallowMount(schedule, mountOptions); + + // Manually create the ref for recalAckModal since shallowMount doesn't populate it + Object.defineProperty(wrapper.vm.$refs, RECAL_ACK_MODAL_REF_NAME, { + value: { + openModal: jest.fn(), + footerButtonClick: jest.fn() + }, + writable: false, + configurable: true + }); + + // Manually create the ref for serviceLocation since shallowMount doesn't populate it + Object.defineProperty(wrapper.vm.$refs, 'serviceLocation', { + value: { + forwardButtonAction: jest.fn(), + initializeComponent: jest.fn() + }, + writable: false, + configurable: true + }); + return { wrapper }; } @@ -126,7 +167,6 @@ afterEach(() => { jest.clearAllMocks(); }); -describe('schedule-page.vue', () => { beforeAll(() => { Object.defineProperty(window, 'matchMedia', { value: jest.fn().mockImplementation((query) => ({ matches: false, @@ -267,21 +307,87 @@ describe('schedule-page.vue', () => { // Assert expect(testValue).toStrictEqual('01234'); }); - }); - test.skip('forwardButtonAction should call route method navigateWithoutSaving', async () => { - // Arrange - const { wrapper } = getShallowMountedComponent(); - wrapper.vm.$router.navigate = jest.fn(() => ({})); - wrapper.vm.selectedTimeSlotInfo = { - timeSlot: { - routeCode: 'test-id' - } - }; + test('forwardButtonAction should call route method navigate', async () => { + // Arrange + const { wrapper } = getShallowMountedComponent(); + wrapper.vm.$router.navigate = jest.fn(() => ({})); + wrapper.vm.mainStore.saveSchedule = jest.fn(); + wrapper.vm.navigationScenarios = { + CLICKED_FORWARD: 'CLICKED_FORWARD' + }; + + // Mock the serviceLocation ref using Object.defineProperty to bypass readonly + Object.defineProperty(wrapper.vm.$refs, 'serviceLocation', { + value: { + forwardButtonAction: jest.fn() + }, + configurable: true + }); + + wrapper.vm.selectedTimeSlotInfo = { + timeSlot: { + routeCode: 'test-id' + } + }; - // Act - await wrapper.vm.forwardButtonAction(); + // Act + await wrapper.vm.forwardButtonAction(); - // Assert - expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + }); + test('recalAckModal should open when part requires recal, but recal not added to order', async () => { + // Arrange + const { wrapper } = getShallowMountedComponent(); + wrapper.vm.mainStore.lineItems.glassParts = [ + { + partNumber: 'TEST123', + requiresRecalibration: true + } + ]; + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$refs[RECAL_ACK_MODAL_REF_NAME].openModal).toHaveBeenCalled(); + }); + test('navigation forward is blocked when recalAckModal is displayed, but checkbox has not been acknowledged', async () => { + // Arrange + const { wrapper } = getShallowMountedComponent(); + wrapper.vm.mainStore.lineItems.glassParts = [ + { + partNumber: 'TEST123', + requiresRecalibration: true + } + ]; + + // Act + await wrapper.vm.forwardButtonAction(); + await wrapper.vm.$refs[RECAL_ACK_MODAL_REF_NAME].openModal(); + await wrapper.vm.$refs[RECAL_ACK_MODAL_REF_NAME].footerButtonClick(); + + // Assert + expect(wrapper.vm.$router.navigate).not.toHaveBeenCalled(); + }); + test('navigation forward is allowed when checkbox has been acknowledged on recalAckModal', async () => { + // Arrange + const { wrapper } = getShallowMountedComponent(); + wrapper.vm.mainStore.lineItems.glassParts = [ + { + partNumber: 'TEST123', + requiresRecalibration: true + } + ]; + + // Act + await wrapper.vm.$refs[RECAL_ACK_MODAL_REF_NAME].openModal(); + wrapper.vm.updateIsRecalAcknowledged(true); + await wrapper.vm.$refs[RECAL_ACK_MODAL_REF_NAME].footerButtonClick(); + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + }); }); }); diff --git a/src/layouts/schedule-page/schedule-page.vue b/src/layouts/schedule-page/schedule-page.vue index a2e7ddcf..257995c1 100644 --- a/src/layouts/schedule-page/schedule-page.vue +++ b/src/layouts/schedule-page/schedule-page.vue @@ -65,7 +65,7 @@ cmsWidgetName="SuggestTimeslotModal" @confirmAppointmentClicked="autoSelectTimeslotConfirmed" /> @@ -117,6 +117,7 @@ import errorMessages from '@/constants/error-messages'; // Define constants const SUGGEST_TIMESLOT_MODAL_REF_NAME = 'SuggestTimeslotModal'; const TIME_SLOTS_CALL_DAYS_LIMIT = 15; +const RECAL_ACK_MODAL_REF_NAME = 'recalAckModal'; const getAvailableDates = async ( startDateString, @@ -380,6 +381,7 @@ export default { selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(), showDatePickerError: false, SUGGEST_TIMESLOT_MODAL_REF_NAME, + RECAL_ACK_MODAL_REF_NAME, isRecalAcknowledged: this.getIsRecalAcknowledgedForScheduling() }; }, @@ -960,7 +962,7 @@ export default { async forwardButtonAction() { if (this.displayRecalAckModal && this.isRecalAcknowledged === false) { showIssLoadingModal(false); - this.$refs.recalAckModal.openModal(); + this.$refs[RECAL_ACK_MODAL_REF_NAME].openModal(); return; }