Merge pull request #970 from Safelite/feature/richardson/INSR-7740

Last Changes for this card
This commit is contained in:
brich1212safe 2025-12-03 15:56:23 -05:00 committed by GitHub
commit 62667545e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 259 additions and 528 deletions

View file

@ -19,60 +19,6 @@ jest.mock('@/helpers/cms-content-helper', () => ({
})); }));
function setupMocks() { function setupMocks() {
// TODO: Use or delete these
const unused1 = () => ({
partsOrQuestions: [
{
parts: null,
partQuestions: [
{
questionSequence: 1,
questionText:
'Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?',
answers: [
{
answerResult: '',
answerText: 'Yes',
nextQuestionSequence: 2
},
{
answerResult: '',
answerText: 'No',
nextQuestionSequence: 3
}
]
}
],
glassLocation: 'Windshield',
glassName: 'Single',
answerKey: 'Windshield-Single',
answerData: null
}
]
});
const unused2 = () => ({
partsQuestionAnswers: [
{
glassLocation: 'Windshield',
glassName: 'Single',
result: 'FW04848',
answeredQuestions: [
{
questionText:
'Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?',
selectedAnswerText: 'Yes',
questionNum: 1
},
{
questionText:
'Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?',
selectedAnswerText: 'Yes',
questionNum: 2
}
]
}
]
});
const mountOptions = getMountOptions({ const mountOptions = getMountOptions({
mixins: [baseMixin, vehicleQuestionsMixin] mixins: [baseMixin, vehicleQuestionsMixin]
}); });

View file

@ -1,18 +1,13 @@
<template> <template>
<div class="container-fluid fade-on-route-transition"> <div class="fade-on-route-transition">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<loadingModal ref="loadingModal" :textSlides="loadingText" />
<siteHeader cmsWidgetName="SiteHeaderWidget" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="questions-page-layout-container iss-heritage-content-container-width">
<vehicleBanner <siteSubHeader
class="mt-2 mb-4" class="mt-4"
cmsWidgetName="VehicleBannerWidget" cmsWidgetName="SiteSubHeaderWidget" />
:displayGenericVehicleImage="false" />
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
<alert <alert
ref="alertFewMoreQuestions" ref="alertFewMoreQuestions"
cmsWidgetName="alertWidget" cmsWidgetName="alertWidget"
@ -48,23 +43,19 @@
<script> <script>
// Components // Components
import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteHeader from '@/iss-components/site-header/site-header.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import alert from '@/ux-components/alert/alert.vue'; import alert from '@/ux-components/alert/alert.vue';
import questionChain from '@/digital-components/question-chain/question-chain.vue'; import questionChain from '@/digital-components/question-chain/question-chain.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue'; import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
export default { export default {
name: 'questions-page', name: 'questions-page',
components: { components: {
siteHeader, siteHeader,
vehicleBanner,
alert, alert,
questionChain, questionChain,
siteSubHeader, siteSubHeader,
siteFooter, siteFooter
loadingModal,
}, },
props: { props: {
isMetaValid: Boolean, isMetaValid: Boolean,
@ -74,7 +65,7 @@ export default {
validationRules: String, validationRules: String,
modelValue: Object, modelValue: Object,
loadingText: Array, loadingText: Array,
index: Number, index: Number
}, },
emits: ['update:modelValue', 'forwardButtonAction', 'back-click'], emits: ['update:modelValue', 'forwardButtonAction', 'back-click'],
computed: { computed: {
@ -84,16 +75,16 @@ export default {
}, },
set(newValue) { set(newValue) {
this.$emit('update:modelValue', newValue); this.$emit('update:modelValue', newValue);
}, }
}, }
}, },
methods: { methods: {
showThisQuestionChain(glass, i) { showThisQuestionChain(glass, i) {
// return false if no questions or if suppressed // return false if no questions or if suppressed
if ( if (
!glass.questions || !glass.questions
glass.questions?.length < 1 || || glass.questions?.length < 1
glass.isSuppressedPart || glass.isSuppressedPart
) { ) {
return false; return false;
} }
@ -106,15 +97,21 @@ export default {
}, },
handleBackButtonAction() { handleBackButtonAction() {
this.$emit('back-click'); this.$emit('back-click');
}, }
showLoadingModal() { }
this.$refs.loadingModal.showModal();
},
},
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.iss-heritage-container-width {
.questions-page-layout-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
}
}
.questions-page { .questions-page {
.question-text { .question-text {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;

View file

@ -1,114 +0,0 @@
import { shallowMount } from '@vue/test-utils';
import vehicleCategories from '@/constants/vehicle-categories.js';
import { useMainStore } from '@/store';
import { createApp } from 'vue';
import { createPinia, mapStores } from 'pinia';
import App from '@/App.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
const cmsData = { VehicleBannerWidget:
{
GenericVehicleImage: 'blurred-image.jpg',
GenericVehicleImageFilePath: 'images/default-source/default-album/blurred-image.jpg',
CarUnmatchedVehicleIcon: 'car-placeholder.jpg',
TruckUnmatchedVehicleIcon: 'truck-placeholder.jpg',
VanUnmatchedVehicleIcon: 'van-placeholder.jpg',
CommercialVanUnmatchedVehicleIcon: 'commercial-placeholder.jpg',
SuvUnmatchedVehicleIcon: 'suv-placeholder.jpg'
} };
const vueApp = createApp(App);
const pinia = createPinia();
vueApp.use(pinia);
const store = useMainStore();
const mockMixin = {
methods: {
getCmsContent(widgetName, fieldName) {
return cmsData[widgetName][fieldName];
}
},
computed: {
...mapStores(useMainStore),
vehicleCategories() {
return vehicleCategories;
}
}
};
describe('vehicleBanner', () => {
test('renders the blurrycar image when displayGenericVehicleImage is true', async () => {
const wrapper = shallowMount(vehicleBanner, {
propsData: {
displayGenericVehicleImage: true,
cmsWidgetName: 'VehicleBannerWidget'
},
mixins: [mockMixin]
});
expect(wrapper.vm.vehicleImageToDisplay).toEqual(wrapper.vm.genericVehicleImage);
expect(wrapper.find('img').attributes('class')).toContain('vehicle-image');
wrapper.unmount();
});
test('renders expected vehicle image', async () => {
store.order.vehicle.imageUrl = 'url_to_vehicle_image';
const wrapper = shallowMount(vehicleBanner, {
propsData: {
displayGenericVehicleImage: false,
cmsWidgetName: 'VehicleBannerWidget'
},
mixins: [mockMixin]
});
expect(wrapper.vm.vehicleImageToDisplay).toEqual('url_to_vehicle_image');
expect(wrapper.find('img').attributes('class')).toContain('vehicle-image');
wrapper.unmount();
});
test('should render default car icon when imageUrl is null and category is default', async () => {
store.order.vehicle.imageUrl = null;
const wrapper = shallowMount(vehicleBanner, {
propsData: {
displayGenericVehicleImage: false,
cmsWidgetName: 'VehicleBannerWidget'
},
mixins: [mockMixin]
});
const iconUrl = wrapper.vm.vehicleImageToDisplay;
expect(iconUrl).toEqual('car-placeholder.jpg');
wrapper.unmount();
});
const params = [['CAR', 'car-placeholder.jpg'],
['TRUCK', 'truck-placeholder.jpg'],
['VAN', 'van-placeholder.jpg'],
['COMMERCIAL VAN', 'commercial-placeholder.jpg'],
['SUV', 'suv-placeholder.jpg'],
['OTHER', 'car-placeholder.jpg']];
test.each(params)('renders correct icon when imageUrl is not populated for %s and %s', async (category, expectedIcon) => {
store.order.vehicle.imageUrl = null;
store.order.vehicle.category = category;
const wrapper = shallowMount(vehicleBanner, {
propsData: {
displayGenericVehicleImage: false,
cmsWidgetName: 'VehicleBannerWidget'
},
mixins: [mockMixin]
});
const vehicleIcon = wrapper.vm.getUnmatchedVehicleIcon();
expect(vehicleIcon).toEqual(expectedIcon);
expect(wrapper.find('img').attributes('class')).toContain('vehicle-image');
wrapper.unmount();
});
});

View file

@ -1,84 +0,0 @@
<template>
<div class="vehicle_banner text-center">
<img
class="vehicle-image img-fluid"
:src="vehicleImageToDisplay"
alt="" />
</div>
</template>
<script>
export default {
name: 'vehicle-banner',
props: {
displayGenericVehicleImage: {
type: Boolean,
required: true
},
cmsWidgetName: String
},
computed: {
vehicleImageToDisplay() {
if (this.displayGenericVehicleImage) {
return this.genericVehicleImage;
}
const imageUrl = (this.mainStore.hasSubmittedOrder())
? this.mainStore.getSubmittedOrder().vehicle.imageUrl
: this.mainStore.order.vehicle.imageUrl;
if (!imageUrl || imageUrl === 'NULL') {
return this.getUnmatchedVehicleIcon();
}
return imageUrl;
},
genericVehicleImage() {
return this.getCmsContent(this.cmsWidgetName, 'GenericVehicleImage');
},
carUnmatchedVehicleIcon() {
return this.getCmsContent(this.cmsWidgetName, 'CarUnmatchedVehicleIcon');
},
truckUnmatchedVehicleIcon() {
return this.getCmsContent(this.cmsWidgetName, 'TruckUnmatchedVehicleIcon');
},
vanUnmatchedVehicleIcon() {
return this.getCmsContent(this.cmsWidgetName, 'VanUnmatchedVehicleIcon');
},
commercialUnmatchedVehicleIcon() {
return this.getCmsContent(this.cmsWidgetName, 'CommercialVanUnmatchedVehicleIcon');
},
suvUnmatchedVehicleIcon() {
return this.getCmsContent(this.cmsWidgetName, 'SuvUnmatchedVehicleIcon');
}
},
methods: {
getUnmatchedVehicleIcon() {
const category = this.mainStore.getSubmittedOrder()?.vehicle.category ?? this.mainStore.order.vehicle.category;
switch (category) {
case this.vehicleCategories.CAR:
return this.carUnmatchedVehicleIcon;
case this.vehicleCategories.SUV:
return this.suvUnmatchedVehicleIcon;
case this.vehicleCategories.TRUCK:
return this.truckUnmatchedVehicleIcon;
case this.vehicleCategories.VAN:
return this.vanUnmatchedVehicleIcon;
case this.vehicleCategories.COMMERCIALVAN:
return this.commercialUnmatchedVehicleIcon;
default:
return this.carUnmatchedVehicleIcon;
}
}
}
};
</script>
<style lang="scss" scoped>
.vehicle-image {
max-width: 290px;
object-fit: cover;
width: 100%;
height: 132px;
}
</style>

View file

@ -1,4 +1,5 @@
<template> <template>
<form>
<div class="page-container-grouped-styles access-denied"> <div class="page-container-grouped-styles access-denied">
<div class="fade-on-route-transition position-relative"> <div class="fade-on-route-transition position-relative">
<div class="container-fluid"> <div class="container-fluid">
@ -10,6 +11,7 @@
</div> </div>
</div> </div>
</div> </div>
</form>
</template> </template>
<script> <script>

View file

@ -13,7 +13,7 @@ import coverageStatuses from '@/constants/coverage-statuses';
import coverageType from '@/constants/coverage-type'; import coverageType from '@/constants/coverage-type';
import { deepClone } from '@/helpers/object-helper'; import { deepClone } from '@/helpers/object-helper';
import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import { AppointmentTypeStrings } from '@/constants/schedule-constants';
import { paymentMethods } from "@/constants/payment-method-constants"; import { paymentMethods } from '@/constants/payment-method-constants';
jest.mock('@/helpers/layout-helper.js', () => jest.fn()); jest.mock('@/helpers/layout-helper.js', () => jest.fn());
@ -42,10 +42,6 @@ const headerStub = {
render: () => {} render: () => {}
}; };
const vehicleBannerStub = {
render: () => {}
};
const addToCalendarStub = { const addToCalendarStub = {
render: () => {} render: () => {}
}; };
@ -148,7 +144,6 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
mountOptions.global.stubs = { mountOptions.global.stubs = {
siteFooter: footerStub, siteFooter: footerStub,
siteHeader: headerStub, siteHeader: headerStub,
vehicleBanner: vehicleBannerStub,
addToCalendar: addToCalendarStub addToCalendar: addToCalendarStub
}; };
@ -181,7 +176,7 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
describe('OrderConfirmation.vue', () => { describe('OrderConfirmation.vue', () => {
afterEach(() => { afterEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
}) });
describe('Page pre-requisites', () => { describe('Page pre-requisites', () => {
test('If submitted order saved to store, page pre-reqs return true', async () => { test('If submitted order saved to store, page pre-reqs return true', async () => {
// Arrange // Arrange
@ -204,7 +199,7 @@ describe('OrderConfirmation.vue', () => {
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => sessionStorage);
}; };
wrapper = getMountedComponent({}, {}, mockStoreActions).wrapper; wrapper = getMountedComponent({}, {}, mockStoreActions).wrapper;
}); });
test('Should render Site Header', () => { test('Should render Site Header', () => {
// Act // Act
@ -213,13 +208,6 @@ describe('OrderConfirmation.vue', () => {
// Assert // Assert
expect(siteHeader.exists()).toBe(true); expect(siteHeader.exists()).toBe(true);
}); });
test('Should render Vehicle Banner', () => {
// Act
const vehicleBanner = wrapper.findComponent(vehicleBannerStub);
// Assert
expect(vehicleBanner.exists()).toBe(true);
});
test('If Advanced flow, should display Site Footer', () => { test('If Advanced flow, should display Site Footer', () => {
// Arrange // Arrange
const mockStoreActions = () => { const mockStoreActions = () => {
@ -287,7 +275,7 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('Computed properties', () => { describe('Computed properties', () => {
describe('customValueMap', () =>{ describe('customValueMap', () => {
test.each([ test.each([
'inShopAppointment', 'inShopAppointment',
'dropOffAppointment', 'dropOffAppointment',
@ -314,7 +302,7 @@ describe('OrderConfirmation.vue', () => {
}); });
test('returns expected vehicle info', () => { test('returns expected vehicle info', () => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
const year = 1998; const year = 1998;
const make = 'Toyota'; const make = 'Toyota';
const model = 'Cruse'; const model = 'Cruse';
@ -327,9 +315,9 @@ describe('OrderConfirmation.vue', () => {
const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions);
// Act // Act
const actualYear = wrapper.vm.customValueMap['vehicleYear']; const actualYear = wrapper.vm.customValueMap.vehicleYear;
const actualMake = wrapper.vm.customValueMap['vehicleMake']; const actualMake = wrapper.vm.customValueMap.vehicleMake;
const actualModel = wrapper.vm.customValueMap['vehicleModel']; const actualModel = wrapper.vm.customValueMap.vehicleModel;
// Assert // Assert
expect(actualYear).toBe(year); expect(actualYear).toBe(year);
@ -338,7 +326,7 @@ describe('OrderConfirmation.vue', () => {
}); });
test('returns expected customer email', () => { test('returns expected customer email', () => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
const emailAddress = 'email@google.com'; const emailAddress = 'email@google.com';
order.customer.emailAddress = emailAddress; order.customer.emailAddress = emailAddress;
const mockStoreActions = () => { const mockStoreActions = () => {
@ -347,19 +335,15 @@ describe('OrderConfirmation.vue', () => {
const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions); const { wrapper } = getMountedComponent(initialStore, {}, mockStoreActions);
// Act // Act
const actualEmail = wrapper.vm.customValueMap['email']; const actualEmail = wrapper.vm.customValueMap.email;
// Assert // Assert
expect(actualEmail).toBe(emailAddress); expect(actualEmail).toBe(emailAddress);
}); });
}) });
describe('confirmationEmailText', () => { describe('confirmationEmailText', () => {
const greaterId = "&gt;"; const greaterId = '&gt;';
const lessId = "&lt;"; const lessId = '&lt;';
const mobileWording = "Mobile wording";
const nonMobileWording = "Non mobile wording";
const mobileWidget = "MobileWordingWidget";
const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget"
test.each([ test.each([
['test', 'test'], ['test', 'test'],
[`te${greaterId}st`, 'te>st'], [`te${greaterId}st`, 'te>st'],
@ -394,7 +378,7 @@ describe('OrderConfirmation.vue', () => {
['Between 11 PM - 12 AM', '23:00', '00: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) => { ])('should return Mobile time in expected format "%p" when start time "%p" and end time "%p"', (expected, startTime, endTime) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.schedule.startTime = startTime; order.schedule.startTime = startTime;
order.schedule.endTime = endTime; order.schedule.endTime = endTime;
order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE; order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;
@ -416,7 +400,7 @@ describe('OrderConfirmation.vue', () => {
['01:00', '02:00'] ['01:00', '02:00']
])('should return Drop off time in same format regardless of start/end time', (startTime, endTime) => { ])('should return Drop off time in same format regardless of start/end time', (startTime, endTime) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.schedule.startTime = startTime; order.schedule.startTime = startTime;
order.schedule.endTime = endTime; order.schedule.endTime = endTime;
order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF; order.serviceLocation.appointmentType = AppointmentTypeStrings.DROP_OFF;
@ -440,7 +424,7 @@ describe('OrderConfirmation.vue', () => {
['at 12:00 PM', '12: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) => { ])('should return In Shop time in expected format "%p" when start time "%p"', (expected, startTime, endTime) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.schedule.startTime = startTime; order.schedule.startTime = startTime;
order.schedule.endTime = endTime; order.schedule.endTime = endTime;
order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP; order.serviceLocation.appointmentType = AppointmentTypeStrings.IN_SHOP;
@ -457,19 +441,19 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('appointmentLocation', () => { describe('appointmentLocation', () => {
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation = { order.serviceLocation = {
address: "123 Service Rd.", address: '123 Service Rd.',
address2: "Box 4", address2: 'Box 4',
city: "Columbus", city: 'Columbus',
state: "OH", state: 'OH',
zipCode: "12345", zipCode: '12345',
provider: { provider: {
address: { address: {
streetAddress: "304 provider Ln.", streetAddress: '304 provider Ln.',
city: "pittsburg", city: 'pittsburg',
state: "PA", state: 'PA',
zipCode: "16001" zipCode: '16001'
} }
} }
}; };
@ -509,9 +493,7 @@ describe('OrderConfirmation.vue', () => {
// Assert // Assert
expect(text).toBe(expectedShopLocation); expect(text).toBe(expectedShopLocation);
}); });
test.each( test.each(['turtle', undefined, null])('unknown appointment type %p returns null', (type) => {
['turtle', undefined, null]
)('unknown appointment type %p returns null', (type) => {
// Arrange // Arrange
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
@ -527,20 +509,20 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('serviceLocationFullAddress', () => { describe('serviceLocationFullAddress', () => {
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
beforeEach(() => { beforeEach(() => {
order.serviceLocation = { order.serviceLocation = {
address: "123 Service Rd.", address: '123 Service Rd.',
address2: "Box 4", address2: 'Box 4',
city: "Columbus", city: 'Columbus',
state: "OH", state: 'OH',
zipCode: "12345", zipCode: '12345',
provider: { provider: {
address: { address: {
streetAddress: "304 provider Ln.", streetAddress: '304 provider Ln.',
city: "pittsburg", city: 'pittsburg',
state: "PA", state: 'PA',
zipCode: "16001" zipCode: '16001'
} }
} }
}; };
@ -550,7 +532,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "123 Service Rd., Box 4,<br/> Columbus, OH 12345"; const expected = '123 Service Rd., Box 4,<br/> Columbus, OH 12345';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -564,7 +546,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = ", Box 4,<br/> Columbus, OH 12345"; const expected = ', Box 4,<br/> Columbus, OH 12345';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -578,7 +560,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "123 Service Rd., <br/> Columbus, OH 12345"; const expected = '123 Service Rd., <br/> Columbus, OH 12345';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -592,7 +574,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "123 Service Rd., Box 4,<br/> , OH 12345"; const expected = '123 Service Rd., Box 4,<br/> , OH 12345';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -606,7 +588,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "123 Service Rd., Box 4,<br/> Columbus, 12345"; const expected = '123 Service Rd., Box 4,<br/> Columbus, 12345';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -620,7 +602,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "123 Service Rd., Box 4,<br/> Columbus, OH "; const expected = '123 Service Rd., Box 4,<br/> Columbus, OH ';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -638,7 +620,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = ", <br/> , "; const expected = ', <br/> , ';
// Act // Act
const text = wrapper.vm.serviceLocationFullAddress; const text = wrapper.vm.serviceLocationFullAddress;
@ -648,20 +630,20 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('providerFullAddress', () => { describe('providerFullAddress', () => {
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
beforeEach(() => { beforeEach(() => {
order.serviceLocation = { order.serviceLocation = {
address: "123 Service Rd.", address: '123 Service Rd.',
address2: "Box 4", address2: 'Box 4',
city: "Columbus", city: 'Columbus',
state: "OH", state: 'OH',
zipCode: "12345", zipCode: '12345',
provider: { provider: {
address: { address: {
streetAddress: "304 provider Ln.", streetAddress: '304 provider Ln.',
city: "pittsburg", city: 'pittsburg',
state: "PA", state: 'PA',
zipCode: "16001" zipCode: '16001'
} }
} }
}; };
@ -671,7 +653,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "304 Provider Ln.,<br/> Pittsburg, PA 16001"; const expected = '304 Provider Ln.,<br/> Pittsburg, PA 16001';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -685,7 +667,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = ""; const expected = '';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -699,7 +681,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "304 Provider Ln.,<br/> , PA 16001"; const expected = '304 Provider Ln.,<br/> , PA 16001';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -713,7 +695,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "304 Provider Ln.,<br/> Pittsburg, 16001"; const expected = '304 Provider Ln.,<br/> Pittsburg, 16001';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -727,7 +709,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = "304 Provider Ln.,<br/> Pittsburg, PA "; const expected = '304 Provider Ln.,<br/> Pittsburg, PA ';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -744,7 +726,7 @@ describe('OrderConfirmation.vue', () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions); const { wrapper } = getMountedComponent({}, {}, mockStoreActions);
const expected = ""; const expected = '';
// Act // Act
const text = wrapper.vm.providerFullAddress; const text = wrapper.vm.providerFullAddress;
@ -754,10 +736,10 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('appointmentWordingText', () => { describe('appointmentWordingText', () => {
const mobileWording = "Mobile wording"; const mobileWording = 'Mobile wording';
const nonMobileWording = "Non mobile wording"; const nonMobileWording = 'Non mobile wording';
const mobileWidget = "MobileWordingWidget"; const mobileWidget = 'MobileWordingWidget';
const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget" const dropOffAndInShopWidget = 'DropOffAndInShopWordingWidget';
let mixin; let mixin;
beforeEach(() => { beforeEach(() => {
processIfStatements.mockImplementation((content) => content); processIfStatements.mockImplementation((content) => content);
@ -765,13 +747,13 @@ describe('OrderConfirmation.vue', () => {
mixin = { mixin = {
methods: { methods: {
getCmsContent: jest.fn().mockImplementation((widget, _) => { getCmsContent: jest.fn().mockImplementation((widget, _) => {
if (widget == mobileWidget){ if (widget === mobileWidget) {
return mobileWording; return mobileWording;
} }
if (widget == dropOffAndInShopWidget){ if (widget === dropOffAndInShopWidget) {
return nonMobileWording; return nonMobileWording;
} }
return ""; return '';
}), }),
setCmsContent: jest.fn() setCmsContent: jest.fn()
} }
@ -784,15 +766,15 @@ describe('OrderConfirmation.vue', () => {
[AppointmentTypeStrings.IN_SHOP, nonMobileWording], [AppointmentTypeStrings.IN_SHOP, nonMobileWording],
['unknown', null], ['unknown', null],
[null, null], [null, null],
[undefined, null], [undefined, null]
])('appointment type %p returns wording %p', (type, wording) => { ])('appointment type %p returns wording %p', (type, wording) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin); const { wrapper } = getMountedComponent({}, {}, mockStoreActions, mixin);
// Act // Act
@ -803,10 +785,10 @@ describe('OrderConfirmation.vue', () => {
}); });
}); });
describe('appointmentWordingText2', () => { describe('appointmentWordingText2', () => {
const mobileWording = "Mobile wording"; const mobileWording = 'Mobile wording';
const nonMobileWording = "Non mobile wording"; const nonMobileWording = 'Non mobile wording';
const mobileWidget = "MobileWordingWidget"; const mobileWidget = 'MobileWordingWidget';
const dropOffAndInShopWidget = "DropOffAndInShopWordingWidget" const dropOffAndInShopWidget = 'DropOffAndInShopWordingWidget';
let mixin; let mixin;
beforeEach(() => { beforeEach(() => {
processIfStatements.mockImplementation((content) => content); processIfStatements.mockImplementation((content) => content);
@ -814,13 +796,13 @@ describe('OrderConfirmation.vue', () => {
mixin = { mixin = {
methods: { methods: {
getCmsContent: jest.fn().mockImplementation((widget, _) => { getCmsContent: jest.fn().mockImplementation((widget, _) => {
if (widget == mobileWidget){ if (widget === mobileWidget) {
return mobileWording; return mobileWording;
} }
if (widget == dropOffAndInShopWidget){ if (widget === dropOffAndInShopWidget) {
return nonMobileWording; return nonMobileWording;
} }
return ""; return '';
}), }),
setCmsContent: jest.fn() setCmsContent: jest.fn()
} }
@ -833,10 +815,10 @@ describe('OrderConfirmation.vue', () => {
[AppointmentTypeStrings.IN_SHOP, nonMobileWording], [AppointmentTypeStrings.IN_SHOP, nonMobileWording],
['unknown', null], ['unknown', null],
[null, null], [null, null],
[undefined, null], [undefined, null]
])('appointment type %p returns wording "%p"', (type, wording) => { ])('appointment type %p returns wording "%p"', (type, wording) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
@ -861,7 +843,7 @@ describe('OrderConfirmation.vue', () => {
[undefined, false] [undefined, false]
])('appointment type %p returns %p', (type, expected) => { ])('appointment type %p returns %p', (type, expected) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
@ -886,7 +868,7 @@ describe('OrderConfirmation.vue', () => {
[undefined, false] [undefined, false]
])('appointment type %p returns %p', (type, expected) => { ])('appointment type %p returns %p', (type, expected) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
@ -911,7 +893,7 @@ describe('OrderConfirmation.vue', () => {
[undefined, false] [undefined, false]
])('appointment type %p returns %p', (type, expected) => { ])('appointment type %p returns %p', (type, expected) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
order.serviceLocation.appointmentType = type; order.serviceLocation.appointmentType = type;
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
@ -957,7 +939,7 @@ describe('OrderConfirmation.vue', () => {
['Wednesday, December 30', '2026-12-30'] ['Wednesday, December 30', '2026-12-30']
])('returns %p given %p', (expected, date) => { ])('returns %p given %p', (expected, date) => {
// Arrange // Arrange
var order = deepClone(sessionStorage); const order = deepClone(sessionStorage);
const mockStoreActions = () => { const mockStoreActions = () => {
useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order); useMainStore().getSubmittedOrder = jest.fn().mockImplementation(() => order);
}; };
@ -970,5 +952,5 @@ describe('OrderConfirmation.vue', () => {
expect(result).toBe(expected); expect(result).toBe(expected);
}); });
}); });
}) });
}); });

View file

@ -4,14 +4,12 @@
v-slot="{ meta }" v-slot="{ meta }"
@submit="onSubmit" @submit="onSubmit"
@invalidSubmit="onInvalidSubmit"> @invalidSubmit="onInvalidSubmit">
<div class="container-fluid fade-on-route-transition"> <div class="fade-on-route-transition">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader :cmsWidgetName="widgets.siteHeader" />
<siteHeader :cmsWidgetName="widgets.siteHeader" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="order-confirmation-container iss-heritage-content-container-width">
<div class="text-center text-color--black pt-5 pb-5 fs-5"> <div class="text-center text-color--black pt-5 pb-5 fs-5">
<img :src="orderConfirmationImage" /> <img :src="orderConfirmationImage" />
<span <span
@ -19,15 +17,11 @@
v-html="orderConfirmationHeaderText"></span> v-html="orderConfirmationHeaderText"></span>
</div> </div>
<div class="appointment-details"> <div class="appointment-details">
<div>
<vehicleBanner
:cmsWidgetName="widgets.vehicleBanner"
:displayGenericVehicleImage="false">
</vehicleBanner>
</div>
<div class="appointment-date-time text-center mt-4"> <div class="appointment-date-time text-center mt-4">
<p>{{ formatDate(schedule.date) }}</p> <p>{{ formatDate(schedule.date) }}</p>
<p class="mt-2">{{ appointmentTimeText }}</p> <p class="mt-2">
{{ appointmentTimeText }}
</p>
</div> </div>
<addToCalendar <addToCalendar
mobileWidgetName="AddToCalendar_Mobile" mobileWidgetName="AddToCalendar_Mobile"
@ -85,7 +79,6 @@
<script> <script>
// Components // Components
import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteHeader from '@/iss-components/site-header/site-header.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue'; import addToCalendar from '@/layouts/order-confirmation/add-to-calendar/add-to-calendar.vue';
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue'; import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
@ -117,7 +110,6 @@ export default {
// eslint-disable-next-line vue/no-reserved-component-names // eslint-disable-next-line vue/no-reserved-component-names
Form, Form,
siteHeader, siteHeader,
vehicleBanner,
siteFooter, siteFooter,
addToCalendar, addToCalendar,
cartDropdown cartDropdown
@ -174,14 +166,13 @@ export default {
referralNumber: referralNumber?.toString(), referralNumber: referralNumber?.toString(),
widgets: { widgets: {
siteHeader: 'SiteHeaderWidget', siteHeader: 'SiteHeaderWidget',
vehicleBanner: 'VehicleBannerWidget',
emailConfirmation: 'EmailConfirmationWordingWidget', emailConfirmation: 'EmailConfirmationWordingWidget',
orderConfirmation: 'OrderConfirmationContent', orderConfirmation: 'OrderConfirmationContent',
mobile: 'MobileWordingWidget', mobile: 'MobileWordingWidget',
dropOffAndInShop: 'DropOffAndInShopWordingWidget', dropOffAndInShop: 'DropOffAndInShopWordingWidget',
siteFooter: 'SiteFooterWidget' siteFooter: 'SiteFooterWidget'
} }
} };
}, },
computed: { computed: {
customValueMap() { customValueMap() {
@ -196,12 +187,13 @@ export default {
email: this.customerEmail, email: this.customerEmail,
CUSTOMER_PORTAL_URL: applicationConfig.CUSTOMER_PORTAL_URL, CUSTOMER_PORTAL_URL: applicationConfig.CUSTOMER_PORTAL_URL,
CUSTOMER_PORTAL_LOGIN_TOKEN: this.customerPortalLoginToken CUSTOMER_PORTAL_LOGIN_TOKEN: this.customerPortalLoginToken
} };
}, },
confirmationEmailText() { confirmationEmailText() {
var content = this.getCmsContentWithCustomValues( const content = this.getCmsContentWithCustomValues(
this.widgets.emailConfirmation, this.widgets.emailConfirmation,
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT); widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
);
return content return content
?.replaceAll('&lt;', '<') ?.replaceAll('&lt;', '<')
?.replaceAll('&gt;', '>'); ?.replaceAll('&gt;', '>');
@ -209,41 +201,47 @@ export default {
orderConfirmationHeaderText() { orderConfirmationHeaderText() {
return this.getCmsContent( return this.getCmsContent(
this.widgets.orderConfirmation, this.widgets.orderConfirmation,
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT); widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
);
}, },
orderConfirmationImage() { orderConfirmationImage() {
return this.getCmsContent( return this.getCmsContent(
this.widgets.orderConfirmation, this.widgets.orderConfirmation,
widgetFields.CONTENT_GROUP_WIDGET.IMAGE); widgetFields.CONTENT_GROUP_WIDGET.IMAGE
);
}, },
mobileWordingText() { mobileWordingText() {
return this.getCmsContentWithCustomValues( return this.getCmsContentWithCustomValues(
this.widgets.mobile, this.widgets.mobile,
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT); widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
);
}, },
mobileWordingText2() { mobileWordingText2() {
return this.getCmsContent( return this.getCmsContent(
this.widgets.mobile, this.widgets.mobile,
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2); widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2
);
}, },
nonMobileWordingText() { nonMobileWordingText() {
return this.getCmsContentWithCustomValues( return this.getCmsContentWithCustomValues(
this.widgets.dropOffAndInShop, this.widgets.dropOffAndInShop,
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT); widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
);
}, },
nonMobileWordingText2() { nonMobileWordingText2() {
return this.getCmsContentWithCustomValues( return this.getCmsContentWithCustomValues(
this.widgets.dropOffAndInShop, this.widgets.dropOffAndInShop,
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2); widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2
);
}, },
appointmentTimeText() { appointmentTimeText() {
const { startTime, endTime } = this.schedule; const { startTime, endTime } = this.schedule;
if (this.isDropOffAppointment){ if (this.isDropOffAppointment) {
return 'Drop off before 9:30 AM'; return 'Drop off before 9:30 AM';
} }
if (this.isInShopAppointment){ if (this.isInShopAppointment) {
const formattedStartTime = get12HourTimeFormat(startTime); const formattedStartTime = get12HourTimeFormat(startTime);
return `at ${formattedStartTime}` return `at ${formattedStartTime}`;
} }
if (this.isMobileAppointment) { if (this.isMobileAppointment) {
const mobileStartTime = get12HourTimeMobileFormat(startTime); const mobileStartTime = get12HourTimeMobileFormat(startTime);
@ -253,38 +251,38 @@ export default {
return null; return null;
}, },
appointmentLocation() { appointmentLocation() {
if (this.isMobileAppointment){ if (this.isMobileAppointment) {
return this.serviceLocationFullAddress; return this.serviceLocationFullAddress;
} }
if (this.isDropOffAppointment || this.isInShopAppointment){ if (this.isDropOffAppointment || this.isInShopAppointment) {
return this.providerFullAddress; return this.providerFullAddress;
} }
return null return null;
}, },
serviceLocationFullAddress() { serviceLocationFullAddress() {
var { address, address2, city, state, zipCode } = this.serviceLocation; const { address, address2, city, state, zipCode } = this.serviceLocation;
return `${address ?? ''}, ${address2 ? `${address2},` : ''}<br/> ${city ?? ''}, ${state ?? ''} ${zipCode ?? ''}`; return `${address ?? ''}, ${address2 ? `${address2},` : ''}<br/> ${city ?? ''}, ${state ?? ''} ${zipCode ?? ''}`;
}, },
providerFullAddress() { providerFullAddress() {
var { streetAddress, city, state, zipCode } = this.providerAddress; const { streetAddress, city, state, zipCode } = this.providerAddress;
return streetAddress return streetAddress
? `${toTitleCase(streetAddress)},<br/> ${toTitleCase(city)}, ${state ?? ''} ${zipCode ?? ''}` ? `${toTitleCase(streetAddress)},<br/> ${toTitleCase(city)}, ${state ?? ''} ${zipCode ?? ''}`
: ''; : '';
}, },
appointmentWordingText() { appointmentWordingText() {
if (this.isMobileAppointment){ if (this.isMobileAppointment) {
return this.mobileWordingText; return this.mobileWordingText;
} }
if (this.isInShopAppointment || this.isDropOffAppointment){ if (this.isInShopAppointment || this.isDropOffAppointment) {
return this.nonMobileWordingText; return this.nonMobileWordingText;
} }
return null; return null;
}, },
appointmentWordingText2() { appointmentWordingText2() {
if (this.isMobileAppointment){ if (this.isMobileAppointment) {
return this.mobileWordingText2; return this.mobileWordingText2;
} }
if (this.isInShopAppointment || this.isDropOffAppointment){ if (this.isInShopAppointment || this.isDropOffAppointment) {
return this.nonMobileWordingText2; return this.nonMobileWordingText2;
} }
return null; return null;
@ -293,7 +291,7 @@ export default {
const mobileAppointmentTypes = [ const mobileAppointmentTypes = [
AppointmentTypeStrings.MOBILE, AppointmentTypeStrings.MOBILE,
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
] ];
return mobileAppointmentTypes.includes(this.appointmentType); return mobileAppointmentTypes.includes(this.appointmentType);
}, },
isInShopAppointment() { isInShopAppointment() {
@ -402,7 +400,7 @@ export default {
const processedIfStatements = processIfStatements( const processedIfStatements = processIfStatements(
rawText, rawText,
'custom', 'custom',
(v) => { return this.customValueMap[v] } (v) => this.customValueMap[v]
); );
return getStringWithCustomValues(processedIfStatements, this.customValueMap); return getStringWithCustomValues(processedIfStatements, this.customValueMap);
}, },
@ -420,6 +418,14 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.iss-heritage-container-width {
.order-confirmation-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
}
}
.page-container-grouped-styles { .page-container-grouped-styles {
overflow: auto; overflow: auto;

View file

@ -4,24 +4,19 @@
v-slot="{ meta }" v-slot="{ meta }"
@submit="onSubmit" @submit="onSubmit"
@invalidSubmit="onInvalidSubmit"> @invalidSubmit="onInvalidSubmit">
<div class="container-fluid fade-on-route-transition"> <div class="fade-on-route-transition">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader
<siteHeader ref="siteHeader"
ref="siteHeader" cmsWidgetName="SiteHeaderWidget" />
cmsWidgetName="SiteHeaderWidget" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="payment-method-container iss-heritage-content-container-width">
<vehicleBanner
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="false" />
<siteSubHeader <siteSubHeader
class="mb-5 mt-4 px-3" class="mb-5 mt-4 px-3"
cmsWidgetName="SiteSubHeaderWidget" cmsWidgetName="SiteSubHeaderWidget"
subTextClasses="text-center" subTextClasses="text-center"
subHeaderClasses="mt-2" /> subHeaderClasses="mt-4" />
<div class="main-content-container"> <div class="main-content-container">
<hr class="my-0" /> <hr class="my-0" />
<reviewDropdown ref="reviewDropdown" /> <reviewDropdown ref="reviewDropdown" />
@ -88,7 +83,6 @@ import { Form } from 'vee-validate';
import issPageValues from '@/router/router-constants/issPage-values'; import issPageValues from '@/router/router-constants/issPage-values';
import bailoutMessage from '@/constants/bailoutMessage'; import bailoutMessage from '@/constants/bailoutMessage';
import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import { AppointmentTypeStrings } from '@/constants/schedule-constants';
import VehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import { saveSession, submitWorkOrder } from '@/helpers/order-helper.js'; import { saveSession, submitWorkOrder } from '@/helpers/order-helper.js';
import { experimentSettings } from '@/constants/experiments'; import { experimentSettings } from '@/constants/experiments';
import submitType from '@/constants/submit-type'; import submitType from '@/constants/submit-type';
@ -106,8 +100,7 @@ export default {
reviewDropdown, reviewDropdown,
cartDropdown, cartDropdown,
paymentMethodQuestion, paymentMethodQuestion,
alert, alert
VehicleBanner
}, },
mixins: [baseFormMixin], mixins: [baseFormMixin],
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
@ -305,10 +298,18 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
$page-side-padding: 1.5rem; $page-side-padding: 1.5rem;
.iss-heritage-container-width {
.payment-method-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
}
}
.main-content-container { .main-content-container {
padding: 0; padding: 0;
} }
.page-container-grouped-styles { .page-container-grouped-styles {
overflow: auto; overflow: auto;

View file

@ -191,7 +191,7 @@ const defaultOrder = {
damage: { damage: {
isRepair: false, isRepair: false,
numberOfChips: null, numberOfChips: null,
glassToReplace: [{location: 'windshield'}] glassToReplace: [{ location: 'windshield' }]
}, },
lineItems: { lineItems: {
glassParts: [parts.windshield], glassParts: [parts.windshield],
@ -380,7 +380,7 @@ describe('payment-page.vue', () => {
// Arrange // Arrange
const { wrapper } = getMountedComponent(defaultOrder); const { wrapper } = getMountedComponent(defaultOrder);
const outerDiv = wrapper.find('.container-fluid'); const outerDiv = wrapper.find('.fade-on-route-transition');
const clickFn = jest.fn(); const clickFn = jest.fn();
outerDiv.element.addEventListener('click', clickFn); outerDiv.element.addEventListener('click', clickFn);
@ -443,7 +443,7 @@ describe('payment-page.vue', () => {
const { wrapper } = getMountedComponent(defaultOrder); const { wrapper } = getMountedComponent(defaultOrder);
useMainStore().order.payment.paymentMethod = paymentMethods.PayNow; useMainStore().order.payment.paymentMethod = paymentMethods.PayNow;
useMainStore().savePaymentMethodChoice = jest.fn().mockImplementation((value) => {useMainStore().order.payment.paymentMethod = value}); useMainStore().savePaymentMethodChoice = jest.fn().mockImplementation((value) => { useMainStore().order.payment.paymentMethod = value; });
// Act // Act
wrapper.vm.handleIFrameContentWindowMessage(event); wrapper.vm.handleIFrameContentWindowMessage(event);

View file

@ -1,13 +1,11 @@
<template> <template>
<Form> <Form>
<div class="container-fluid fade-on-route-transition"> <div class="fade-on-route-transition">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<siteHeader cmsWidgetName="SiteHeaderWidget" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="payment-page-container iss-heritage-content-container-width">
<alert <alert
v-if="displayPayInAdvanceCreditCardAlert" v-if="displayPayInAdvanceCreditCardAlert"
name="payInAdvanceCreditCardErrorAlert" name="payInAdvanceCreditCardErrorAlert"
@ -787,12 +785,19 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.container-fluid { .iss-heritage-container-width {
&.fade-on-route-transition { .payment-page-container {
height: unset; position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
} }
} }
.fade-on-route-transition {
height: unset;
}
.payment p { .payment p {
margin-bottom: 0.75rem; margin-bottom: 0.75rem;
} }

View file

@ -4,16 +4,14 @@
v-slot="{ meta }" v-slot="{ meta }"
@submit="onSubmit" @submit="onSubmit"
@invalidSubmit="onInvalidSubmit"> @invalidSubmit="onInvalidSubmit">
<div class="container-fluid fade-on-route-transition service-packages"> <div class="fade-on-route-transition service-packages">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<siteHeader cmsWidgetName="SiteHeaderWidget" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="service-packages-container iss-heritage-content-container-width">
<siteSubHeader <siteSubHeader
class="mb-2 mt-4" class="mt-4"
subHeaderClasses="mt-5" subHeaderClasses="mt-5"
justification="left" justification="left"
cmsWidgetName="SiteSubHeaderWidget" cmsWidgetName="SiteSubHeaderWidget"
@ -199,6 +197,15 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.iss-heritage-container-width {
.service-packages-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
}
}
.subheader-secondary { .subheader-secondary {
margin-top: 0.5rem; margin-top: 0.5rem;
padding: 0px; padding: 0px;

View file

@ -78,18 +78,18 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
const defaultOrder = { const defaultOrder = {
serviceLocation: { serviceLocation: {
provider: { provider: {
companyName: "Hershey", companyName: 'Hershey',
phoneNumber: "726-117-0377" phoneNumber: '726-117-0377'
} }
}, },
currentDeductible: 479, currentDeductible: 479,
isVerified: false, isVerified: false,
carrierPhoneNumber: "757-277-0388", carrierPhoneNumber: '757-277-0388',
vehicle: { vehicle: {
imageUrl: 'url for image', imageUrl: 'url for image',
category: 'car' category: 'car'
} }
} };
describe('TPAConfirmation.vue', () => { describe('TPAConfirmation.vue', () => {
describe('Rendering', () => { describe('Rendering', () => {
@ -108,13 +108,6 @@ describe('TPAConfirmation.vue', () => {
// Assert // Assert
expect(siteHeader.exists()).toBe(true); expect(siteHeader.exists()).toBe(true);
}); });
test('Should render Vehicle Banner', () => {
// Act
const vehicleBanner = wrapper.findComponent({ ref: 'vehicleBanner' });
// Assert
expect(vehicleBanner.exists()).toBe(true);
});
test('Should render Confirmation Body One', () => { test('Should render Confirmation Body One', () => {
// Act // Act
const bodyOne = wrapper.findComponent({ ref: 'tpaConfirmationBodyOne' }); const bodyOne = wrapper.findComponent({ ref: 'tpaConfirmationBodyOne' });
@ -249,7 +242,7 @@ describe('TPAConfirmation.vue', () => {
[false, false, 0], [false, false, 0],
[false, false, 500], [false, false, 500],
[true, true, 0], [true, true, 0],
[false, true, 500] [false, true, 500]
])('with argument zeroDeductible', (expected, isVerified, deductible) => { ])('with argument zeroDeductible', (expected, isVerified, deductible) => {
test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => { test(`returns ${expected} when coverageStatus is ${getEnumName(coverageStatuses, status)} and currentDeductible is ${deductible}`, () => {
// Arrange // Arrange

View file

@ -4,21 +4,14 @@
v-slot="{ meta }" v-slot="{ meta }"
@submit="onSubmit" @submit="onSubmit"
@invalidSubmit="onInvalidSubmit"> @invalidSubmit="onInvalidSubmit">
<div class="container-fluid fade-on-route-transition"> <div class="fade-on-route-transition">
<div class="row justify-content-center"> <div class="justify-content-center">
<div class="col-md-6 px-0 px-md-2"> <siteHeader
<siteHeader ref="siteHeader"
ref="siteHeader" cmsWidgetName="SiteHeaderWidget" />
cmsWidgetName="SiteHeaderWidget" />
</div>
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="tpa-confirmation-container iss-heritage-content-container-width">
<vehicleBanner
ref="vehicleBanner"
class="mb-4"
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="false" />
<div class="d-flex justify-content-center align-items-center text-color--black pb-2 fs-5"> <div class="d-flex justify-content-center align-items-center text-color--black pb-2 fs-5">
<img :src="tpaConfirmationImage" /> <img :src="tpaConfirmationImage" />
<span <span
@ -69,7 +62,6 @@
<script> <script>
// Components // Components
import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteHeader from '@/iss-components/site-header/site-header.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import textBlock from '@/digital-components/text-block/text-block.vue'; import textBlock from '@/digital-components/text-block/text-block.vue';
import deductibleBox from '@/layouts/tpa-submit/deductible-box/deductible-box.vue'; import deductibleBox from '@/layouts/tpa-submit/deductible-box/deductible-box.vue';
@ -96,7 +88,6 @@ export default {
components: { components: {
siteHeader, siteHeader,
siteFooter, siteFooter,
vehicleBanner,
textBlock, textBlock,
deductibleBox, deductibleBox,
// eslint-disable-next-line vue/no-reserved-component-names // eslint-disable-next-line vue/no-reserved-component-names
@ -219,6 +210,15 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.iss-heritage-container-width {
.tpa-confirmation-container {
position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
}
}
.text-color--black { .text-color--black {
color: $black; color: $black;
} }

View file

@ -20,7 +20,6 @@ Object {
"shop": "PreferredShopSubTitle", "shop": "PreferredShopSubTitle",
"vehicle": "VehicleSubTitle", "vehicle": "VehicleSubTitle",
}, },
"vehicleBanner": "VehicleBannerWidget",
}, },
} }
`; `;

View file

@ -161,7 +161,6 @@ export default {
siteHeader: 'SiteHeaderWidget', siteHeader: 'SiteHeaderWidget',
siteSubHeader: 'SiteSubHeaderWidget', siteSubHeader: 'SiteSubHeaderWidget',
serviceSummary: 'ServiceSummaryContent', serviceSummary: 'ServiceSummaryContent',
vehicleBanner: 'VehicleBannerWidget',
subheader: { subheader: {
vehicle: 'VehicleSubTitle', vehicle: 'VehicleSubTitle',
damage: 'DamageSubTitle', damage: 'DamageSubTitle',

View file

@ -62,10 +62,6 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
const apiResponses = { const apiResponses = {
cmsContent: { cmsContent: {
SiteSubHeaderWidget: pageHeaderWidgetHeaderText, SiteSubHeaderWidget: pageHeaderWidgetHeaderText,
VehicleBannerWidget: {
GenericVehicleImage:
`${applicationConfig.ISS_DEV_CMS_DOMAIN}/images/default-source/default-album/blurred-image.jpg`
},
FunnelHeaderWidget: { FunnelHeaderWidget: {
LogoImage: LogoImage:
`${applicationConfig.ISS_DEV_CMS_DOMAIN}/images/default-source/default-album/logos/insuranceLogo.jpg` `${applicationConfig.ISS_DEV_CMS_DOMAIN}/images/default-source/default-album/logos/insuranceLogo.jpg`

View file

@ -1,47 +1,36 @@
<template> <template>
<Form ref="theForm" @submit="onSubmit" @invalidSubmit="onInvalidSubmit"> <Form
<div class="container-fluid fade-on-route-transition"> ref="theForm"
<div class="row justify-content-center"> @submit="onSubmit"
<div class="col-md-6 px-0 px-md-2"> @invalidSubmit="onInvalidSubmit">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition">
</div> <div class="justify-content-center">
<siteHeader cmsWidgetName="SiteHeaderWidget" />
</div> </div>
<div class="row justify-content-center"> <div class="iss-heritage-container-width">
<div class="col-md-6 col-xl-4"> <div class="vehicle-parts-container iss-heritage-content-container-width">
<vehicleBanner
ref="vehicleBanner"
class="mt-2 mb-4"
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="false" />
<siteSubHeader <siteSubHeader
ref="siteSubHeader" ref="siteSubHeader"
class="mt-4"
cmsWidgetName="SiteSubHeaderWidget" /> cmsWidgetName="SiteSubHeaderWidget" />
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6 col-xl-4">
<alert <alert
id="vehicle-parts-alert" id="vehicle-parts-alert"
class="mt-3 mb-3" class="mt-3 mb-3"
alertClass="alert-warning" alertClass="alert-warning"
cmsWidgetName="AlertWidget" cmsWidgetName="AlertWidget"
:isDismissible="false" /> :isDismissible="false" />
<div v-for="(item, i) in PartsOrQuestions" :key="i"> <div
v-for="(item, i) in PartsOrQuestions"
:key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) --> <!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<hr v-if="i > 0" /> <hr v-if="i > 0" />
<glassPartQuestion <glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`" :ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model=" v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
selectedGlassParts[
item.glassLocation + '-' + item.glassName
]
"
:glassLocation="item.glassLocation" :glassLocation="item.glassLocation"
:glassName="item.glassName" :glassName="item.glassName"
:colorAnswers="item.colorAnswers" :colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData=" :alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
alreadyPopulatedPartsData
" />
</div> </div>
<siteFooter <siteFooter
ref="siteFooter" ref="siteFooter"
@ -60,7 +49,6 @@
// Components // Components
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue'; import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue';
import siteHeader from '@/iss-components/site-header/site-header.vue'; import siteHeader from '@/iss-components/site-header/site-header.vue';
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue'; import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import alert from '@/ux-components/alert/alert.vue'; import alert from '@/ux-components/alert/alert.vue';
@ -81,7 +69,6 @@ export default {
Form, Form,
glassPartQuestion, glassPartQuestion,
siteHeader, siteHeader,
vehicleBanner,
siteSubHeader, siteSubHeader,
siteFooter, siteFooter,
alert alert
@ -239,9 +226,18 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
#vehicle-parts-alert { .iss-heritage-container-width {
.alert-heading { .vehicle-parts-container {
margin-top: 0.25rem !important; position: relative;
min-height: 1px;
padding-left: .9375rem;
padding-right: .9375rem;
#vehicle-parts-alert {
.alert-heading {
margin-top: 0.25rem !important;
}
}
} }
} }
</style> </style>