diff --git a/src/digital-components/phone-number-question/phone-number-question.vue b/src/digital-components/phone-number-question/phone-number-question.vue index f3fdc6cd6..86dfc3f04 100644 --- a/src/digital-components/phone-number-question/phone-number-question.vue +++ b/src/digital-components/phone-number-question/phone-number-question.vue @@ -8,7 +8,7 @@ :mask="mask" :isRequired="isRequired" :validationRules="validationRulesForTextBoxQuestion" - cmsWidgetName="PhoneNumberQuestionWidget" /> + :cmsWidgetName="cmsWidgetName" /> diff --git a/src/layouts/customer-details/customer-details.vue b/src/layouts/customer-details/customer-details.vue index e91317ca9..55e1b01b8 100644 --- a/src/layouts/customer-details/customer-details.vue +++ b/src/layouts/customer-details/customer-details.vue @@ -25,7 +25,7 @@ validationRules="email-address-required|email-address-format" /> diff --git a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js new file mode 100644 index 000000000..a8e0a6f7b --- /dev/null +++ b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.spec.js @@ -0,0 +1,150 @@ +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + +import customerDetailsModalQuestion from "@/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question"; + +const testConstants = { + previousCustomerValues: { + firstName: "First", + lastName: "Last", + emailAddress: "builddigitaltest@safelite.com", + phoneNumber: "111-111-1111", + isSmsOptIn: false, + }, + newValues: { + firstName: "New First", + lastName: "New Last", + emailAddress: "builddigitaltest2@safelite.com", + phoneNumber: "222-222-2222", + isSmsOptIn: true, + }, +}; + +let cmsContent; + +describe("Customer Details Modal", () => { + beforeEach(() => { + cmsContent = {}; + }); + + describe("Submit", () => { + test("Should push to store if a field has changed", async () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + wrapper.vm.onModalOpened(); + + wrapper.vm.firstName = testConstants.newValues.firstName; + + await wrapper.vm.setContactDetails(); + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled(); + expect(wrapper.vm.closeModal).toHaveBeenCalled(); + }); + + test("Should not push to store if no fields have changed", async () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + wrapper.vm.onModalOpened(); + + await wrapper.vm.setContactDetails(); + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.dispatchStoreAction).not.toHaveBeenCalled(); + expect(wrapper.vm.closeModal).toHaveBeenCalled(); + }); + }); + + describe("Default values", () => { + test("Should populate on open", () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + wrapper.vm.onModalOpened(); + + // Assert + expect(wrapper.vm.firstName).toBe(testConstants.previousCustomerValues.firstName); + expect(wrapper.vm.lastName).toBe(testConstants.previousCustomerValues.lastName); + expect(wrapper.vm.emailAddress).toBe(testConstants.previousCustomerValues.emailAddress); + expect(wrapper.vm.phoneNumber).toBe(testConstants.previousCustomerValues.phoneNumber); + expect(wrapper.vm.isSmsOptIn).toBe(testConstants.previousCustomerValues.isSmsOptIn); + }); + + test("Should replace old values on open", async () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + wrapper.vm.firstName = testConstants.newValues.firstName; + wrapper.vm.lastName = testConstants.newValues.lastName; + wrapper.vm.emailAddress = testConstants.newValues.emailAddress; + wrapper.vm.phoneNumber = testConstants.newValues.phoneNumber; + wrapper.vm.isSmsOptIn = testConstants.newValues.isSmsOptIn; + + wrapper.vm.onModalOpened(); + + // Assert + expect(wrapper.vm.firstName).toBe(testConstants.previousCustomerValues.firstName); + expect(wrapper.vm.lastName).toBe(testConstants.previousCustomerValues.lastName); + expect(wrapper.vm.emailAddress).toBe(testConstants.previousCustomerValues.emailAddress); + expect(wrapper.vm.phoneNumber).toBe(testConstants.previousCustomerValues.phoneNumber); + expect(wrapper.vm.isSmsOptIn).toBe(testConstants.previousCustomerValues.isSmsOptIn); + }); + }); +}); + +function generateDefaultProps() { + return { + previousCustomerValues: { + firstName: testConstants.previousCustomerValues.firstName, + lastName: testConstants.previousCustomerValues.lastName, + emailAddress: testConstants.previousCustomerValues.emailAddress, + phoneNumber: testConstants.previousCustomerValues.phoneNumber, + isSmsOptIn: testConstants.previousCustomerValues.isSmsOptIn, + }, + }; +} + +function setupMocks(customMountOptions) { + const mountOptions = getMountOptions(customMountOptions); + + const mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return cmsContent?.[widgetName]?.[cmsFieldName] ?? ""; + }), + }, + }; + + mountOptions.global.mixins = [mockMixin]; + + const wrapper = shallowMount(customerDetailsModalQuestion, mountOptions); + wrapper.vm.setCmsContent = jest.fn(); + wrapper.vm.openModal = jest.fn(); + wrapper.vm.closeModal = jest.fn(); + wrapper.vm.dispatchStoreAction = jest.fn(); + return { wrapper }; +} diff --git a/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue new file mode 100644 index 000000000..0b08abee7 --- /dev/null +++ b/src/layouts/review/review-sections/customer-review/customer-details-modal-question/customer-details-modal-question.vue @@ -0,0 +1,148 @@ + + + diff --git a/src/layouts/review/review-sections/customer-review/customer-review.spec.js b/src/layouts/review/review-sections/customer-review/customer-review.spec.js new file mode 100644 index 000000000..1bcbbe83b --- /dev/null +++ b/src/layouts/review/review-sections/customer-review/customer-review.spec.js @@ -0,0 +1,159 @@ +import { shallowMount } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; + +import customerReview from "@/layouts/review/review-sections/customer-review/customer-review"; + +const testConstants = { + cms: { + header: { + text: "Header", + }, + sms: { + template: "Test {custom:smsOptInJoiner}", + expected: { + ifTrue: "Test in to", + ifFalse: "Test out of", + }, + }, + }, + customer: { + firstName: "First", + lastName: "Last", + phoneNumber: "111-111-1111", + emailAddress: "builddigitaltest@safelite.com", + isSmsOptIn: false, + }, + displayContent: { + fullName: "First Last", + phoneNumber: "111-111-1111", + emailAddress: "builddigitaltest@safelite.com", + smsOptIn: "Test out of", + }, +}; + +let cmsContent; + +describe("Customer Review Block", () => { + beforeEach(() => { + cmsContent = { + CustomerWidget: { + HeaderText: testConstants.cms.header.text, + SubheaderText: testConstants.cms.sms.template, + }, + }; + }); + + test("Should display header text from cms", async () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.header).toEqual(testConstants.cms.header.text); + }); + + describe("SMS Opt In Text", () => { + test("Should render correctly when opt in is true:", async () => { + // Arrange + let props = generateDefaultProps(); + props.customer.isSmsOptIn = true; + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifTrue); + }); + test("Should render correctly when opt in is false:", async () => { + // Arrange + let props = generateDefaultProps(); + props.customer.isSmsOptIn = false; + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifFalse); + }); + test("Should render correctly when opt in is null:", async () => { + // Arrange + let props = generateDefaultProps(); + props.customer.isSmsOptIn = null; + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.smsOptIn).toEqual(testConstants.cms.sms.expected.ifFalse); + }); + }); + + test("Should render correct display content", async () => { + // Arrange + let props = generateDefaultProps(); + + const { wrapper } = setupMocks({ + propsData: props, + }); + + // Act + await wrapper.vm.$nextTick(); + + // Assert + expect(wrapper.vm.displayContent).toEqual([ + testConstants.displayContent.fullName, + testConstants.displayContent.emailAddress, + testConstants.displayContent.phoneNumber, + testConstants.displayContent.smsOptIn, + ]); + }); +}); + +function generateDefaultProps() { + return { + cmsWidgetName: "CustomerWidget", + customer: { + firstName: testConstants.customer.firstName, + lastName: testConstants.customer.lastName, + phoneNumber: testConstants.customer.phoneNumber, + emailAddress: testConstants.customer.emailAddress, + isSmsOptIn: testConstants.customer.isSmsOptIn, + }, + }; +} + +function setupMocks(customMountOptions) { + const mountOptions = getMountOptions(customMountOptions); + + const mockMixin = { + methods: { + getCmsContent: jest.fn((widgetName, cmsFieldName) => { + return cmsContent?.[widgetName]?.[cmsFieldName] ?? ""; + }), + }, + }; + + mountOptions.global.mixins = [mockMixin]; + + const wrapper = shallowMount(customerReview, mountOptions); + wrapper.vm.setCmsContent = jest.fn(); + return { wrapper }; +} diff --git a/src/layouts/review/review-sections/customer-review/customer-review.vue b/src/layouts/review/review-sections/customer-review/customer-review.vue new file mode 100644 index 000000000..d8777d9e4 --- /dev/null +++ b/src/layouts/review/review-sections/customer-review/customer-review.vue @@ -0,0 +1,49 @@ + + + diff --git a/src/layouts/review/review.vue b/src/layouts/review/review.vue index fce6e4f59..fe14e8f7e 100644 --- a/src/layouts/review/review.vue +++ b/src/layouts/review/review.vue @@ -76,12 +76,23 @@ cmsWidgetName="ScheduleWidget" :appointmentType="appointmentType" @edit-clicked="editSchedule" /> + +
+ +

+ + diff --git a/src/router/index.js b/src/router/index.js index 6d812f847..e8fbf4d26 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -31,11 +31,6 @@ import { applicationConfig } from "../constants/application-config"; import review from "@/layouts/review/review"; import paymentMethod from "@/layouts/payment-method/payment-method"; const routes = [ - { - path: "/review", // This is a temporary route for testing. - name: "review", - component: review, - }, { path: "/payment-method", // This is a temporary route for testing. name: "payment-method",