diff --git a/src/layouts/schedule/schedule.spec.js b/src/layouts/schedule/schedule.spec.js new file mode 100644 index 000000000..7d5cdcec1 --- /dev/null +++ b/src/layouts/schedule/schedule.spec.js @@ -0,0 +1,183 @@ +// Components +import schedule from "@/layouts/schedule/schedule.vue"; + +// Supporting Files +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { routeData } from "@/router/constants/routes"; +import store from "@/store"; +import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; + +const storeMocked = { + getters: { + payment: { isInsurance: false }, + order: { + payment: { isInsurance: false, insuranceCoverage: { isVerified: false } }, + referralNumber: "", + serviceLocation: { + address: "", + address2: "", + city: "", + state: "", + zipCode: "00000", + zipCodeCtu: "000", + appointmentType: null, + provider: {}, + isVehicleProtected: false, + }, + schedule: { + date: "", + routeCode: "", + startTime: "", + endTime: "", + jobMinMinutes: null, + jobMaxMinutes: null, + }, + policy: { + isItac: false, + isNoComp: false, + }, + damage: { isRepair: false }, + lineItems: { glassParts: [] }, + }, + vehicle: { + cardId: "", + }, + lineItems: { + supportingItems: [], + }, + applicationUser: { + experiments: [], + }, + isMobileAppointment: false, + }, +}; + +jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({ + navigateToHeritageFunnel: jest.fn(), +})); + +describe("schedule.vue", () => { + describe("navigation", () => { + test("backButtonAction => non-insurance: navigateWithoutSaving called", () => { + // Arrange + const { wrapper, mocks } = setupMocks(); + + // Act + wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith( + mocks.navigationScenarios.CLICKED_BACK, + routeData.SCHEDULE.name + ); + }); + + test("backButtonAction => insurance verified: navigateToHeritageFunnel called", () => { + // Arrange + store.getters.order.payment.isInsurance = true; + store.getters.order.payment.insuranceCoverage = { isVerified: true }; + store.getters.order.referralNumber = ""; + const { wrapper } = setupMocks(); + + // Act + wrapper.vm.backButtonAction(); + + // Assert + expect(navigateToHeritageFunnel).toHaveBeenCalledWith({ + shouldSaveSession: false, + pageNameToLog: "schedule", + navType: "back", + }); + }); + }); + + describe("computed: isForwardActionDisabled", () => { + test("should be true when routeCode missing or appointmentType not set", async () => { + const { wrapper } = setupMocks(); + await wrapper.setData({ + selectedTimeSlotInfo: { timeSlot: { routeCode: null } }, + appointmentType: null, + }); + expect(wrapper.vm.isForwardActionDisabled).toBe(true); + }); + + test("should be false when routeCode present and appointmentType set", async () => { + const { wrapper } = setupMocks(); + await wrapper.setData({ + selectedTimeSlotInfo: { timeSlot: { routeCode: "RC123" } }, + appointmentType: "SomeType", + }); + expect(wrapper.vm.isForwardActionDisabled).toBe(false); + }); + }); + + describe("computed: selectedRouteCodeData", () => { + test("should return null when routeCode not set", async () => { + const { wrapper } = setupMocks(); + await wrapper.setData({ + selectedTimeSlotInfo: { timeSlot: { routeCode: null } }, + }); + expect(wrapper.vm.selectedRouteCodeData).toBeNull(); + }); + + test("should return routeCode and premium flag when set", async () => { + const { wrapper } = setupMocks(); + await wrapper.setData({ + selectedTimeSlotInfo: { + timeSlot: { routeCode: "RC999" }, + isPremiumAppointment: true, + }, + }); + expect(wrapper.vm.selectedRouteCodeData).toEqual({ + routeCode: "RC999", + isPremiumAppointment: true, + }); + }); + }); + + describe("forwardButtonAction (early exit path)", () => { + test("shows recal acknowledgement popup and does not navigate when required", async () => { + const { wrapper } = setupMocks(); + // Force the recal-ack modal path + wrapper.vm.showRecalAcknowledgementModal = jest.fn(() => true); + await wrapper.setData({ isRecalAcknowledgedForScheduling: null }); + + await wrapper.vm.forwardButtonAction(); + + expect(wrapper.vm.showRecalAcknowledgementPopup).toBe(true); + expect(wrapper.vm.$router.navigateWithSaving).not.toHaveBeenCalled(); + }); + }); +}); + +function setupMocks(mountOptionsMockData = {}) { + const route = { name: "schedule" }; + const defaultMountOptions = { + route: route, + router: { + navigate: jest.fn(), + navigateWithSaving: jest.fn(), + navigateWithoutSaving: jest.fn(), + }, + store: { ...storeMocked }, + }; + const mockBaseMixin = { + methods: { + getTierOnePackagePrice: jest.fn(), + filterOutFees: jest.fn(), + getCmsContent: jest.fn(), + }, + }; + const baseMountOptions = getMountOptions({ + ...defaultMountOptions, + ...mountOptionsMockData, + }); + + baseMountOptions.global.mixins = [mockBaseMixin]; + baseMountOptions.global.mocks.pageName = route.name; + const wrapper = shallowMount(schedule, baseMountOptions); + wrapper.getCmsContent = jest.fn(); + + return { wrapper, mocks: baseMountOptions.global?.mocks || {} }; +}