DigitalConsumer.FixMyGlass/src/fmg-components/save-progress-popup-question/save-progress-popup-question.spec.js
2026-07-27 11:15:23 -04:00

428 lines
16 KiB
JavaScript

import { mount, flushPromises } from "@vue/test-utils";
import saveProgressPopupQuestion from "./save-progress-popup-question";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeActions } from "@/constants/store-actions";
import { saveQuote } from "@/helpers/heritage-integration/order-helper.js";
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: {
closeModal: jest.fn(),
resetButtonStyle: jest.fn(),
},
}));
describe("save-progress-popup-question ", () => {
describe("when closeModal is run ", () => {
test("the modal should close ", () => {
// Arrange
const { wrapper } = setupMocks({
props: {
modalWidgetName: "testModal",
},
});
// Act
wrapper.vm.closeModal();
// Assert
expect(wrapper.vm.modal).not.toBeNull();
});
});
describe("contact method tabs", () => {
test("should default to the email tab", () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
expect(wrapper.vm.isPhoneTabSelected).toBe(false);
});
test("should use tab labels from phone and email specific CMS widgets", () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
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 disclaimer BodyText from the selected tab widget", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
cmsContent: {
SaveProgressPopupWidget_PhoneSpecific: { BodyText: "Phone disclaimer" },
SaveProgressPopupWidget_EmailSpecific: { BodyText: "Email disclaimer" },
},
});
expect(wrapper.vm.modalDisclaimerText).toBe("Email disclaimer");
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.modalDisclaimerText).toBe("Phone disclaimer");
});
test("should use phone question CMS widget on the phone tab", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.phoneQuestionWidgetName).toBe("SaveProgressPopupPhoneQuestionWidget");
});
test("should show email content when the email tab is selected", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
expect(wrapper.vm.contactMethod).toBe("EmailAnswer");
expect(wrapper.vm.isPhoneTabSelected).toBe(false);
expect(wrapper.vm.emailQuestionWidgetName).toBe("SaveProgressPopupEmailQuestionWidget");
});
test("should show phone content when the phone tab is selected", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.contactMethod).toBe("PhoneAnswer");
expect(wrapper.vm.isPhoneTabSelected).toBe(true);
expect(wrapper.vm.userInput).toBe("");
});
test("should reset sms consent when switching tabs", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.smsConsent = { transactional: true, marketing: true };
wrapper.vm.showConsentErrors = true;
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.smsConsent).toEqual({ transactional: false, marketing: false });
expect(wrapper.vm.showConsentErrors).toBe(false);
});
});
describe("validatePhoneAndSave", () => {
test("should show consent errors when phone is valid but no consent is selected", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.selectContactMethod("PhoneAnswer");
wrapper.vm.modal.validate = jest.fn().mockResolvedValue({ valid: true });
const resetSpy = jest.spyOn(wrapper.vm, "resetPhoneSendButtonStyle");
const scrollSpy = jest
.spyOn(wrapper.vm, "scrollConsentIntoView")
.mockResolvedValue(undefined);
await wrapper.vm.validatePhoneAndSave();
expect(wrapper.vm.showConsentErrors).toBe(true);
expect(scrollSpy).toHaveBeenCalled();
expect(resetSpy).toHaveBeenCalled();
});
test("should scroll consent checkboxes into view", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
const mockScrollIntoView = jest.fn();
const consentEl = document.createElement("fieldset");
consentEl.className = "save-progress-popup-sms-consent";
consentEl.scrollIntoView = mockScrollIntoView;
wrapper.element.appendChild(consentEl);
await wrapper.vm.scrollConsentIntoView();
expect(mockScrollIntoView).toHaveBeenCalledWith({
behavior: "smooth",
block: "nearest",
});
});
test("should reset the send button loader when phone validation fails", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.selectContactMethod("PhoneAnswer");
wrapper.vm.modal.validate = jest.fn().mockResolvedValue({ valid: false });
const resetSpy = jest.spyOn(wrapper.vm, "resetPhoneSendButtonStyle");
await wrapper.vm.validatePhoneAndSave();
expect(wrapper.vm.showConsentErrors).toBe(false);
expect(resetSpy).toHaveBeenCalled();
});
test("should save when phone and consent are valid", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
await flushPromises();
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.selectContactMethod("PhoneAnswer");
wrapper.vm.userInput = "555-123-4567";
wrapper.vm.smsConsent = { transactional: true, marketing: false };
wrapper.vm.modal.validate = jest.fn().mockResolvedValue({ valid: true });
const resetSpy = jest.spyOn(wrapper.vm, "resetPhoneSendButtonStyle");
await wrapper.vm.validatePhoneAndSave();
expect(wrapper.vm.showConsentErrors).toBe(false);
expect(wrapper.vm.isProgressSaved).toBe(true);
expect(resetSpy).toHaveBeenCalled();
});
});
describe("footer button suppression", () => {
test("should suppress the modal footer button on the phone tab", async () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.isFooterButtonSuppressed).toBe(true);
});
test("should show the modal footer button on the email tab before save", () => {
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
},
});
expect(wrapper.vm.isFooterButtonSuppressed).toBe(false);
});
test("should suppress the modal footer button after a successful email save", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.userInput = "test@example.com";
await wrapper.vm.saveProgress();
expect(wrapper.vm.isFooterButtonSuppressed).toBe(true);
});
test("should reset the modal footer button loader before suppressing it after save", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.userInput = "test@example.com";
wrapper.vm.modal.resetButtonStyle = jest.fn();
await wrapper.vm.saveProgress();
expect(wrapper.vm.modal.resetButtonStyle).toHaveBeenCalled();
});
});
describe("saveProgress", () => {
test("should save phone number and sms consent when phone tab is selected", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.selectContactMethod("PhoneAnswer");
wrapper.vm.userInput = "555-123-4567";
wrapper.vm.smsConsent = { transactional: true, marketing: false };
await wrapper.vm.saveProgress();
expect(dispatchStoreAction).toHaveBeenCalledWith(
storeActions.SAVE_PHONE_NUMBER,
"5551234567",
false
);
expect(dispatchStoreAction).not.toHaveBeenCalledWith(
storeActions.SAVE_EMAIL,
expect.anything(),
false
);
expect(dispatchStoreAction).toHaveBeenCalledWith(
storeActions.SAVE_IS_SMS_OPT_IN,
true,
false
);
expect(saveQuote).toHaveBeenCalledWith({ pageNameToLog: "quote" });
expect(wrapper.vm.isProgressSaved).toBe(true);
expect(wrapper.vm.savedContactMethod).toBe("PhoneAnswer");
});
test("should save email when email tab is selected", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.userInput = "test@example.com";
await wrapper.vm.saveProgress();
expect(dispatchStoreAction).toHaveBeenCalledWith(
storeActions.SAVE_EMAIL,
"test@example.com",
false
);
expect(dispatchStoreAction).not.toHaveBeenCalledWith(
storeActions.SAVE_PHONE_NUMBER,
expect.anything(),
false
);
expect(saveQuote).toHaveBeenCalledWith({ pageNameToLog: "quote" });
expect(wrapper.vm.savedContactMethod).toBe("EmailAnswer");
});
test("should not allow switching tabs after a successful phone save", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.selectContactMethod("PhoneAnswer");
wrapper.vm.userInput = "555-123-4567";
wrapper.vm.smsConsent = { transactional: true, marketing: false };
await wrapper.vm.saveProgress();
wrapper.vm.selectContactMethod("EmailAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.contactMethod).toBe("PhoneAnswer");
expect(wrapper.vm.isContactMethodTabDisabled("EmailAnswer")).toBe(true);
expect(wrapper.vm.isContactMethodTabDisabled("PhoneAnswer")).toBe(false);
});
test("should not allow switching tabs after a successful email save", async () => {
const dispatchStoreAction = jest.fn().mockResolvedValue(undefined);
const { wrapper } = setupMocks({
props: {
modalWidgetName: "SaveProgressPopupWidget",
pageName: "quote",
},
});
wrapper.vm.dispatchStoreAction = dispatchStoreAction;
wrapper.vm.userInput = "test@example.com";
await wrapper.vm.saveProgress();
wrapper.vm.selectContactMethod("PhoneAnswer");
await wrapper.vm.$nextTick();
expect(wrapper.vm.contactMethod).toBe("EmailAnswer");
expect(wrapper.vm.isContactMethodTabDisabled("PhoneAnswer")).toBe(true);
expect(wrapper.vm.isContactMethodTabDisabled("EmailAnswer")).toBe(false);
});
});
});
function setupMocks({ options, props, cmsContent = {} }) {
const mountOptions = getMountOptions({
...options,
});
const mockBaseMixin = {
methods: {
getCmsContent: jest.fn(
(widgetName, fieldName) => cmsContent[widgetName]?.[fieldName] ?? ""
),
dispatchStoreAction: jest.fn(),
},
};
if (props) mountOptions.propsData = props;
mountOptions.global.mixins = [mockBaseMixin];
const wrapper = mount(saveProgressPopupQuestion, mountOptions);
return { wrapper };
}