Merge pull request #578 from Safelite/feature/SSR-1131
service duration on order-confirmation page
This commit is contained in:
commit
ecc056c686
4 changed files with 179 additions and 31 deletions
|
|
@ -12,7 +12,8 @@ import { createTestingPinia } from '@pinia/testing';
|
||||||
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
|
||||||
|
|
||||||
jest.mock('@/helpers/cms-content-helper', () => ({
|
jest.mock('@/helpers/cms-content-helper', () => ({
|
||||||
fetchCmsContentForPage: jest.fn()
|
fetchCmsContentForPage: jest.fn(),
|
||||||
|
processIfStatements: jest.fn()
|
||||||
}));
|
}));
|
||||||
const wordingText = 'wording Text {custom:address}';
|
const wordingText = 'wording Text {custom:address}';
|
||||||
|
|
||||||
|
|
@ -34,12 +35,18 @@ const headerStub = {
|
||||||
render: () => {}
|
render: () => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const vehicleBannerStub = {
|
||||||
|
render: () => {}
|
||||||
|
};
|
||||||
|
|
||||||
const initialStore = {
|
const initialStore = {
|
||||||
order: {
|
order: {
|
||||||
schedule: {
|
schedule: {
|
||||||
date: '2024-03-01',
|
date: '2024-03-01',
|
||||||
startTime: '09:00',
|
startTime: '09:00',
|
||||||
endTime: '10:00'
|
endTime: '10:00',
|
||||||
|
jobMinMinutes: 60,
|
||||||
|
jobMaxMinutes: 90
|
||||||
},
|
},
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
address: '123 Test Way',
|
address: '123 Test Way',
|
||||||
|
|
@ -70,7 +77,8 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRu
|
||||||
|
|
||||||
mountOptions.global.stubs = {
|
mountOptions.global.stubs = {
|
||||||
siteFooter: footerStub,
|
siteFooter: footerStub,
|
||||||
siteHeader: headerStub
|
siteHeader: headerStub,
|
||||||
|
vehicleBanner: vehicleBannerStub
|
||||||
};
|
};
|
||||||
|
|
||||||
const testingPinia = createTestingPinia({
|
const testingPinia = createTestingPinia({
|
||||||
|
|
@ -110,6 +118,16 @@ describe('OrderConfirmation.vue', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(siteHeader.exists()).toBe(true);
|
expect(siteHeader.exists()).toBe(true);
|
||||||
});
|
});
|
||||||
|
test('Should render Vehicle Banner', () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = getMountedComponent(initialStore);
|
||||||
|
|
||||||
|
// 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 testStore = {
|
const testStore = {
|
||||||
|
|
@ -215,7 +233,7 @@ describe('OrderConfirmation.vue', () => {
|
||||||
endTime: '10:00'
|
endTime: '10:00'
|
||||||
},
|
},
|
||||||
serviceLocation: {
|
serviceLocation: {
|
||||||
appointmentType: 'Drop Off'
|
appointmentType: 'Dropoff'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -282,7 +300,7 @@ describe('OrderConfirmation.vue', () => {
|
||||||
zipCode: '12345'
|
zipCode: '12345'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
appointmentType: 'Drop Off'
|
appointmentType: 'Dropoff'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -324,5 +342,74 @@ describe('OrderConfirmation.vue', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(testValue).toEqual('<br/>123 Safelite Street,<br/> Mesa, AZ 12345<br/>');
|
expect(testValue).toEqual('<br/>123 Safelite Street,<br/> Mesa, AZ 12345<br/>');
|
||||||
});
|
});
|
||||||
|
test('appointmentWordingText2 should return Mobile text in expected format', () => {
|
||||||
|
// Arrange
|
||||||
|
const testStore = {
|
||||||
|
order: {
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent(testStore);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const testValue = wrapper.vm.appointmentWordingText2;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(testValue).toEqual(wordingText);
|
||||||
|
});
|
||||||
|
test('appointmentWordingText2 should return Drop Off and text in expected format', () => {
|
||||||
|
// Arrange
|
||||||
|
const testStore = {
|
||||||
|
order: {
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const { wrapper } = getMountedComponent(testStore);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const testValue = wrapper.vm.appointmentWordingText2;
|
||||||
|
const expected = wrapper.vm.getBodyText2FromCms('Test Widget');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(testValue).toEqual(expected);
|
||||||
|
});
|
||||||
|
test('appointmentWordingText2 should return In Shop text in expected format', () => {
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = getMountedComponent(initialStore);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const testValue = wrapper.vm.appointmentWordingText2;
|
||||||
|
const expected = wrapper.vm.getBodyText2FromCms('Test Widget');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(testValue).toEqual(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,13 @@
|
||||||
<p>{{ appointmentTimeFormatted }}</p>
|
<p>{{ appointmentTimeFormatted }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="appointment-text text-center text-color--black lh-base"
|
class="appointment-text text-center lh-base"
|
||||||
v-html="appointmentWordingText">
|
v-html="appointmentWordingText">
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="appointment-text text-center lh-base mt-2"
|
||||||
|
v-html="appointmentWordingText2">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<siteFooter
|
<siteFooter
|
||||||
v-if="carrierUrl"
|
v-if="carrierUrl"
|
||||||
|
|
@ -49,13 +53,15 @@ import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.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';
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage, processIfStatements } from '@/helpers/cms-content-helper';
|
||||||
import settleAllPromises from '@/helpers/layout-helper';
|
import settleAllPromises from '@/helpers/layout-helper';
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { get12HourTimeFormat, get12HourTimeMobileFormat, convertDateStringToDate } from '@/helpers/date-helper.js';
|
import { get12HourTimeFormat, get12HourTimeMobileFormat, convertDateStringToDate,
|
||||||
|
getDisplayTextForDurationLength } from '@/helpers/date-helper.js';
|
||||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||||
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'order-confirmation',
|
name: 'order-confirmation',
|
||||||
|
|
@ -100,7 +106,7 @@ export default {
|
||||||
return this.getCmsContent('OrderConfirmationContent', 'Image');
|
return this.getCmsContent('OrderConfirmationContent', 'Image');
|
||||||
},
|
},
|
||||||
appointmentType() {
|
appointmentType() {
|
||||||
return this.mainStore.order.serviceLocation.appointmentType.toUpperCase();
|
return this.mainStore.order.serviceLocation.appointmentType;
|
||||||
},
|
},
|
||||||
appointmentDate() {
|
appointmentDate() {
|
||||||
return this.mainStore.order.schedule.date;
|
return this.mainStore.order.schedule.date;
|
||||||
|
|
@ -128,9 +134,15 @@ export default {
|
||||||
mobileWordingText() {
|
mobileWordingText() {
|
||||||
return this.getCmsContent('MobileWordingWidget', 'BodyText');
|
return this.getCmsContent('MobileWordingWidget', 'BodyText');
|
||||||
},
|
},
|
||||||
|
mobileWordingText2() {
|
||||||
|
return this.getCmsContent('MobileWordingWidget', 'BodyText2');
|
||||||
|
},
|
||||||
dropOffAndInShopWordingText() {
|
dropOffAndInShopWordingText() {
|
||||||
return this.getCmsContent('DropOffAndInShopWordingWidget', 'BodyText');
|
return this.getCmsContent('DropOffAndInShopWordingWidget', 'BodyText');
|
||||||
},
|
},
|
||||||
|
dropOffAndInShopWordingText2() {
|
||||||
|
return this.getBodyText2FromCms('DropOffAndInShopWordingWidget');
|
||||||
|
},
|
||||||
serviceLocationAddress() {
|
serviceLocationAddress() {
|
||||||
return this.mainStore.order.serviceLocation.address;
|
return this.mainStore.order.serviceLocation.address;
|
||||||
},
|
},
|
||||||
|
|
@ -167,7 +179,58 @@ export default {
|
||||||
return `<br/>${this.providerAddress},<br/> ${this.providerCity}, ${this.providerState} ${this.providerZipCode}<br/>`;
|
return `<br/>${this.providerAddress},<br/> ${this.providerCity}, ${this.providerState} ${this.providerZipCode}<br/>`;
|
||||||
},
|
},
|
||||||
appointmentWordingText() {
|
appointmentWordingText() {
|
||||||
return this.formatWordingText(this.appointmentType);
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mobileAppointment() {
|
||||||
|
return this.mainStore.isMobileAppointment;
|
||||||
|
},
|
||||||
|
inShopAppointment() {
|
||||||
|
return this.mainStore.isInShopAppointment;
|
||||||
|
},
|
||||||
|
dropOffAppointment() {
|
||||||
|
return this.mainStore.isDropOffAppointment;
|
||||||
|
},
|
||||||
|
inShopAppointmentDuration() {
|
||||||
|
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||||
|
this.mainStore.order.schedule.jobMinMinutes,
|
||||||
|
this.mainStore.order.schedule.jobMaxMinutes
|
||||||
|
);
|
||||||
|
return inshopDurationTime;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -181,34 +244,29 @@ export default {
|
||||||
},
|
},
|
||||||
formatAppointmentTime(appointmentType) {
|
formatAppointmentTime(appointmentType) {
|
||||||
switch (appointmentType) {
|
switch (appointmentType) {
|
||||||
case 'MOBILE':
|
case AppointmentTypeStrings.MOBILE:
|
||||||
|
case AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP:
|
||||||
// eslint-disable-next-line max-len
|
// eslint-disable-next-line max-len
|
||||||
return `Between ${get12HourTimeMobileFormat(this.appointmentStartTime)} - ${get12HourTimeMobileFormat(this.appointmentEndTime)}`;
|
return `Between ${get12HourTimeMobileFormat(this.appointmentStartTime)} - ${get12HourTimeMobileFormat(this.appointmentEndTime)}`;
|
||||||
case 'DROP OFF':
|
case AppointmentTypeStrings.DROP_OFF:
|
||||||
return 'Drop off before 9:30 AM';
|
return 'Drop off before 9:30 AM';
|
||||||
case 'INSHOP':
|
case AppointmentTypeStrings.IN_SHOP:
|
||||||
return `at ${get12HourTimeFormat(this.appointmentStartTime)}`;
|
return `at ${get12HourTimeFormat(this.appointmentStartTime)}`;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formatWordingText(appointmentType) {
|
processIfStatements,
|
||||||
switch (appointmentType) {
|
getBodyText2FromCms(cmsWidgetName) {
|
||||||
case 'MOBILE':
|
const body2Text = this.getCmsContent(cmsWidgetName, 'BodyText2');
|
||||||
return this.mobileWordingText?.replaceAll(
|
return this.processIfStatements(body2Text, 'custom', this.getCustomValueFromString);
|
||||||
'{custom:address}',
|
},
|
||||||
this.serviceLocationFullAddress
|
getCustomValueFromString(str) {
|
||||||
);
|
switch (str) {
|
||||||
case 'DROP OFF':
|
case 'inShopAppointment':
|
||||||
return this.dropOffAndInShopWordingText?.replaceAll(
|
return this.inShopAppointment;
|
||||||
'{custom:address}',
|
case 'dropOffAppointment':
|
||||||
this.providerFullAddress
|
return this.dropOffAppointment;
|
||||||
);
|
|
||||||
case 'INSHOP':
|
|
||||||
return this.dropOffAndInShopWordingText?.replaceAll(
|
|
||||||
'{custom:address}',
|
|
||||||
this.providerFullAddress
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -254,6 +312,7 @@ $page-side-padding: 1.5rem;
|
||||||
.appointment-text {
|
.appointment-text {
|
||||||
:deep(strong) {
|
:deep(strong) {
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
|
color: $black;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,8 @@ export default {
|
||||||
&& providerLocation.zipCode
|
&& providerLocation.zipCode
|
||||||
);
|
);
|
||||||
|
|
||||||
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||||
const serviceLocationReqs =
|
const serviceLocationReqs =
|
||||||
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,6 +253,7 @@ export const useMainStore = defineStore({
|
||||||
isMobileAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
isMobileAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|
||||||
|| state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP,
|
|| state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP,
|
||||||
isDropOffAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF,
|
isDropOffAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.DROP_OFF,
|
||||||
|
isInShopAppointment: (state) => state.order.serviceLocation.appointmentType === AppointmentTypeStrings.IN_SHOP,
|
||||||
isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired,
|
isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired,
|
||||||
isClaimAlreadyRegistered: (state) => state.order.payment.insuranceCoverage.claimNumber !== null,
|
isClaimAlreadyRegistered: (state) => state.order.payment.insuranceCoverage.claimNumber !== null,
|
||||||
isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null,
|
isBailout: (state) => state.applicationUser.pageData[issPageValues.BAILOUT_PAGE] != null,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue