diff --git a/jest.config.js b/jest.config.js index aaf2d9ff8..0a6fbc048 100644 --- a/jest.config.js +++ b/jest.config.js @@ -26,8 +26,7 @@ module.exports = { testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], coverageThreshold: { global: { - statements: 75, - // Got the go ahead from Mark to temporarily lower this. Taking out initialize component made the year,make,model and style coverage drop a bit. Once unit tests for license plate lookup, vin lookup and address lookup are in the coverage should go back up to 90 + statements: 80, }, }, // Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit diff --git a/src/layouts/schedule/schedule.spec.js b/src/layouts/schedule/schedule.spec.js new file mode 100644 index 000000000..654e0e4c9 --- /dev/null +++ b/src/layouts/schedule/schedule.spec.js @@ -0,0 +1,228 @@ +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { applicationConfig } from "@/constants/application-config"; +import { storeActions } from "@/constants/store-actions"; +import schedule from "@/layouts/schedule/schedule.vue"; +import store from "@/store"; +import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; +import { nextTick } from "vue"; + +jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: () => Promise.resolve("content"), + splitCopyOnCMSPlaceHolder: jest.fn(() => ["A", "B"]), +})); + +jest.mock( + "@/store", + () => { + return {}; + }, + { virtual: true } +); + +store.getters = { + order: { + schedule: { + date: "2020-01-01", + }, + lineItems: { + glassParts: [], + supportingItems: [], + }, + serviceLocation: { + appointmentType: "Inshop", + }, + }, + lineItems: { + glassParts: [], + supportingItems: [], + }, +}; + +describe("schedule.vue", () => { + test("Should navigateWithoutSaving", async () => { + //Arrange + const { wrapper } = setupMocks({ + customMountOptions: { + router: { + navigateWithoutSaving: jest.fn(), + }, + route: { schedule }, + }, + }); + + wrapper.vm.dispatchStoreAction = jest.fn(() => { + return { + data: [], + }; + }); + + //Act + await wrapper.vm.forwardButtonAction(); + + //Assert + expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled(); + }); + test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => { + //Arrange + const { wrapper } = setupMocks({}); + store.getters = { + order: { + schedule: { + date: "2020-01-01", + }, + serviceLocation: { + zipCode: "12345", + zipCodeCtu: "value", + appointmentType: "Mobile", + }, + damage: { + isRepair: true, + }, + referralNumber: "1234567", + }, + payment: { + isInsurance: true, + }, + lineItems: { + supportingItems: [], + }, + }; + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + + expect(arePagePrerequisitesValid).toBe(true); + }); + test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => { + //Arrange + const { wrapper } = setupMocks({}); + store.getters = { + order: { + schedule: { + date: "2020-01-01", + }, + serviceLocation: { + zipCode: "12345", + zipCodeCtu: "value", + appointmentType: "Inshop", + provider: { + providerNumber: "5", + }, + }, + damage: { + isRepair: true, + }, + referralNumber: "1234567", + }, + payment: { + isInsurance: true, + }, + lineItems: { + supportingItems: [], + }, + }; + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + + expect(arePagePrerequisitesValid).toBe(true); + }); + test("should fail arePagePrerequisitesValid with a replace with no glass parts", () => { + //Arrange + const { wrapper } = setupMocks({}); + store.getters = { + order: { + schedule: { + date: "2020-01-01", + }, + serviceLocation: { + zipCode: "12345", + zipCodeCtu: "value", + appointmentType: "Inshop", + provider: { + providerNumber: "5", + }, + }, + damage: { + isRepair: false, + }, + referralNumber: "1234567", + }, + payment: { + isInsurance: true, + }, + lineItems: { + supportingItems: [], + glassParts: [], + }, + }; + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + + expect(arePagePrerequisitesValid).toBe(false); + }); + test("should fail arePagePrerequisitesValid without isInsurance", () => { + //Arrange + const { wrapper } = setupMocks({}); + store.getters = { + order: { + schedule: { + date: "2020-01-01", + }, + serviceLocation: { + zipCode: "12345", + zipCodeCtu: "value", + appointmentType: "Inshop", + provider: { + providerNumber: "5", + }, + }, + damage: { + isRepair: true, + }, + referralNumber: "1234567", + }, + payment: { + isInsurance: null, + }, + lineItems: { + supportingItems: [], + glassParts: [], + }, + }; + + let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); + + expect(arePagePrerequisitesValid).toBe(false); + }); +}); + +const mockCmsContent = {}; + +function setupMocks({ customMountOptions }) { + const mountOptions = getMountOptions({ + ...customMountOptions, + }); + + mountOptions.global.mocks["$store"] = store; + mountOptions["attachTo"] = document.body; + mountOptions.mixins = [ + { + methods: { + getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => { + if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName]) + return mockCmsContent[widgetName][fieldName]; + }), + }, + }, + ]; + + const wrapper = shallowMount(schedule, mountOptions); + wrapper.vm.setCmsContent = jest.fn(); + return { wrapper }; +} diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js new file mode 100644 index 000000000..43d997892 --- /dev/null +++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.spec.js @@ -0,0 +1,712 @@ +import { shallowMount, flushPromises } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import timeSlotModalQuestion from "@/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue"; +import store from "@/store"; +import { + RouteCodeFlags, + PREMIUM_TIME_SLOT_ID_FLAG, + PREMIUM_FEE_PART_TYPE, +} from "@/constants/schedule-constants"; + +describe("time-slot-modal-list-button-question.vue", () => { + test("When selected time slot is changed, a correctly formatted selectedTimeSlot should be emitted", async () => { + //Arrange + const date = "2023-07-01"; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + const expectedEmit = [ + [ + { + date: date, + routeCode: timeSlotId, + startTime: startTime, + endTime: endTime, + jobMaxMinutes: jobMaxMinutes.toString(), + }, + ], + ]; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + }, + }, + }); + + wrapper.vm.$refs.timeSlots.closeModal = jest.fn(); + wrapper.vm.selectedTimeSlotId = timeSlotId; + + //Act + wrapper.vm.setSelectedTimeSlot(); + + //Assert + expect(wrapper.emitted()["update:modelValue"]).toEqual(expectedEmit); + }); +}); +describe("time-slot-modal-list-button-question.vue Supplemental information", () => { + test("The correct supplemental information should be obtained from CMS - Mobile - Not Premium ", async () => { + //Arrange + const mobileCmsWidgetName = "MobileNotPremium"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "test" }, + appointmentType: "Mobile", + mobileCmsWidgetName: mobileCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toEqual( + mockCmsContent[mobileCmsWidgetName]["BodyText"] + ); + }); + test("The correct supplemental information should be obtained from CMS - Mobile - Premium", async () => { + //Arrange + const mobileCmsWidgetName = "MobilePremium"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "test" + PREMIUM_TIME_SLOT_ID_FLAG }, + appointmentType: "Mobile", + mobileCmsWidgetName: mobileCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toEqual( + mockCmsContent[mobileCmsWidgetName]["BodyText"] + ); + }); + test("No supplemental information should be obtained from CMS - Inshop", async () => { + //Arrange + const inshopWidgetName = "Inshop"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "test" }, + appointmentType: "Inshop", + cmsWidgetName: inshopWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toBeNull(); + }); + test("No supplemental information should be obtained from CMS - Drop off, nothing selected", async () => { + //Arrange + const dropOffWidgetName = "Dropoff"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: null, + appointmentType: "Dropoff", + cmsWidgetName: dropOffWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toBeNull(); + }); + test("Correct supplemental information should be retrieved, Dropoff regular", async () => { + //Arrange + const dropOffWidgetName = "Dropoff"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + dropoffCmsWidgetName: dropOffWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toEqual( + mockCmsContent[dropOffWidgetName]["BodyText"] + ); + }); + test("Correct supplemental information should be retrieved, Dropoff Overnight", async () => { + //Arrange + const overnightDropOffCmsWidgetName = "Overnight"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF }, + appointmentType: "Dropoff", + overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.supplementalInformationBlock).toEqual( + mockCmsContent[overnightDropOffCmsWidgetName]["BodyText"] + ); + }); + test("Correct supplemental information should be retrieved, Dropoff Sameday", async () => { + //Arrange + const sameDayDropOffCmsWidgetName = "Sameday"; + const date = new Date().toISOString().split("T")[0]; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName, + }, + }, + }); + + //Assert + expect(wrapper.vm.supplementalInformationBlock).toEqual( + mockCmsContent[sameDayDropOffCmsWidgetName]["BodyText"] + ); + }); +}); + +describe("time-slot-modal-list-button-question.vue Disclaimer", () => { + test("The correct disclaimer information should be obtained from CMS - Dropoff - Sameday ", async () => { + //Arrange + const sameDayDropOffCmsWidgetName = "Sameday"; + const date = new Date().toISOString().split("T")[0]; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName, + }, + }, + }); + + //Assert + expect(wrapper.vm.disclaimerTextBlockCopy).toEqual( + mockCmsContent[sameDayDropOffCmsWidgetName]["FooterText"] + ); + }); + test("Correct disclaimer information should be retrieved, Dropoff regular", async () => { + //Arrange + const dropOffWidgetName = "Dropoff"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + dropoffCmsWidgetName: dropOffWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.disclaimerTextBlockCopy).toEqual( + mockCmsContent[dropOffWidgetName]["FooterText"] + ); + }); + test("Correct disclaimer information should be retrieved, Dropoff overnight", async () => { + //Arrange + const overnightDropOffCmsWidgetName = "Overnight"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF }, + appointmentType: "Dropoff", + overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.disclaimerTextBlockCopy).toEqual( + mockCmsContent[overnightDropOffCmsWidgetName]["FooterText"] + ); + }); + test("No disclaimer information should be retrieved, non-dropoff", async () => { + //Arrange + const inshopWidgetName = "Inshop"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "test" }, + appointmentType: "Inshop", + cmsWidgetName: inshopWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.disclaimerTextBlockCopy).toBeNull(); + }); +}); + +describe("time-slot-modal-list-button-question.vue Duration", () => { + test("The correct duration information should be displayed - Dropoff - Sameday ", async () => { + //Arrange + const sameDayDropOffCmsWidgetName = "Sameday"; + const date = new Date().toISOString().split("T")[0]; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName, + }, + }, + }); + + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[sameDayDropOffCmsWidgetName]["SubheaderText"] + ); + }); + test("Correct duration information should be retrieved, Dropoff overnight", async () => { + //Arrange + const overnightDropOffCmsWidgetName = "Overnight"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.OVERNIGHT_DROP_OFF }, + appointmentType: "Dropoff", + overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[overnightDropOffCmsWidgetName]["SubheaderText"] + ); + }); + test("Correct duration information should be retrieved, Dropoff", async () => { + //Arrange + const dropoffCmsWidgetName = "Dropoff"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + modelValue: { routeCode: "Test" + RouteCodeFlags.ALL_DAY_DROP_OFF }, + appointmentType: "Dropoff", + dropoffCmsWidgetName: dropoffCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[dropoffCmsWidgetName]["SubheaderText"] + ); + }); + test("Correct duration information should be retrieved, Inshop - convert to hours", async () => { + //Arrange + const cmsWidgetName = "Inshop"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: 180, + estimatedServiceMinutesMinimum: 120, + modelValue: { routeCode: "Test" }, + appointmentType: "Inshop", + cmsWidgetName: cmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[cmsWidgetName]["SubheaderText"] + " 2 - 3 hours" + ); + }); + test("Correct duration information should be retrieved, Inshop - convert to minutes", async () => { + //Arrange + const cmsWidgetName = "Inshop"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: 90, + estimatedServiceMinutesMinimum: 60, + modelValue: { routeCode: "Test" }, + appointmentType: "Inshop", + cmsWidgetName: cmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[cmsWidgetName]["SubheaderText"] + " 60 - 90 minutes" + ); + }); + test("Correct duration information should be retrieved, Inshop - min = maximum time", async () => { + //Arrange + const cmsWidgetName = "Inshop"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: 240, + estimatedServiceMinutesMinimum: 240, + modelValue: { routeCode: "Test" }, + appointmentType: "Inshop", + cmsWidgetName: cmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toEqual( + mockCmsContent[cmsWidgetName]["SubheaderText"] + " 4 hours" + ); + }); + test("No duration information should be displayed, Mobile", async () => { + //Arrange + const mobileCmsWidgetName = "Mobile"; + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: 240, + estimatedServiceMinutesMinimum: 240, + modelValue: { routeCode: "Test" }, + appointmentType: "Mobile", + mobileCmsWidgetName: mobileCmsWidgetName, + }, + }, + }); + //Assert + expect(wrapper.vm.durationTextBlockCopy).toBeNull(); + }); +}); + +describe("time-slot-modal-list-button-question.vue Available Timeslots", () => { + test("Available Timeslots should be formatted correctly - Dropoff - Sameday ", async () => { + //Arrange + const sameDayDropOffCmsWidgetName = "Sameday"; + const date = new Date().toISOString().split("T")[0]; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + appointmentType: "Dropoff", + sameDayDropOffCmsWidgetName: sameDayDropOffCmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { + buttonLabel: mockCmsContent[sameDayDropOffCmsWidgetName]["HeaderText"], + value: timeSlotId, + }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); + test("Available Timeslots should be formatted correctly - Dropoff - Overnight ", async () => { + //Arrange + const overnightDropOffCmsWidgetName = "Overnight"; + const date = new Date().toISOString().split("T")[0]; + const timeSlotId = "testRouteCodeId" + RouteCodeFlags.OVERNIGHT_DROP_OFF; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + appointmentType: "Dropoff", + overnightDropOffCmsWidgetName: overnightDropOffCmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { + buttonLabel: mockCmsContent[overnightDropOffCmsWidgetName]["HeaderText"], + value: timeSlotId, + }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); + test("Available Timeslots should be formatted correctly - Dropoff", async () => { + //Arrange + const dropoffCmsWidgetName = "Dropoff"; + const date = "2020-01-01"; + const timeSlotId = "testRouteCodeId" + RouteCodeFlags.ALL_DAY_DROP_OFF; + const startTime = "8:00 AM"; + const endTime = "8:30 AM"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + appointmentType: "Dropoff", + dropoffCmsWidgetName: dropoffCmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { + buttonLabel: mockCmsContent[dropoffCmsWidgetName]["HeaderText"], + value: timeSlotId, + }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); + test("Available Timeslots should be formatted correctly - Mobile not premium", async () => { + //Arrange + const mobileCmsWidgetName = "MobileNotPremium"; + const date = "2020-01-01"; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00"; + const endTime = "8:30"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + appointmentType: "Mobile", + mobileCmsWidgetName: mobileCmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { + buttonLabel: startTime + " AM - " + endTime + " AM", + value: timeSlotId, + }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); + test("Available Timeslots should be formatted correctly - Mobile with premium", async () => { + //Arrange + const mobilePremiumCmsWidgetName = "MobilePremium"; + const date = "2020-01-01"; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00"; + const endTime = "8:30"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + premiumAppointmentFee: { + partType: PREMIUM_FEE_PART_TYPE, + }, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + offerPremium: true, + }, + ], + }, + appointmentType: "Mobile", + mobilePremiumCmsWidgetName: mobilePremiumCmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { + additionalButtonData: { + isPremiumAppointment: true, + }, + buttonLabel: mockCmsContent[mobilePremiumCmsWidgetName]["HeaderText"], + buttonLabelSubCopy: "+$15.99", + value: timeSlotId + PREMIUM_TIME_SLOT_ID_FLAG, + }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); + test("Available Timeslots should be formatted correctly - Inshop", async () => { + //Arrange + const cmsWidgetName = "Inshop"; + const date = "2020-01-01"; + const timeSlotId = "testRouteCodeId"; + const startTime = "8:00"; + const endTime = "8:30"; + const jobMaxMinutes = 100; + + const { wrapper } = setupMocks({ + customMountOptions: { + propsData: { + estimatedServiceMinutesMaximum: jobMaxMinutes, + dateAndTimeSlotData: { + date: date, + timeSlots: [ + { + id: timeSlotId, + startTime: startTime, + endTime: endTime, + }, + ], + }, + appointmentType: "Inshop", + cmsWidgetName: cmsWidgetName, + }, + }, + }); + + //Assert + const expectedTimeSlotObject = { buttonLabel: startTime + " AM", value: timeSlotId }; + expect(wrapper.vm.availableTimeSlots[0]).toEqual(expectedTimeSlotObject); + }); +}); + +const mockCmsContent = { + MobileNotPremium: { + BodyText: "Mobile, not premium BodyText", + FooterText: "Mobile, not premium FooterText", + SubheaderText: "Mobile, not premium SubheaderText", + HeaderText: "Mobile, not premium HeaderText", + }, + MobilePremium: { + "BodyText:": "Mobile, with premium BodyText", + FooterText: "Mobile, with premium FooterText", + SubheaderText: "Mobile, with premium SubheaderText", + HeaderText: "Mobile, with premium HeaderText", + }, + Inshop: { + BodyText: "Inshop BodyText", + FooterText: "Inshop FooterText", + SubheaderText: "Inshop SubheaderText", + HeaderText: "Inshop HeaderText", + }, + Dropoff: { + BodyText: "Dropoff BodyText", + FooterText: "Dropoff FooterText", + SubheaderText: "Dropoff SubheaderText", + HeaderText: "Dropoff HeaderText", + }, + Overnight: { + BodyText: "Dropoff Overnight", + FooterText: "Dropoff, Overnight FooterText", + SubheaderText: "Dropoff, Overnight SubheaderText", + HeaderText: "Dropoff, Overnight HeaderText", + }, + Sameday: { + BodyText: "Dropoff Sameday", + FooterText: "Dropoff, Sameday FooterText", + SubheaderText: "Dropoff, Sameday SubheaderText", + HeaderText: "Dropoff, Sameday HeaderText", + }, +}; + +function setupMocks({ customMountOptions }) { + const mountOptions = getMountOptions({ + ...customMountOptions, + }); + mountOptions.global.mocks["$store"] = store; + mountOptions["attachTo"] = document.body; + mountOptions.mixins = [ + { + methods: { + getCmsContent: jest.fn().mockImplementation((widgetName, fieldName) => { + if (mockCmsContent[widgetName] && mockCmsContent[widgetName][fieldName]) + return mockCmsContent[widgetName][fieldName]; + }), + getTotalLineItemPrice: jest.fn().mockImplementation(() => 15.99), + }, + }, + ]; + + const wrapper = shallowMount(timeSlotModalQuestion, mountOptions); + wrapper.vm.setCmsContent = jest.fn(); + return { wrapper }; +} diff --git a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue index 13f33ae05..724facf6c 100644 --- a/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue +++ b/src/layouts/schedule/time-slot-modal-question/time-slot-modal-question.vue @@ -150,7 +150,7 @@ export default { return this.modelValue?.routeCode; }, set: function (newValue) { - // Button Question only supports Number, or String data types so we must get the full object to emit + // Button Question only supports Number, or String data types so we must convert to the full object before emitting this.selectedValue = this.getSelectedTimeSlotObject(newValue); }, }, @@ -326,7 +326,7 @@ export default { } }, modal() { - return this.$refs["timeSlots"]; + return this.$refs[this.modalName]; }, }, methods: {