diff --git a/src/iss-components/vehicle-banner/vehicle-banner.vue b/src/iss-components/vehicle-banner/vehicle-banner.vue index 64a1ffaa..6a17a3b7 100644 --- a/src/iss-components/vehicle-banner/vehicle-banner.vue +++ b/src/iss-components/vehicle-banner/vehicle-banner.vue @@ -24,7 +24,7 @@ export default { } const imageUrl = (this.mainStore.hasSubmittedOrder()) - ? this.mainStore.submittedOrder.vehicle.imageUrl + ? this.mainStore.getSubmittedOrder().vehicle.imageUrl : this.mainStore.order.vehicle.imageUrl; if (!imageUrl || imageUrl === 'NULL') { @@ -54,7 +54,7 @@ export default { }, methods: { getUnmatchedVehicleIcon() { - const category = this.mainStore.submittedOrder?.vehicle.category ?? this.mainStore.order.vehicle.category; + const category = this.mainStore.getSubmittedOrder()?.vehicle.category ?? this.mainStore.order.vehicle.category; switch (category) { case this.vehicleCategories.CAR: return this.carUnmatchedVehicleIcon; diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js index 7efff67b..d45ddf9c 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.spec.js @@ -2,10 +2,11 @@ import calendarOptions from '@/constants/calendar-options'; // Supporting Files -import { shallowMount } from '@vue/test-utils'; +import { shallowMount, mount } from '@vue/test-utils'; import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store'; import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue'; +import { createTestingPinia } from '@pinia/testing'; const appointmentText = 'Appointment content'; function setupMocks({ customMountOptions }) { @@ -24,6 +25,59 @@ function setupMocks({ customMountOptions }) { return { wrapper }; } +const calendarModalQuestionStub = { + render: () => {} +}; + +const mockMixin = { + methods: { + getCmsContent: jest.fn().mockImplementation(() => appointmentText) + } +}; + +function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) { + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn(), + navigateToExternalUrl: jest.fn() + } + }); + + mountOptions.global.stubs = { + // siteFooter: footerStub, + // siteHeader: headerStub, + // vehicleBanner: vehicleBannerStub, + // addToCalendar: addToCalendarStub + calendarModalQuestion: calendarModalQuestionStub + }; + + const testingPinia = createTestingPinia({ + initialState: { + main: mainInitialState + } + }); + useMainStore(testingPinia); + methodToRun(); + + mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); + mountOptions.global.plugins = [testingPinia]; + mountOptions.mixins = [mixin]; + mountOptions.data = () => ( + initialData + ); + + // const apiResponses = { + // supportingItems: [] + // }; + //const apiPromise = Promise.resolve(apiResponses); + // settleAllPromises.mockImplementation(() => apiPromise); + //fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + + const wrapper = shallowMount(addToCalendar, mountOptions); + wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn(); + return { wrapper }; +} + beforeEach(() => { jest.restoreAllMocks(); jest.clearAllMocks(); @@ -76,10 +130,52 @@ afterEach(() => { jest.clearAllMocks(); }); +const sessionStorage = { + schedule: { + date: '2019-01-01', + startTime: '09:00', + endTime: '10:00', + routeCode: '000' + }, + lineItems: { + glassParts: [ + { + partNumber: 'ABC123' + } + ], + supportingItems: [] + }, + serviceLocation: { + address: '', + address2: null, + city: '', + state: 'AZ', + appointmentType: 'Inshop', + zipCode: '12345', + zipCodeCtu: '01234', + provider: { + providerNumber: '123', + address: { + streetAddress: 'test1', + city: 'test', + state: 'AZ', + zipCode: '12345', + zipCodeCtu: '01234' + } + } + }, + damage: { + isRepair: false + }, + referralNumber: '1234567', + payment: { + isInsurance: true + } +}; + describe('Add-to-calendar methods...', () => { test('Add-to-calendar should trigger openModal method', () => { // Arrange - const { wrapper } = setupMocks({ customMountOptions: { propsData: { diff --git a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue index ebd7eb47..7dea78e0 100644 --- a/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue +++ b/src/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue @@ -30,8 +30,6 @@ import { getDateFormat, addMinutes } from '@/helpers/date-helper'; import { AppointmentTypeStrings, RouteCodeFlags } from '@/constants/schedule-constants'; import { getCalendarFile, download } from '@/helpers/add-to-calendar-helper'; - -import { useMainStore } from '@/store'; import serviceType from '@/constants/service-type'; import applicationConfig from '@/constants/application-config.js'; import calendarModalQuestion from '@/layouts/order-confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue'; @@ -53,12 +51,11 @@ export default { appointmentType: String, scheduleDate: String, scheduleStartTime: String, - scheduleEndTime: String - }, - setup() { - const mainStore = useMainStore(); - const { submittedOrder } = mainStore; - return { mainStore, submittedOrder }; + scheduleEndTime: String, + hasRecalibrationPart: Boolean, + uniqueId: String, + isRepair: Boolean, + routeCode: String }, data() { return { @@ -116,23 +113,15 @@ export default { AddToCalendar_SameDayDropOff_Body() { return this.getCmsContent(this.sameDayDropOffWidgetName, 'BodyText'); }, - UniqueId() { - return this.submittedOrder.referralNumber?.toString(); - }, ServiceType() { - const { isRepair } = this.submittedOrder.damage; - const { hasRecalibrationPart } = this.mainStore; - if (!isRepair) { - if (hasRecalibrationPart) { + if (!this.isRepair) { + if (this.hasRecalibrationPart) { return serviceType.REPLACEMENT_AND_RECALIBRATION; } return serviceType.REPLACEMENT; } return serviceType.REPAIR; }, - RouteCode() { - return this.submittedOrder.schedule.routeCode; - }, Appointment() { let subject = ''; let location = ''; @@ -153,10 +142,10 @@ export default { } else { location = this.providerFullAddress?.replace('
', ''); if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { - if (this.RouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + if (this.routeCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { subject = this.AddToCalendar_OvernightDropOff_Subject; body = this.AddToCalendar_OvernightDropOff_Body; - } else if (this.RouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + } else if (this.routeCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.IsSameDayDropOff) { subject = this.AddToCalendar_SameDayDropOff_Subject; endDateTime = addMinutes(startDateTime, 120); @@ -196,7 +185,7 @@ export default { Location: location, StartDate: startDateTime, EndDate: endDateTime, - RefrrlSeqNum: this.UniqueId, + RefrrlSeqNum: this.uniqueId, Body: body, IsHTML: isHTML, Duration: duration @@ -287,10 +276,6 @@ export default { const calBody = getCalendarFile(calFile); download('SafeliteAppointment.ics', calBody); } - // getInShopAppointmentText() { - // const test = this.getCmsContent('AddToCalendar_InShop_TEST', 'Text'); - // return test; - // } } }; diff --git a/src/layouts/order-confirmation/order-confirmation.spec.js b/src/layouts/order-confirmation/order-confirmation.spec.js index 80cead3a..e0f651c6 100644 --- a/src/layouts/order-confirmation/order-confirmation.spec.js +++ b/src/layouts/order-confirmation/order-confirmation.spec.js @@ -5,25 +5,27 @@ import orderConfirmation from '@/layouts/order-confirmation/order-confirmation.v import { getMountOptions } from '@/helpers/unit-test-helper.js'; import { useMainStore } from '@/store/index.js'; import settleAllPromises from '@/helpers/layout-helper.js'; -import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; +import { fetchCmsContentForPage, getStringWithCustomValues, processIfStatements } from '@/helpers/cms-content-helper'; import { mount } from '@vue/test-utils'; import { createTestingPinia } from '@pinia/testing'; import { nextTick } from 'vue'; import coverageStatuses from '@/constants/coverage-statuses'; import coverageType from '@/constants/coverage-type'; +import { deepClone } from '@/helpers/object-helper'; +import { AppointmentTypeStrings } from '@/constants/schedule-constants'; jest.mock('@/helpers/layout-helper.js', () => jest.fn()); jest.mock('@/helpers/cms-content-helper', () => ({ fetchCmsContentForPage: jest.fn(), processIfStatements: jest.fn(), - splitCopyOnCMSPlaceHolder: jest.fn() + splitCopyOnCMSPlaceHolder: jest.fn(), + getStringWithCustomValues: jest.fn() })); -const wordingText = 'wording text {custom:address}'; const mockMixin = { methods: { - getCmsContent: jest.fn().mockImplementation(() => wordingText), + getCmsContent: jest.fn(), setCmsContent: jest.fn() } }; @@ -124,33 +126,17 @@ const sessionStorage = { vaps: [] }, policy: {}, - damage: {} + damage: {}, + vehicle: { + year: 2000, + make: 'Honda', + model: 'Civic' + }, + customer: {}, + customerPortalLoginToken: 'token' }; -const sessionStorageMock = (() => { - let sessionStore = {}; - - return { - getItem(key) { - return sessionStore[key] || null; - }, - setItem(key, value) { - sessionStore[key] = value.toString(); - }, - removeItem(key) { - delete sessionStore[key]; - }, - clear() { - sessionStore = {}; - } - }; -})(); - -Object.defineProperty(window, 'sessionStorage', { - value: sessionStorageMock -}); - -function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}) { +function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}, mixin = mockMixin) { const mountOptions = getMountOptions({ router: { navigate: jest.fn(), @@ -175,7 +161,7 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); mountOptions.global.plugins = [testingPinia]; - mountOptions.mixins = [mockMixin]; + mountOptions.mixins = [mixin]; mountOptions.data = () => ( initialData ); @@ -192,17 +178,16 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu } describe('OrderConfirmation.vue', () => { - beforeEach(() => { - window.sessionStorage.clear(); - }); afterEach(() => { - window.sessionStorage.removeItem('submittedOrder'); - }); + jest.resetAllMocks(); + }) describe('Page pre-requisites', () => { test('If submitted order saved to store, page pre-reqs return true', async () => { // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); // Act const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); @@ -213,11 +198,14 @@ describe('OrderConfirmation.vue', () => { }); }); describe('Rendering', () => { + let wrapper; + beforeEach(() => { + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; + wrapper = getMountedComponent({}, {}, mockStoreActions).wrapper; + }); test('Should render Site Header', () => { - // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); - // Act const siteHeader = wrapper.findComponent(headerStub); @@ -225,10 +213,6 @@ describe('OrderConfirmation.vue', () => { expect(siteHeader.exists()).toBe(true); }); test('Should render Vehicle Banner', () => { - // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); - // Act const vehicleBanner = wrapper.findComponent(vehicleBannerStub); @@ -237,7 +221,9 @@ describe('OrderConfirmation.vue', () => { }); test('If Advanced flow, should display Site Footer', () => { // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; const testStore = { order: { schedule: { @@ -252,7 +238,7 @@ describe('OrderConfirmation.vue', () => { successReturnURL: 'testURL' } }; - const { wrapper } = getMountedComponent(testStore); + wrapper = getMountedComponent(testStore, {}, mockStoreActions).wrapper; // Act const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); @@ -261,10 +247,6 @@ describe('OrderConfirmation.vue', () => { expect(siteFooter.exists()).toBe(true); }); test('If Essential flow, should not display Site Footer', () => { - // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); - // Act const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); @@ -276,6 +258,9 @@ describe('OrderConfirmation.vue', () => { test('If Advanced flow, forward button action navigates to carrier URL', () => { // Arrange window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; const carrierReturnUrl = 'testURL'; const testStore = { order: { @@ -291,7 +276,7 @@ describe('OrderConfirmation.vue', () => { successReturnURL: carrierReturnUrl } }; - const { wrapper } = getMountedComponent(testStore); + const { wrapper } = getMountedComponent(testStore, {}, mockStoreActions); // Act wrapper.vm.forwardButtonAction(); @@ -301,422 +286,665 @@ describe('OrderConfirmation.vue', () => { }); }); describe('Computed properties', () => { - test('appointmentDateFormatted should return date in expected format', () => { - // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); + describe('customValueMap', () =>{ + test.each([ + 'inShopAppointment', + 'dropOffAppointment', + 'vehicleYear', + 'vehicleMake', + 'vehicleModel', + 'address', + 'inShopDuration', + 'email', + 'CUSTOMER_PORTAL_URL', + 'CUSTOMER_PORTAL_LOGIN_TOKEN' + ])('contains key %p', (key) => { + // Arrange + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); - // Act - const testValue = wrapper.vm.appointmentDateFormatted; + // Act + const keyExists = key in wrapper.vm.customValueMap; - // Assert - expect(testValue).toEqual('Friday, March 1'); + // Assert + expect(keyExists).toBeTruthy(); + }); + test('returns expected vehicle info', () => { + // Arrange + var order = deepClone(sessionStorage); + const year = 1998; + const make = 'Toyota'; + const model = 'Cruse'; + order.vehicle = { + year, make, model + }; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); + + // Act + const actualYear = wrapper.vm.customValueMap['vehicleYear']; + const actualMake = wrapper.vm.customValueMap['vehicleMake']; + const actualModel = wrapper.vm.customValueMap['vehicleModel']; + + // Assert + expect(actualYear).toBe(year); + expect(actualMake).toBe(make); + expect(actualModel).toBe(model); + }); + test('returns expected customer email', () => { + // Arrange + var order = deepClone(sessionStorage); + const emailAddress = 'email@google.com'; + order.customer.emailAddress = emailAddress; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); + + // Act + const actualEmail = wrapper.vm.customValueMap['email']; + + // Assert + expect(actualEmail).toBe(emailAddress); + }); + }) + describe('confirmationEmailText', () => { + const greaterId = ">"; + const lessId = "<"; + const mobileWording = "Mobile wording"; + const nonMobileWording = "Non mobile wording"; + const mobileWidget = "MobileWordingWidget"; + const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget" + test.each([ + ['test', 'test'], + [`te${greaterId}st`, 'te>st'], + [`${greaterId}test${greaterId}`, '>test>'], + [`te${greaterId}st ${greaterId}`, 'te>st >'], + [`${lessId} test`, '< test'], + [`t${lessId}e${lessId}st`, 'tt<'] + ])('given %p returned from cms, returns %p', (rawCms, expected) => { + // Arrange + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); + }; + getStringWithCustomValues.mockReturnValue(rawCms); + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); + + // Act + const text = wrapper.vm.confirmationEmailText; + + // Assert + expect(text).toBe(expected); + }); }); - test('appointmentTimeFormatted should return Mobile time in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - appointmentType: 'Mobile' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} + describe('appointmentTimeText', () => { + test.each([ + ['Between 9 AM - 10 AM', '09:00', '10:00'], + ['Between 1 PM - 5 PM', '13:00', '17:00'], + ['Between 8:30 AM - 3 PM', '08:30', '15:00'], + ['Between 1 AM - 2 AM', '01:00', '02:00'], + ['Between 12 AM - 2 AM', '00:00', '02:00'], + ['Between 12 PM - 2 AM', '12:00', '02:00'], + ['Between 11 PM - 12 AM', '23:00', '00:00'] + ])('should return Mobile time in expected format "%p" when start time "%p" and end time "%p"', (expected, startTime, endTime) => { + // Arrange + var order = deepClone(sessionStorage); + order.schedule.startTime = startTime; + order.schedule.endTime = endTime; + order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const testValue = wrapper.vm.appointmentTimeText; + + // Assert + expect(testValue).toEqual(expected); + }); + test.each([ + ['09:00', '10:00'], + ['13:00', '17:00'], + ['08:30', '15:00'], + ['01:00', '02:00'] + ])('should return Drop off time in same format regardless of start/end time', (startTime, endTime) => { + // Arrange + var order = deepClone(sessionStorage); + order.schedule.startTime = startTime; + order.schedule.endTime = endTime; + order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const testValue = wrapper.vm.appointmentTimeText; + + // Assert + expect(testValue).toEqual('Drop off before 9:30 AM'); + }); + test.each([ + ['at 9:00 AM', '09:00', '10:00'], + ['at 1:00 PM', '13:00', '17:00'], + ['at 8:30 AM', '08:30', '15:00'], + ['at 1:00 AM', '01:00', '02:00'], + ['at 12:00 AM', '00:00', '02:00'], + ['at 12:00 PM', '12:00', '02:00'] + ])('should return In Shop time in expected format "%p" when start time "%p"', (expected, startTime, endTime) => { + // Arrange + var order = deepClone(sessionStorage); + order.schedule.startTime = startTime; + order.schedule.endTime = endTime; + order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const testValue = wrapper.vm.appointmentTimeText; + + // Assert + expect(testValue).toEqual(expected); + }); + }); + describe('appointmentLocation', () => { + var order = deepClone(sessionStorage); + order.serviceLocation = { + address: "123 Service Rd.", + address2: "Box 4", + city: "Columbus", + state: "OH", + zipCode: "12345", + provider: { + address: { + streetAddress: "304 provider Ln.", + city: "pittsburg", + state: "PA", + zipCode: "16001" + } + } }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + const expectedServiceLocation = '123 Service Rd., Box 4,
Columbus, OH 12345'; + const expectedShopLocation = '304 Provider Ln.,
Pittsburg, PA 16001'; + test.each([ + AppointmentTypeStrings.MOBILE, + AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP + ])('mobile location %p returns service location', (type) => { + // Arrange + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - // Act - const testValue = wrapper.vm.appointmentTimeFormatted; + // Act + const text = wrapper.vm.appointmentLocation; - // Assert - expect(testValue).toEqual('Between 9 AM - 10 AM'); + // Assert + expect(text).toBe(expectedServiceLocation); + }); + test.each([ + AppointmentTypeStrings.IN_SHOP, + AppointmentTypeStrings.DROP_OFF + ])('%p appointment location returns shop location', (type) => { + // Arrange + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const text = wrapper.vm.appointmentLocation; + + // Assert + expect(text).toBe(expectedShopLocation); + }); + test.each( + ['turtle', undefined, null] + )('unknown appointment type %p returns null', (type) => { + // Arrange + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const text = wrapper.vm.appointmentLocation; + + // Assert + expect(text).toBeNull(); + }); }); - test('appointmentTimeFormatted should return Drop Off time in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - appointmentType: 'Dropoff', + describe('serviceLocationFullAddress', () => { + var order = deepClone(sessionStorage); + beforeEach(() => { + order.serviceLocation = { + address: "123 Service Rd.", + address2: "Box 4", + city: "Columbus", + state: "OH", + zipCode: "12345", provider: { address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' + streetAddress: "304 provider Ln.", + city: "pittsburg", + state: "PA", + zipCode: "16001" } } - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + }; + }); + test('returns expected when all defined', () => { + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "123 Service Rd., Box 4,
Columbus, OH 12345"; - // Act - const testValue = wrapper.vm.appointmentTimeFormatted; + // Act + const text = wrapper.vm.serviceLocationFullAddress; - // Assert - expect(testValue).toEqual('Drop off before 9:30 AM'); + // Assert + expect(text).toBe(expected); + }); + test('returns expected when address null', () => { + order.serviceLocation.address = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = ", Box 4,
Columbus, OH 12345"; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when address2 null', () => { + order.serviceLocation.address2 = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "123 Service Rd.,
Columbus, OH 12345"; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when city null', () => { + order.serviceLocation.city = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "123 Service Rd., Box 4,
, OH 12345"; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when state null', () => { + order.serviceLocation.state = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "123 Service Rd., Box 4,
Columbus, 12345"; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when zipCode null', () => { + order.serviceLocation.zipCode = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "123 Service Rd., Box 4,
Columbus, OH "; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when all null', () => { + order.serviceLocation.address = null; + order.serviceLocation.address2 = null; + order.serviceLocation.city = null; + order.serviceLocation.state = null; + order.serviceLocation.zipCode = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = ",
, "; + + // Act + const text = wrapper.vm.serviceLocationFullAddress; + + // Assert + expect(text).toBe(expected); + }); }); - test('appointmentTimeFormatted should return In Shop time in expected format', () => { - // Arrange - window.sessionStorage.setItem('submittedOrder', JSON.stringify(sessionStorage)); - const { wrapper } = getMountedComponent(initialStore); - - // Act - const testValue = wrapper.vm.appointmentTimeFormatted; - - // Assert - expect(testValue).toEqual('at 9:00 AM'); - }); - test('appointmentWordingText should return Mobile text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - address: '123 Test Way', - address2: '#1', - city: 'Mesa', - state: 'AZ', - zipCode: '12345', - appointmentType: 'Mobile' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); - - // Act - const testValue = wrapper.vm.appointmentWordingText; - - // Assert - expect(testValue).toEqual('wording text 123 Test Way, #1,
Mesa, AZ 12345'); - }); - test('appointmentWordingText should return Drop Off text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { + describe('providerFullAddress', () => { + var order = deepClone(sessionStorage); + beforeEach(() => { + order.serviceLocation = { + address: "123 Service Rd.", + address2: "Box 4", + city: "Columbus", + state: "OH", + zipCode: "12345", provider: { address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' + streetAddress: "304 provider Ln.", + city: "pittsburg", + state: "PA", + zipCode: "16001" } - }, - appointmentType: 'Dropoff' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + } + }; + }); + test('returns expected when all properties defined', () => { + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "304 Provider Ln.,
Pittsburg, PA 16001"; - // Act - const testValue = wrapper.vm.appointmentWordingText; + // Act + const text = wrapper.vm.providerFullAddress; - // Assert - expect(testValue).toEqual('wording text 123 Safelite Street,
Mesa, AZ 12345'); + // Assert + expect(text).toBe(expected); + }); + test('returns expected when streetAddress null', () => { + order.serviceLocation.provider.address.streetAddress = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = ""; + + // Act + const text = wrapper.vm.providerFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when city null', () => { + order.serviceLocation.provider.address.city = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "304 Provider Ln.,
, PA 16001"; + + // Act + const text = wrapper.vm.providerFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when state null', () => { + order.serviceLocation.provider.address.state = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "304 Provider Ln.,
Pittsburg, 16001"; + + // Act + const text = wrapper.vm.providerFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when zipCode null', () => { + order.serviceLocation.provider.address.zipCode = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = "304 Provider Ln.,
Pittsburg, PA "; + + // Act + const text = wrapper.vm.providerFullAddress; + + // Assert + expect(text).toBe(expected); + }); + test('returns expected when all null', () => { + order.serviceLocation.provider.address.streetAddress = null; + order.serviceLocation.provider.address.city = null; + order.serviceLocation.provider.address.state = null; + order.serviceLocation.provider.address.zipCode = null; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + const expected = ""; + + // Act + const text = wrapper.vm.providerFullAddress; + + // Assert + expect(text).toBe(expected); + }); }); - test('appointmentWordingText should return In Shop text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - provider: { - address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' - } - }, - appointmentType: 'Inshop' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + describe('appointmentWordingText', () => { + const mobileWording = "Mobile wording"; + const nonMobileWording = "Non mobile wording"; + const mobileWidget = "MobileWordingWidget"; + const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget" + let mixin; + beforeEach(() => { + processIfStatements.mockImplementation((content) => content); + getStringWithCustomValues.mockImplementation((content, _) => content); + mixin = { + methods: { + getCmsContent: jest.fn().mockImplementation((widget, _) => { + if (widget == mobileWidget){ + return mobileWording; + } + if (widget == dropOffAndInShopWidget){ + return nonMobileWording; + } + return ""; + }), + setCmsContent: jest.fn() + } + }; + }); + test.each([ + [AppointmentTypeStrings.MOBILE, mobileWording], + [AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, mobileWording], + [AppointmentTypeStrings.DROP_OFF, nonMobileWording], + [AppointmentTypeStrings.IN_SHOP, nonMobileWording], + ['unknown', null], + [null, null], + [undefined, null], + ])('appointment type %p returns wording %p', (type, wording) => { + // Arrange + var order = deepClone(sessionStorage); + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + + const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin); - // Act - const testValue = wrapper.vm.appointmentWordingText; + // Act + const testValue = wrapper.vm.appointmentWordingText; - // Assert - expect(testValue).toEqual('wording text 123 Safelite Street,
Mesa, AZ 12345'); + // Assert + expect(testValue).toEqual(wording); + }); }); - test('serviceLocationFullAddress should return text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - address: '123 Test Way', - address2: '#1', - city: 'Mesa', - state: 'AZ', - zipCode: '12345', - appointmentType: 'Mobile' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + describe('appointmentWordingText2', () => { + const mobileWording = "Mobile wording"; + const nonMobileWording = "Non mobile wording"; + const mobileWidget = "MobileWordingWidget"; + const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget" + let mixin; + beforeEach(() => { + processIfStatements.mockImplementation((content) => content); + getStringWithCustomValues.mockImplementation((content, _) => content); + mixin = { + methods: { + getCmsContent: jest.fn().mockImplementation((widget, _) => { + if (widget == mobileWidget){ + return mobileWording; + } + if (widget == dropOffAndInShopWidget){ + return nonMobileWording; + } + return ""; + }), + setCmsContent: jest.fn() + } + }; + }); + test.each([ + [AppointmentTypeStrings.MOBILE, mobileWording], + [AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, mobileWording], + [AppointmentTypeStrings.DROP_OFF, nonMobileWording], + [AppointmentTypeStrings.IN_SHOP, nonMobileWording], + ['unknown', null], + [null, null], + [undefined, null], + ])('appointment type %p returns wording "%p"', (type, wording) => { + // Arrange + var order = deepClone(sessionStorage); + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin); - // Act - const testValue = wrapper.vm.serviceLocationFullAddress; + // Act + const testValue = wrapper.vm.appointmentWordingText2; - // Assert - expect(testValue).toEqual('123 Test Way, #1,
Mesa, AZ 12345'); + // Assert + expect(testValue).toEqual(wording); + }); }); - test('providerFullAddress should return text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - provider: { - address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' - } - }, - appointmentType: 'Inshop' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + describe('isMobileAppointment', () => { + test.each([ + [AppointmentTypeStrings.MOBILE, true], + [AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, true], + [AppointmentTypeStrings.IN_SHOP, false], + [AppointmentTypeStrings.DROP_OFF, false], + ['other', false], + [null, false], + [undefined, false] + ])('appointment type %p returns %p', (type, expected) => { + // Arrange + var order = deepClone(sessionStorage); + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - // Act - const testValue = wrapper.vm.providerFullAddress; + // Act + const testValue = wrapper.vm.isMobileAppointment; - // Assert - expect(testValue).toEqual('123 Safelite Street,
Mesa, AZ 12345'); + // Assert + expect(testValue).toBe(expected); + }); }); - test('appointmentWordingText2 should return Mobile text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - address: '123 Test Way', - address2: '#1', - city: 'Mesa', - state: 'AZ', - zipCode: '12345', - appointmentType: 'Mobile' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + describe('isInShopAppointment', () => { + test.each([ + [AppointmentTypeStrings.MOBILE, false], + [AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, false], + [AppointmentTypeStrings.IN_SHOP, true], + [AppointmentTypeStrings.DROP_OFF, false], + ['other', false], + [null, false], + [undefined, false] + ])('appointment type %p returns %p', (type, expected) => { + // Arrange + var order = deepClone(sessionStorage); + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - // Act - const testValue = wrapper.vm.appointmentWordingText2; + // Act + const testValue = wrapper.vm.isInShopAppointment; - // Assert - expect(testValue).toEqual(wordingText); + // Assert + expect(testValue).toBe(expected); + }); }); - test('appointmentWordingText2 should return Drop Off and text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - provider: { - address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' - } - }, - appointmentType: 'Dropoff' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); + describe('isDropOffAppointment', () => { + test.each([ + [AppointmentTypeStrings.MOBILE, false], + [AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP, false], + [AppointmentTypeStrings.IN_SHOP, false], + [AppointmentTypeStrings.DROP_OFF, true], + ['other', false], + [null, false], + [undefined, false] + ])('appointment type %p returns %p', (type, expected) => { + // Arrange + var order = deepClone(sessionStorage); + order.serviceLocation.appointmentType = type; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); - // Act - const testValue = wrapper.vm.appointmentWordingText2; - const expected = wrapper.vm.getBodyText2FromCms('Test Widget'); + // Act + const testValue = wrapper.vm.isDropOffAppointment; - // Assert - expect(testValue).toEqual(expected); - }); - test('appointmentWordingText2 should return In Shop text in expected format', () => { - // Arrange - const testSessionStorage = { - schedule: { - date: '2019-01-01', - startTime: '09:00', - endTime: '10:00' - }, - serviceLocation: { - provider: { - address: { - streetAddress: '123 Safelite Street', - city: 'Mesa', - state: 'AZ', - zipCode: '12345' - } - }, - appointmentType: 'Inshop' - }, - insuranceCoverage: { - coverageStatus: coverageStatuses.VERIFIED, - coverageType: coverageType.Deductible - }, - payment: { - isPayInAdvance: false - }, - lineItems: { - vaps: [] - }, - policy: {}, - damage: {} - }; - window.sessionStorage.setItem('submittedOrder', JSON.stringify(testSessionStorage)); - const { wrapper } = getMountedComponent(); - - // Act - const testValue = wrapper.vm.appointmentWordingText2; - const expected = wrapper.vm.getBodyText2FromCms('Test Widget'); - - // Assert - expect(testValue).toEqual(expected); + // Assert + expect(testValue).toBe(expected); + }); }); }); + describe('Methods', () => { + describe('formatDate', () => { + test.each([ + ['Wednesday, April 22', '2020-04-22'], + ['Thursday, February 1', '2018-02-01'], + ['Wednesday, December 30', '2026-12-30'] + ])('returns %p given %p', (expected, date) => { + // Arrange + var order = deepClone(sessionStorage); + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); + + // Act + const result = wrapper.vm.formatDate(date); + + // Assert + expect(result).toBe(expected); + }); + }); + }) }); diff --git a/src/layouts/order-confirmation/order-confirmation.vue b/src/layouts/order-confirmation/order-confirmation.vue index de1c896e..e33a5e08 100644 --- a/src/layouts/order-confirmation/order-confirmation.vue +++ b/src/layouts/order-confirmation/order-confirmation.vue @@ -7,7 +7,7 @@
- +
@@ -21,13 +21,13 @@
-

{{ appointmentDateFormatted }}

-

{{ appointmentTimeFormatted }}

+

{{ formatDate(schedule.date) }}

+

{{ appointmentTimeText }}

+ :scheduleDate="schedule.date" + :scheduleStartTime="schedule.startTime" + :scheduleEndTime="schedule.endTime" + :routeCode="schedule.routeCode" + :hasRecalibrationPart="hasRecalibrationPart" + :uniqueId="referralNumber" + :isRepair="isRepair" />
@@ -54,7 +56,7 @@
'); }, orderConfirmationHeaderText() { - return this.getCmsContent('OrderConfirmationContent', 'HeaderText'); + return this.getCmsContent( + this.widgets.orderConfirmation, + widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT); }, orderConfirmationImage() { - return this.getCmsContent('OrderConfirmationContent', 'Image'); - }, - appointmentType() { - return this.submittedOrder.serviceLocation.appointmentType; - }, - appointmentDate() { - return this.submittedOrder.schedule.date; - }, - appointmentStartTime() { - return this.submittedOrder.schedule.startTime; - }, - appointmentEndTime() { - return this.submittedOrder.schedule.endTime; - }, - appointmentDateFormatted() { - // This conversion ensures we don't get get GMT induced date changes - const dateObject = convertDateStringToDate(this.appointmentDate); - // Ex: Tuesday, April 22 - return dateObject.toLocaleDateString('en-us', { - weekday: 'long', - month: 'long', - day: 'numeric' - }); - }, - appointmentTimeFormatted() { - const formattedTime = this.formatAppointmentTime(this.appointmentType); - return formattedTime; + return this.getCmsContent( + this.widgets.orderConfirmation, + widgetFields.CONTENT_GROUP_WIDGET.IMAGE); }, mobileWordingText() { - return this.getCmsContent('MobileWordingWidget', 'BodyText'); + return this.getCmsContentWithCustomValues( + this.widgets.mobile, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT); }, mobileWordingText2() { - return this.getCmsContent('MobileWordingWidget', 'BodyText2'); - }, - dropOffAndInShopWordingText() { return this.getCmsContent( - 'DropOffAndInShopWordingWidget', - 'BodyText' - ); + this.widgets.mobile, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2); }, - dropOffAndInShopWordingText2() { - return this.getBodyText2FromCms('DropOffAndInShopWordingWidget'); + nonMobileWordingText() { + return this.getCmsContentWithCustomValues( + this.widgets.dropOffAndInShop, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT); }, - serviceLocationAddress() { - return this.submittedOrder.serviceLocation.address; + nonMobileWordingText2() { + return this.getCmsContentWithCustomValues( + this.widgets.dropOffAndInShop, + widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2); }, - serviceLocationAddress2() { - return this.submittedOrder.serviceLocation.address2; + appointmentTimeText() { + const { startTime, endTime } = this.schedule; + if (this.isDropOffAppointment){ + return 'Drop off before 9:30 AM'; + } + if (this.isInShopAppointment){ + const formattedStartTime = get12HourTimeFormat(startTime); + return `at ${formattedStartTime}` + } + if (this.isMobileAppointment) { + const mobileStartTime = get12HourTimeMobileFormat(startTime); + const mobileEndTime = get12HourTimeMobileFormat(endTime); + return `Between ${mobileStartTime} - ${mobileEndTime}`; + } + return null; }, - serviceLocationCity() { - return this.submittedOrder.serviceLocation.city; - }, - serviceLocationState() { - return this.submittedOrder.serviceLocation.state; - }, - serviceLocationZipCode() { - return this.submittedOrder.serviceLocation.zipCode; + appointmentLocation() { + if (this.isMobileAppointment){ + return this.serviceLocationFullAddress; + } + if (this.isDropOffAppointment || this.isInShopAppointment){ + return this.providerFullAddress; + } + return null }, serviceLocationFullAddress() { - // eslint-disable-next-line max-len - return `${this.serviceLocationAddress}, ${ - this.serviceLocationAddress2 - ? `${this.serviceLocationAddress2},` - : '' - }
${this.serviceLocationCity}, ${this.serviceLocationState} ${ - this.serviceLocationZipCode - }`; - }, - providerAddress() { - return toTitleCase(this.submittedOrder.serviceLocation.provider.address - .streetAddress); - }, - providerCity() { - return toTitleCase(this.submittedOrder.serviceLocation.provider.address.city); - }, - providerState() { - return this.submittedOrder.serviceLocation.provider.address.state; - }, - providerZipCode() { - return this.submittedOrder.serviceLocation.provider.address.zipCode; + var { address, address2, city, state, zipCode } = this.serviceLocation; + return `${address ?? ''}, ${address2 ? `${address2},` : ''}
${city ?? ''}, ${state ?? ''} ${zipCode ?? ''}`; }, providerFullAddress() { - // eslint-disable-next-line max-len - return this.submittedOrder.serviceLocation?.provider?.address - ? `${this.providerAddress},
${this.providerCity}, ${this.providerState} ${this.providerZipCode}` + var { streetAddress, city, state, zipCode } = this.providerAddress; + return streetAddress + ? `${toTitleCase(streetAddress)},
${toTitleCase(city)}, ${state ?? ''} ${zipCode ?? ''}` : ''; }, appointmentWordingText() { - switch (this.appointmentType) { - case AppointmentTypeStrings.MOBILE: - case AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP: - return this.mobileWordingText?.replaceAll( - '{custom:address}', - this.serviceLocationFullAddress - ); - case AppointmentTypeStrings.DROP_OFF: - return this.dropOffAndInShopWordingText?.replaceAll( - '{custom:address}', - this.providerFullAddress - ); - case AppointmentTypeStrings.IN_SHOP: - return this.dropOffAndInShopWordingText?.replaceAll( - '{custom:address}', - this.providerFullAddress - ); - default: - return null; + if (this.isMobileAppointment){ + return this.mobileWordingText; } + if (this.isInShopAppointment || this.isDropOffAppointment){ + return this.nonMobileWordingText; + } + return null; }, appointmentWordingText2() { - switch (this.appointmentType) { - case AppointmentTypeStrings.MOBILE: - case AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP: - return this.mobileWordingText2; - case AppointmentTypeStrings.DROP_OFF: - return this.dropOffAndInShopWordingText2; - case AppointmentTypeStrings.IN_SHOP: - return this.dropOffAndInShopWordingText2?.replaceAll( - '{custom:inShopDuration}', - this.inShopAppointmentDuration - ); - default: - return null; + if (this.isMobileAppointment){ + return this.mobileWordingText2; } + if (this.isInShopAppointment || this.isDropOffAppointment){ + return this.nonMobileWordingText2; + } + return null; }, - mobileAppointment() { - return ( - this.submittedOrder.serviceLocation.appointmentType - === AppointmentTypeStrings.MOBILE - || this.submittedOrder.serviceLocation.appointmentType - === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP - ); + isMobileAppointment() { + const mobileAppointmentTypes = [ + AppointmentTypeStrings.MOBILE, + AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP + ] + return mobileAppointmentTypes.includes(this.appointmentType); }, - inShopAppointment() { - return ( - this.submittedOrder.serviceLocation.appointmentType - === AppointmentTypeStrings.IN_SHOP - ); + isInShopAppointment() { + return this.appointmentType === AppointmentTypeStrings.IN_SHOP; }, - dropOffAppointment() { - return ( - this.submittedOrder.serviceLocation.appointmentType - === AppointmentTypeStrings.DROP_OFF - ); + isDropOffAppointment() { + return this.appointmentType === AppointmentTypeStrings.DROP_OFF; }, inShopAppointmentDuration() { - const inshopDurationTime = getDisplayTextForDurationLength( - this.submittedOrder.schedule.jobMinMinutes, - this.submittedOrder.schedule.jobMaxMinutes + return getDisplayTextForDurationLength( + this.schedule.jobMinMinutes, + this.schedule.jobMaxMinutes ); - return inshopDurationTime; - }, - isPayInAdvance() { - return this.submittedOrder.payment.isPayInAdvance; - }, - selectedVaps() { - return this.submittedOrder.lineItems.vaps; } }, mounted() { @@ -404,38 +383,24 @@ export default { forwardButtonAction() { this.$router.navigateToExternalUrl(this.carrierUrl); }, - formatAppointmentTime(appointmentType) { - switch (appointmentType) { - case AppointmentTypeStrings.MOBILE: - case AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP: - // eslint-disable-next-line max-len - return `Between ${get12HourTimeMobileFormat(this.appointmentStartTime)} - ${get12HourTimeMobileFormat(this.appointmentEndTime)}`; - case AppointmentTypeStrings.DROP_OFF: - return 'Drop off before 9:30 AM'; - case AppointmentTypeStrings.IN_SHOP: - return `at ${get12HourTimeFormat(this.appointmentStartTime)}`; - default: - return null; - } - }, - processIfStatements, - getBodyText2FromCms(cmsWidgetName) { - const body2Text = this.getCmsContent(cmsWidgetName, 'BodyText2'); - return this.processIfStatements( - body2Text, + getCmsContentWithCustomValues(widgetName, widgetField) { + const rawText = this.getCmsContent(widgetName, widgetField); + const processedIfStatements = processIfStatements( + rawText, 'custom', - this.getCustomValueFromString + (v) => { return this.customValueMap[v] } ); + return getStringWithCustomValues(processedIfStatements, this.customValueMap); }, - getCustomValueFromString(str) { - switch (str) { - case 'inShopAppointment': - return this.inShopAppointment; - case 'dropOffAppointment': - return this.dropOffAppointment; - default: - return null; - } + formatDate(date) { + // This conversion ensures we don't get get GMT induced date changes + const dateObject = convertDateStringToDate(date); + // Ex: Tuesday, April 22 + return dateObject.toLocaleDateString('en-us', { + weekday: 'long', + month: 'long', + day: 'numeric' + }); } } }; diff --git a/src/layouts/payment-method/payment-method.spec.js b/src/layouts/payment-method/payment-method.spec.js index acfaeafe..b255afab 100644 --- a/src/layouts/payment-method/payment-method.spec.js +++ b/src/layouts/payment-method/payment-method.spec.js @@ -22,7 +22,11 @@ jest.mock('@/helpers/order-helper.js', () => ({ function setupMocks({ customMountOptions = {}, queryString }, mainInitialState = {}, customMixin = null) { const mountOptions = getMountOptions({ ...customMountOptions, - route: { query: { issPage: issPageValues.PAYMENT_METHOD, ...queryString }, params: {} } + route: { query: { issPage: issPageValues.PAYMENT_METHOD, ...queryString }, params: {} }, + router: { + navigate: jest.fn(), + navigateToExternalUrl: jest.fn() + } }); const testingPinia = createTestingPinia({ diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 3a1c415b..09a6dad6 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -301,20 +301,18 @@ export default { if (this.paymentMethod === paymentMethods.PAY_AT_TIME_OF_SERVICE) { try { - await submitWorkOrder({ submitType: submitType.SAFELITE }).then(() => { - this.$router.navigate( - this.navigationScenarios.CLICKED_FORWARD, - this.$route - ); - }).catch((submitError) => { - useMainStore().setBailout(bailoutMessage.saveSessionError(submitError.data)); - this.$router.navigate( - this.navigationScenarios.SAVE_SESSION_FAILED, - this.$route, - { issPage: issPageValues.PAYMENT_METHOD } - ); - }); + await submitWorkOrder({ submitType: submitType.SAFELITE }); + this.$router.navigate( + this.navigationScenarios.CLICKED_FORWARD, + this.$route + ); } catch (error) { + useMainStore().setBailout(bailoutMessage.saveSessionError(error.data)); + this.$router.navigate( + this.navigationScenarios.SAVE_SESSION_FAILED, + this.$route, + { issPage: issPageValues.PAYMENT_METHOD } + ); console.error(`error: response from submit work order:${error.message}`); } } else { diff --git a/src/layouts/tpa-confirmation/tpa-confirmation.spec.js b/src/layouts/tpa-confirmation/tpa-confirmation.spec.js index 5cc2eb2a..11f9e60b 100644 --- a/src/layouts/tpa-confirmation/tpa-confirmation.spec.js +++ b/src/layouts/tpa-confirmation/tpa-confirmation.spec.js @@ -8,8 +8,8 @@ import settleAllPromises from '@/helpers/layout-helper.js'; import { fetchCmsContentForPage } from '@/helpers/cms-content-helper'; import { mount } from '@vue/test-utils'; import { createTestingPinia } from '@pinia/testing'; -import bailoutMessage from '@/constants/bailoutMessage'; import coverageStatuses from '@/constants/coverage-statuses'; +import { deepClone } from '@/helpers/object-helper'; jest.mock('@/helpers/layout-helper.js', () => jest.fn()); @@ -54,11 +54,6 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu } }); const store = useMainStore(testingPinia); - store.submittedOrder = { - ...JSON.parse(JSON.stringify(store.order)), - isVerified: store.isVerified, - isUnverified: store.isUnverified - }; store.order = getDefaultState().order; store.hasSubmittedOrder = jest.fn().mockReturnValue(true); methodToRun(); @@ -80,12 +75,33 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu return { wrapper }; } +const defaultOrder = { + serviceLocation: { + provider: { + companyName: "Hershey", + phoneNumber: "726-117-0377" + } + }, + currentDeductible: 479, + isVerified: false, + carrierPhoneNumber: "757-277-0388", + vehicle: { + imageUrl: 'url for image', + category: 'car' + } +} + describe('TPAConfirmation.vue', () => { describe('Rendering', () => { + let wrapper; + let mockStoreActions; + beforeEach(() => { + mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder); + }; + wrapper = getMountedComponent({}, {}, mockStoreActions).wrapper; + }); test('Should render Site Header', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const siteHeader = wrapper.findComponent({ ref: 'siteHeader' }); @@ -93,9 +109,6 @@ describe('TPAConfirmation.vue', () => { expect(siteHeader.exists()).toBe(true); }); test('Should render Vehicle Banner', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const vehicleBanner = wrapper.findComponent({ ref: 'vehicleBanner' }); @@ -103,9 +116,6 @@ describe('TPAConfirmation.vue', () => { expect(vehicleBanner.exists()).toBe(true); }); test('Should render Confirmation Body One', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const bodyOne = wrapper.findComponent({ ref: 'tpaConfirmationBodyOne' }); @@ -113,9 +123,6 @@ describe('TPAConfirmation.vue', () => { expect(bodyOne.exists()).toBe(true); }); test('Should render Confirmation Body Two', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const bodyTwo = wrapper.findComponent({ ref: 'tpaConfirmationBodyTwo' }); @@ -123,9 +130,6 @@ describe('TPAConfirmation.vue', () => { expect(bodyTwo.exists()).toBe(true); }); test('Should render Order Details title', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const orderDetailsTitle = wrapper.findComponent({ ref: 'tpaConfirmationOrderDetailsTitle' }); @@ -133,9 +137,6 @@ describe('TPAConfirmation.vue', () => { expect(orderDetailsTitle.exists()).toBe(true); }); test('Should render Order Details body', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const orderDetailsBody = wrapper.findComponent({ ref: 'tpaConfirmationOrderDetailsBody' }); @@ -143,9 +144,6 @@ describe('TPAConfirmation.vue', () => { expect(orderDetailsBody.exists()).toBe(true); }); test('Should render Deductible Box', () => { - // Arrange - const { wrapper } = getMountedComponent({}); - // Act const deductibleBox = wrapper.findComponent({ ref: 'deductibleBox' }); @@ -160,7 +158,7 @@ describe('TPAConfirmation.vue', () => { successReturnURL: carrierReturnUrl } }; - const { wrapper } = getMountedComponent(initialStore); + wrapper = getMountedComponent(initialStore, {}, mockStoreActions).wrapper; // Act const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); @@ -169,9 +167,6 @@ describe('TPAConfirmation.vue', () => { expect(siteFooter.exists()).toBe(true); }); test('If Essential flow, should not display Site Footer', () => { - // Arrange - const { wrapper } = getMountedComponent(); - // Act const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); @@ -190,7 +185,10 @@ describe('TPAConfirmation.vue', () => { } } }; - const { wrapper } = getMountedComponent(initialStore); + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const expected = 'Verifying coverage'; // Assert @@ -207,7 +205,12 @@ describe('TPAConfirmation.vue', () => { currentDeductible } }; - const { wrapper } = getMountedComponent(initialStore); + const order = deepClone(defaultOrder); + order.isVerified = true; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); + }; + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const notExpected = 'Verifying coverage'; // Assert @@ -216,26 +219,22 @@ describe('TPAConfirmation.vue', () => { }); }); describe('Methods', () => { - describe('getCustomValueFromString', () => { + describe.only('getCustomValueFromString', () => { describe.each([ - [false, coverageStatuses.PENDING, 0], - [false, coverageStatuses.PENDING, 500], - [false, coverageStatuses.NO_COVERAGE, 0], - [false, coverageStatuses.NO_COVERAGE, 500], - [false, coverageStatuses.VERIFIED, 0], - [true, coverageStatuses.VERIFIED, 500] - ])('with argument deductibleAboveZero', (expected, status, deductible) => { + [false, false, 0], + [false, false, 500], + [false, true, 0], + [true, true, 500] + ])('with argument deductibleAboveZero', (expected, isVerified, deductible) => { test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => { // Arrange - const initialStore = { - order: { - insuranceCoverage: { - coverageStatus: status - }, - currentDeductible: deductible - } + const order = deepClone(defaultOrder); + order.isVerified = isVerified; + order.currentDeductible = deductible; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; - const { wrapper } = getMountedComponent(initialStore); + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const argument = 'deductibleAboveZero'; // Act @@ -247,24 +246,20 @@ describe('TPAConfirmation.vue', () => { }); describe('with argument zeroDeductible', () => { describe.each([ - [false, coverageStatuses.PENDING, 0], - [false, coverageStatuses.PENDING, 500], - [false, coverageStatuses.NO_COVERAGE, 0], - [false, coverageStatuses.NO_COVERAGE, 500], - [true, coverageStatuses.VERIFIED, 0], - [false, coverageStatuses.VERIFIED, 500] - ])('with argument zeroDeductible', (expected, status, deductible) => { + [false, false, 0], + [false, false, 500], + [true, true, 0], + [false, true, 500] + ])('with argument zeroDeductible', (expected, isVerified, deductible) => { test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => { // Arrange - const initialStore = { - order: { - insuranceCoverage: { - coverageStatus: status - }, - currentDeductible: deductible - } + const order = deepClone(defaultOrder); + order.isVerified = isVerified; + order.currentDeductible = deductible; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; - const { wrapper } = getMountedComponent(initialStore); + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const argument = 'zeroDeductible'; // Act @@ -277,21 +272,18 @@ describe('TPAConfirmation.vue', () => { }); describe('with argument verifyingCoverage', () => { describe.each([ - [true, coverageStatuses.PENDING], - [true, coverageStatuses.NO_COVERAGE], - [false, coverageStatuses.VERIFIED] - ])('with argument zeroDeductible', (expected, status) => { + [true, false], + [false, true] + ])('with argument zeroDeductible', (expected, isVerified) => { test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)}`, () => { // Arrange - const initialStore = { - order: { - insuranceCoverage: { - coverageStatus: status - }, - currentDeductible: 123 - } + const order = deepClone(defaultOrder); + order.isVerified = isVerified; + order.currentDeductible = 123; + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); }; - const { wrapper } = getMountedComponent(initialStore); + const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const argument = 'verifyingCoverage'; // Act @@ -304,6 +296,9 @@ describe('TPAConfirmation.vue', () => { }); }); describe('Navigation', () => { + const mockStoreActions = () => { + useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => defaultOrder); + }; test('If Advanced flow, forward button action navigates to carrier URL', () => { // Arrange const carrierReturnUrl = 'testURL'; @@ -312,7 +307,7 @@ describe('TPAConfirmation.vue', () => { successReturnURL: carrierReturnUrl } }; - const { wrapper } = getMountedComponent(initialStore); + const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); // Act wrapper.vm.forwardButtonAction(); diff --git a/src/layouts/tpa-confirmation/tpa-confirmation.vue b/src/layouts/tpa-confirmation/tpa-confirmation.vue index 1e817d6b..6c52383c 100644 --- a/src/layouts/tpa-confirmation/tpa-confirmation.vue +++ b/src/layouts/tpa-confirmation/tpa-confirmation.vue @@ -127,7 +127,7 @@ export default { }, setup() { const mainStore = useMainStore(); - const { submittedOrder } = mainStore; + const submittedOrder = mainStore.getSubmittedOrder(); return { mainStore, submittedOrder }; }, computed: { diff --git a/src/router/index.js b/src/router/index.js index 188e64b7..1b8deda3 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -50,7 +50,7 @@ const routes = [ // Intercept all navigation if a submitted order exists in storage if (useMainStore().hasSubmittedOrder()) { if (to.query.issPage !== issPageValues.ENTRY_PAGE) { - return await GoToConfirmationPage(next, useMainStore().submittedOrder); + return await GoToConfirmationPage(next, useMainStore().getSubmittedOrder()); } } diff --git a/src/store/index.js b/src/store/index.js index dabe3fb3..7f26d157 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -423,8 +423,7 @@ export const useMainStore = defineStore({ experimentSettings: (state) => state.applicationUser.experiments .filter((x) => !!x.isActive) .map((x) => x.settings) - .reduce((r, c) => Object.assign(r, c), {}) ?? {}, - submittedOrder: () => JSON.parse(window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER)) + .reduce((r, c) => Object.assign(r, c), {}) ?? {} }, actions: { @@ -2651,6 +2650,10 @@ export const useMainStore = defineStore({ return window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER) !== null; }, + getSubmittedOrder() { + return JSON.parse(window.sessionStorage.getItem(webStorageConstants.SUBMITTED_ORDER)); + }, + createSubmittedOrder(submitType) { if (this.hasSubmittedOrder()) { return;