import { mount } from "@vue/test-utils"; import saveProgressModalQuestion from "./save-progress-modal-question"; import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { storeActions } from "@/constants/store-actions"; import { saveProgressCmsWidgets } from "@/constants/save-progress-cms-widgets"; import { saveQuote } from "@/helpers/heritage-integration/order-helper.js"; import experimentMixin from "@/mixins/experiment-mixin.js"; import { experimentSettings } from "@/constants/experiments"; jest.mock("@/helpers/heritage-integration/order-helper.js", () => ({ saveQuote: jest.fn().mockResolvedValue(undefined), })); jest.mock("@/helpers/save-progress-sms-consent/save-progress-sms-consent-helper", () => ({ ...jest.requireActual("@/helpers/save-progress-sms-consent/save-progress-sms-consent-helper"), getSaveProgressSmsConsentConfig: jest.fn().mockReturnValue({ copy: { transactional: "Sign me up for updates about my upcoming service.", marketing: "Sign me up for promotional and product offers.", }, value: { transactional: false, marketing: false }, }), })); jest.mock("@/digital-components/modal/modal", () => ({ methods: { openModal: jest.fn(), closeModal: jest.fn(), resetButtonStyle: jest.fn(), resetForm: jest.fn(), validate: jest.fn().mockResolvedValue({ valid: true }), }, })); jest.mock("@/ux-components/alert/alert", () => ({ name: "alert", template: "
", })); describe("save-progress-modal-question", () => { beforeEach(() => { jest.clearAllMocks(); experimentMixin.methods.hasSettingEqualTo = jest.fn().mockReturnValue(false); }); describe("when openModal is run", () => { test("the modal should open", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "testModal", }, }); wrapper.vm.openModal(); expect(wrapper.vm.modal).not.toBeNull(); }); }); describe("legacy email-only mode", () => { test("should save email to the store", async () => { const { wrapper, dispatchStoreAction } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", pageName: "part-questions", }, }); wrapper.vm.userInput = "test@example.com"; await wrapper.vm.saveProgress(); expect(dispatchStoreAction).toHaveBeenCalledWith( storeActions.SAVE_EMAIL, "test@example.com", false ); expect(saveQuote).toHaveBeenCalledWith({ pageNameToLog: "part-questions" }); expect(wrapper.vm.isProgressSaved).toBe(true); }); test("should use the legacy disclaimer widget", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, cmsContent: { SaveProgressModalWidget: { FooterText2: "Legacy disclaimer" }, }, }); expect(wrapper.vm.modalDisclaimerText).toBe("Legacy disclaimer"); }); }); describe("consent management mode", () => { beforeEach(() => { experimentMixin.methods.hasSettingEqualTo = jest .fn() .mockImplementation( (settingName, settingValue) => settingName === experimentSettings.SHOW_CONSENT_MANAGEMENT && settingValue === "true" ); }); test("should default to the phone tab when opened", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, }); wrapper.vm.openModal(); expect(wrapper.vm.isPhoneTabSelected).toBe(true); }); test("should use popup-specific tab labels from CMS widgets", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, cmsContent: { SaveProgressPopupWidget_PhoneSpecific: { HeadlineText: "PHONE" }, SaveProgressPopupWidget_EmailSpecific: { HeadlineText: "EMAIL" }, }, }); expect(wrapper.vm.contactTabs).toEqual([ { label: "PHONE", value: "PhoneAnswer" }, { label: "EMAIL", value: "EmailAnswer" }, ]); }); test("should use the modal question CMS widgets for phone and email inputs", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, }); expect(wrapper.vm.phoneQuestionWidgetName).toBe( saveProgressCmsWidgets.MODAL_PHONE_QUESTION ); expect(wrapper.vm.emailQuestionWidgetName).toBe( saveProgressCmsWidgets.MODAL_EMAIL_QUESTION ); }); test("should use the email-specific popup disclaimer on the email tab", async () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, cmsContent: { SaveProgressPopupWidget_EmailSpecific: { BodyText: "Email disclaimer" }, SaveProgressPopupWidget_PhoneSpecific: { BodyText: "Phone disclaimer" }, }, }); wrapper.vm.selectContactMethod("EmailAnswer"); await wrapper.vm.$nextTick(); expect(wrapper.vm.modalDisclaimerText).toBe("Email disclaimer"); }); test("should use the phone-specific popup disclaimer on the phone tab", () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, cmsContent: { SaveProgressPopupWidget_EmailSpecific: { BodyText: "Email disclaimer" }, SaveProgressPopupWidget_PhoneSpecific: { BodyText: "Phone disclaimer" }, }, }); wrapper.vm.contactMethod = "PhoneAnswer"; expect(wrapper.vm.modalDisclaimerText).toBe("Phone disclaimer"); }); test("should show consent errors when phone is valid but transactional consent is missing", async () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, }); wrapper.vm.contactMethod = "PhoneAnswer"; wrapper.vm.userInput = "5551234567"; wrapper.vm.smsConsent = { transactional: false, marketing: false }; await wrapper.vm.validatePhoneAndSave(); expect(wrapper.vm.showConsentErrors).toBe(true); }); test("should save phone and sms consent when valid", async () => { const { wrapper, dispatchStoreAction } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", pageName: "vehicle-parts", }, }); wrapper.vm.contactMethod = "PhoneAnswer"; wrapper.vm.userInput = "555-123-4567"; wrapper.vm.smsConsent = { transactional: true, marketing: true }; await wrapper.vm.saveProgress(); expect(dispatchStoreAction).toHaveBeenCalledWith( storeActions.SAVE_PHONE_NUMBER, "5551234567", false ); expect(dispatchStoreAction).toHaveBeenCalledWith( storeActions.SAVE_IS_SMS_OPT_IN, true, false ); expect(dispatchStoreAction).toHaveBeenCalledWith( storeActions.SAVE_IS_SMS_MARKETING_OPT_IN, true, false ); expect(saveQuote).toHaveBeenCalledWith({ pageNameToLog: "vehicle-parts" }); }); test("should reset sms consent when switching tabs", async () => { const { wrapper } = setupMocks({ props: { modalWidgetName: "SaveProgressModalWidget", }, }); wrapper.vm.contactMethod = "PhoneAnswer"; wrapper.vm.smsConsent = { transactional: true, marketing: true }; wrapper.vm.selectContactMethod("EmailAnswer"); await wrapper.vm.$nextTick(); expect(wrapper.vm.smsConsent).toEqual({ transactional: false, marketing: false }); }); }); }); function setupMocks({ options, props, cmsContent = {} }) { const mountOptions = getMountOptions({ ...options, }); const dispatchStoreAction = jest.fn().mockResolvedValue(undefined); const mockBaseMixin = { methods: { getCmsContent: jest.fn((widgetName, fieldName) => cmsContent[widgetName]?.[fieldName]), dispatchStoreAction, }, }; if (props) mountOptions.propsData = props; mountOptions.global.mixins = [mockBaseMixin]; const wrapper = mount(saveProgressModalQuestion, mountOptions); return { wrapper, dispatchStoreAction }; }