Linting for first 10 layouts
This commit is contained in:
parent
5fc43ab548
commit
20cb89ed8d
23 changed files with 1268 additions and 1400 deletions
|
|
@ -1,5 +1,5 @@
|
|||
// Components
|
||||
import addressLookup from '@/layouts/address-lookup/address-lookup.vue';
|
||||
import addressLookup from '@/layouts/address-lookup/address-lookup';
|
||||
|
||||
// Supporting Files
|
||||
import { settleAllPromises } from '@/helpers/layout-helper.js';
|
||||
|
|
@ -18,6 +18,79 @@ jest.mock('@/helpers/layout-helper.js', () => ({
|
|||
settleAllPromises: jest.fn()
|
||||
}));
|
||||
|
||||
function setupMocks({
|
||||
lookupVinbyAddressResponse,
|
||||
partsOrQuestions = [],
|
||||
isStatePermissible = true,
|
||||
vinVehicles = [],
|
||||
carId = 'C0000',
|
||||
route = null
|
||||
}) {
|
||||
useMainStore().lookupVinByAddress = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: lookupVinbyAddressResponse || {
|
||||
isStatePermissible: true,
|
||||
vinVehicles: [
|
||||
{
|
||||
vin: 'TEST_VIN',
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}));
|
||||
|
||||
useMainStore().getPartsOrQuestions = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: {
|
||||
partsOrQuestions
|
||||
}
|
||||
}));
|
||||
|
||||
const wrapper = shallowMount(addressLookup,
|
||||
getMountOptions({
|
||||
route: route || undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId,
|
||||
registration: {
|
||||
licensePlate: 'TESTPLATE',
|
||||
zipCode: '12345'
|
||||
}
|
||||
},
|
||||
customer: {
|
||||
emailAddress: 'test@test.com'
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: '11111'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
const apiResponses = {
|
||||
vinLookupResponse: {
|
||||
isStatePermissible,
|
||||
vinVehicles
|
||||
}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('address-lookup.vue', () => {
|
||||
describe('page level alerts', () => {
|
||||
test('if the address matches a different vehicle display the Matched Different VehicleAlert', async () => {
|
||||
|
|
@ -51,9 +124,7 @@ describe('address-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedDifferentVehicle' }).isVisible()).toBe(
|
||||
true
|
||||
);
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedDifferentVehicle' }).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
test('if the address matches two identical YMM vehicles, then display Two Identical YMM Vehicle alert', async () => {
|
||||
|
|
@ -88,9 +159,7 @@ describe('address-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(
|
||||
true
|
||||
);
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
test('if the looking up VIN by address is not allowed in the state selected display the Vin Lookup By HomeAddress Not Allowed Alert', async () => {
|
||||
|
|
@ -135,9 +204,7 @@ describe('address-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(
|
||||
wrapper.findComponent({ ref: 'alertVinLookupsByHomeAddressNotAllowed' }).isVisible()
|
||||
).toBe(true);
|
||||
expect(wrapper.findComponent({ ref: 'alertVinLookupsByHomeAddressNotAllowed' }).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
test('if no vehicles found, display Vin Not Found alert', async () => {
|
||||
|
|
@ -278,13 +345,11 @@ describe('address-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
carsFound
|
||||
);
|
||||
carsFound);
|
||||
});
|
||||
|
||||
test('if a different vehicle is found than the one entered and the selected glass is not available for that vehicle, navigate back to vehicle-damage page', async () => {
|
||||
|
|
@ -310,7 +375,7 @@ describe('address-lookup.vue', () => {
|
|||
|
||||
useMainStore().order.vehicle.carId = 'CARID';
|
||||
|
||||
let carsFound = [
|
||||
const carsFound = [
|
||||
{
|
||||
vin: 'TEST_VIN2',
|
||||
vehicle: {
|
||||
|
|
@ -323,12 +388,10 @@ describe('address-lookup.vue', () => {
|
|||
await wrapper.vm.navigateForward(carsFound);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
undefined,
|
||||
{},
|
||||
{ displayVehicleChangeAlert: true }
|
||||
);
|
||||
{ displayVehicleChangeAlert: true });
|
||||
});
|
||||
|
||||
test('single car was found and matches entered vehicle => navigateForwardWithSingleCarMatch', async () => {
|
||||
|
|
@ -391,84 +454,3 @@ describe('address-lookup.vue', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
lookupVinbyAddressResponse,
|
||||
partsOrQuestions = [],
|
||||
isStatePermissible = true,
|
||||
vinVehicles = [],
|
||||
carId = 'C0000',
|
||||
route = null
|
||||
}) {
|
||||
useMainStore().lookupVinByAddress = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: lookupVinbyAddressResponse
|
||||
? lookupVinbyAddressResponse
|
||||
: {
|
||||
isStatePermissible: true,
|
||||
vinVehicles: [
|
||||
{
|
||||
vin: 'TEST_VIN',
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useMainStore().getPartsOrQuestions = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
partsOrQuestions: partsOrQuestions
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(
|
||||
addressLookup,
|
||||
getMountOptions({
|
||||
route: route ? route : undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId: carId,
|
||||
registration: {
|
||||
licensePlate: 'TESTPLATE',
|
||||
zipCode: '12345'
|
||||
}
|
||||
},
|
||||
customer: {
|
||||
emailAddress: 'test@test.com'
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: '11111'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
);
|
||||
|
||||
const apiResponses = {
|
||||
vinLookupResponse: {
|
||||
isStatePermissible: isStatePermissible,
|
||||
vinVehicles: vinVehicles
|
||||
}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.enableForwardAction = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -9,51 +13,56 @@
|
|||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
ref="vehicleBanner"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" ref="siteSubHeader" class="mb-5" />
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mb-5" />
|
||||
<alert
|
||||
ref="alertVinNotFound"
|
||||
v-if="displayVinNotFoundAlert"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
class="mb-4 mt-4"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4 mt-4"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4 mt-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
class="mt-4"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
ref="alertVinLookupsByHomeAddressNotAllowed"
|
||||
class="mt-4"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<customerQuestions
|
||||
ref="customerQuestions"
|
||||
v-model="customerQuestions" />
|
||||
<siteFooter
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
:isDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
:isForwardActionDisabled="!meta.valid" />
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isDisabled="!meta.valid"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -67,7 +76,7 @@
|
|||
<script>
|
||||
// Components
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
|
|
@ -84,10 +93,21 @@ import { routerParams } from '@/router/router-constants/router-params';
|
|||
import { getDamageString, isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||
|
||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||
import { useMainStore } from '@/store'
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
export default {
|
||||
name: 'address-lookup',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
customerQuestions,
|
||||
textboxQuestion,
|
||||
alert,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -122,6 +142,52 @@ export default {
|
|||
forwardButtonCarStyle: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
AlertMatchedDifferentVehicleHeader() {
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget',
|
||||
'HeadlineText').replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedDifferentVehicleBody() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader() {
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText').replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleBody() {
|
||||
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
|
||||
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() == vinYmmExpected.toLowerCase());
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
customerQuestions: {
|
||||
handler() {
|
||||
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote"
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('siteFooterWidget', 'ForwardButtonText'));
|
||||
this.resetWarningsAndErrors();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return this.mainStore.order.vehicle.carId !== null;
|
||||
|
|
@ -133,12 +199,10 @@ export default {
|
|||
},
|
||||
attachCustomEvents() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.pushEventToGA(this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.GaActions.SUBMITTED,
|
||||
this.GaLabels.ADDRESS_LOOKUP,
|
||||
true
|
||||
);
|
||||
true);
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -175,7 +239,7 @@ export default {
|
|||
const carsFound = resultMap.vinLookupResponse.vinVehicles;
|
||||
|
||||
// Handle cases for different amounts of VINS found for the address.
|
||||
if (carsFound.length == 1) {
|
||||
if (carsFound.length === 1) {
|
||||
// Single VIN found
|
||||
const carFound = carsFound[0].vehicle;
|
||||
|
||||
|
|
@ -186,19 +250,15 @@ export default {
|
|||
this.customAlertData.vehicleInfo = carFound;
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
|
||||
this.forwardButtonCarStyle= carFound.style;
|
||||
this.forwardButtonCarStyle = carFound.style;
|
||||
} else {
|
||||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||
carFound.carId
|
||||
);
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(carFound.carId);
|
||||
|
||||
// Update button "Continue with..."
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`
|
||||
);
|
||||
this.$refs.siteFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`);
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
}
|
||||
|
||||
|
|
@ -206,9 +266,7 @@ export default {
|
|||
vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin });
|
||||
} else if (carsFound.length > 1) {
|
||||
// If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info
|
||||
const matchingCars = carsFound.filter(
|
||||
(vin) => vin.vehicle.carId === this.mainStore.order.vehicle.carId
|
||||
);
|
||||
const matchingCars = carsFound.filter((vin) => vin.vehicle.carId === this.mainStore.order.vehicle.carId);
|
||||
|
||||
if (matchingCars.length === 1) {
|
||||
vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {
|
||||
|
|
@ -223,55 +281,47 @@ export default {
|
|||
}
|
||||
|
||||
// Save vehicle, customer, service and registration information
|
||||
await useMainStore().saveRegistrationAddressLookup(
|
||||
{
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo:
|
||||
await useMainStore().saveRegistrationAddressLookup({
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo:
|
||||
Object.keys(vehicleInfoToCommit).length === 0
|
||||
? null
|
||||
: vehicleInfoToCommit,
|
||||
registrationInfo: {
|
||||
firstName: this.customerQuestions.firstName,
|
||||
lastName: this.customerQuestions.lastName,
|
||||
address: this.customerQuestions.addressQuestions.streetAddress,
|
||||
city: this.customerQuestions.addressQuestions.city,
|
||||
state: this.customerQuestions.addressQuestions.state,
|
||||
zipCode: this.customerQuestions.addressQuestions.zipCode
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
registrationInfo: {
|
||||
firstName: this.customerQuestions.firstName,
|
||||
lastName: this.customerQuestions.lastName,
|
||||
address: this.customerQuestions.addressQuestions.streetAddress,
|
||||
city: this.customerQuestions.addressQuestions.city,
|
||||
state: this.customerQuestions.addressQuestions.state,
|
||||
zipCode: this.customerQuestions.addressQuestions.zipCode
|
||||
}
|
||||
},
|
||||
false);
|
||||
|
||||
return await this.navigateForward(carsFound);
|
||||
return this.navigateForward(carsFound);
|
||||
},
|
||||
async navigateForward(carsFound) {
|
||||
// Match vehicles found to vehicles in state.
|
||||
const matchingCars = carsFound.filter(
|
||||
(car) => car.vehicle.carId === useMainStore().order.vehicle.carId
|
||||
);
|
||||
const matchingCars = carsFound.filter((car) => car.vehicle.carId === useMainStore().order.vehicle.carId);
|
||||
|
||||
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage"
|
||||
// display vehicle changed alert on that page.
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
!this.isSelectedGlassAvailableForVehicle
|
||||
this.isCarIdDifferent
|
||||
&& !this.isSelectedGlassAvailableForVehicle
|
||||
) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true });
|
||||
} else if (matchingCars.length === 1) {
|
||||
await this.navigateForwardWithSingleCarMatch();
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{},
|
||||
carsFound
|
||||
);
|
||||
carsFound);
|
||||
}
|
||||
},
|
||||
resetWarningsAndErrors() {
|
||||
|
|
@ -280,68 +330,6 @@ export default {
|
|||
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
},
|
||||
computed: {
|
||||
AlertMatchedDifferentVehicleHeader() {
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedDifferentVehicleWidget',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedDifferentVehicleBody() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader() {
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleBody() {
|
||||
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
|
||||
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
customerQuestions: {
|
||||
handler(newValue) {
|
||||
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote"
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('siteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
this.resetWarningsAndErrors();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
customerQuestions,
|
||||
textboxQuestion,
|
||||
alert,
|
||||
Form,
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import customerQuestions from '@/layouts/address-lookup/customer-questions/customer-questions';
|
||||
|
||||
const customerModel = {
|
||||
addressQuestions: {
|
||||
streetAddress: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zipCode: ''
|
||||
},
|
||||
firstName: '',
|
||||
lastName: '',
|
||||
emailAddress: ''
|
||||
};
|
||||
// const customerModel = {
|
||||
// addressQuestions: {
|
||||
// streetAddress: '',
|
||||
// city: '',
|
||||
// state: '',
|
||||
// zipCode: ''
|
||||
// },
|
||||
// firstName: '',
|
||||
// lastName: '',
|
||||
// emailAddress: ''
|
||||
// };
|
||||
|
||||
describe('customerQuestions.vue', () => {
|
||||
it('Should render customerQuestions sub-components (addressQuestions, first name, last name, and email textbox-questions)', async () => {
|
||||
it('Should render customerQuestions sub-components '
|
||||
+ 'addressQuestions, first name, last name, and email textbox - questions)', async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(customerQuestions);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
<template>
|
||||
<addressQuestions ref="addressQuestions" v-model="customerModel.addressQuestions" />
|
||||
<addressQuestions
|
||||
ref="addressQuestions"
|
||||
v-model="customerModel.addressQuestions" />
|
||||
<div class="row mb-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="FirstNameQuestionWidget"
|
||||
v-model="customerModel.firstName"
|
||||
ref="firstName"
|
||||
v-model="customerModel.firstName"
|
||||
cmsWidgetName="FirstNameQuestionWidget"
|
||||
inputId="08497a2efd9a4a73a70360ab47b4838d"
|
||||
disableAutoFill
|
||||
:validationRules="rules.firstName" />
|
||||
|
|
@ -14,9 +16,9 @@
|
|||
<div class="row mb-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="LastNameQuestionWidget"
|
||||
v-model="customerModel.lastName"
|
||||
ref="lastName"
|
||||
v-model="customerModel.lastName"
|
||||
cmsWidgetName="LastNameQuestionWidget"
|
||||
inputId="0030e56a57e74a4ab92de7fb8e97fec5"
|
||||
disableAutoFill
|
||||
:validationRules="rules.lastName" />
|
||||
|
|
@ -25,13 +27,16 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import addressQuestions from '@/iss-components/address-questions/address-questions.vue';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
import addressQuestions from '@/iss-components/address-questions/address-questions';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
|
||||
export default {
|
||||
name: 'customer-questions',
|
||||
emits: ['update:modelValue'], // The component emits an event
|
||||
components: {
|
||||
addressQuestions,
|
||||
textboxQuestion
|
||||
}, // The component emits an event
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
|
|
@ -50,6 +55,7 @@ export default {
|
|||
},
|
||||
validationRules: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
rules: {
|
||||
|
|
@ -60,17 +66,13 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
customerModel: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
addressQuestions,
|
||||
textboxQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,42 @@
|
|||
import addressVehiclesQuestion from '@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue';
|
||||
import addressVehiclesQuestion from '@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
|
||||
function setupMocks({
|
||||
modelValueProp = 'TESTCAR',
|
||||
cmsQuestionText = 'CMS text goes here'
|
||||
}) {
|
||||
const mountOptions = getMountOptions();
|
||||
|
||||
// Mock props
|
||||
mountOptions.propsData = {
|
||||
modelValue: modelValueProp
|
||||
};
|
||||
|
||||
const wrapper = shallowMount(addressVehiclesQuestion, mountOptions);
|
||||
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
QuestionText: cmsQuestionText
|
||||
};
|
||||
return { wrapper, cmsContent };
|
||||
}
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((contentName) => {
|
||||
if (contentName === 'AlertMatchedDifferentVehicleWidget') {
|
||||
return 'AlertMatchedDifferentVehicleWidgetTestReturn';
|
||||
}
|
||||
if (contentName === 'AlertMatchedTwoIdenticalYMMVehicleWidget') {
|
||||
return 'AlertMatchedTwoIdenticalYMMVehicleWidgetTestReturn';
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
vehicles: jest.fn(() => [{ vehicle: 'test' }])
|
||||
}
|
||||
};
|
||||
|
||||
describe('address-vehicles-question.vue', () => {
|
||||
test('Selected vehicle is emitted upon selection', async () => {
|
||||
// Arrange
|
||||
|
|
@ -14,13 +49,13 @@ describe('address-vehicles-question.vue', () => {
|
|||
|
||||
// Assert
|
||||
expect(wrapper.emitted()['update:modelValue'][0]).toEqual([
|
||||
{ selectedVehicle: '2016 Jaguar F-Type' },
|
||||
{ selectedVehicle: '2016 Jaguar F-Type' }
|
||||
]);
|
||||
});
|
||||
test('Should return content for differentVehicleAlertHeader', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(addressVehiclesQuestion, {
|
||||
mixins: [mockMixin],
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Assert
|
||||
|
|
@ -62,40 +97,3 @@ describe('address-vehicles-question.vue', () => {
|
|||
expect(wrapper.vm.AlertMatchedTwoIdenticalYMMVehicleBody).toEqual('AlertMatchedTwoIdenticalYMMVehicleWidgetTestReturn');
|
||||
});
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((contentName) => {
|
||||
if (contentName === 'AlertMatchedDifferentVehicleWidget') {
|
||||
return 'AlertMatchedDifferentVehicleWidgetTestReturn';
|
||||
}
|
||||
if (contentName === 'AlertMatchedTwoIdenticalYMMVehicleWidget') {
|
||||
return 'AlertMatchedTwoIdenticalYMMVehicleWidgetTestReturn';
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
vehicles: jest.fn(() => {
|
||||
return [{ vehicle: 'test' }];
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
function setupMocks({
|
||||
modelValueProp = 'TESTCAR',
|
||||
cmsQuestionText = 'CMS text goes here'
|
||||
}) {
|
||||
const mountOptions = getMountOptions();
|
||||
|
||||
// Mock props
|
||||
mountOptions.propsData = {
|
||||
modelValue: modelValueProp
|
||||
};
|
||||
|
||||
const wrapper = shallowMount(addressVehiclesQuestion, mountOptions);
|
||||
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
QuestionText: cmsQuestionText
|
||||
};
|
||||
return { wrapper, cmsContent };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,38 +1,36 @@
|
|||
<template>
|
||||
<div>
|
||||
<alert
|
||||
ref="differentVehicleAlert"
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
id="address-vehicles-question-alert"
|
||||
ref="differentVehicleAlert"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualHeadline="differentVehicleAlertHeader"
|
||||
:manualCopy="differentVehicleAlertBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false"
|
||||
id="address-vehicles-question-alert" />
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false"
|
||||
id="address-vehicles-question-alert" />
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
id="address-vehicles-question-alert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="my-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
</div>
|
||||
|
||||
<buttonQuestion
|
||||
class="address-vehicles-question"
|
||||
ref="addressVehiclesQuestion"
|
||||
v-model="selectedVehicleVin"
|
||||
class="address-vehicles-question"
|
||||
buttonTypeString="listButton"
|
||||
groupName="ChooseAddressVehicle"
|
||||
:questionText="questionText"
|
||||
:answers="vehicles"
|
||||
v-model="selectedVehicleVin"
|
||||
isRequired
|
||||
:validation-rules="validationRules" />
|
||||
|
||||
:validationRules="validationRules" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -43,6 +41,10 @@ import { getDamageString } from '@/helpers/damage-helper';
|
|||
|
||||
export default {
|
||||
name: 'address-vehicles-question',
|
||||
components: {
|
||||
buttonQuestion,
|
||||
alert
|
||||
},
|
||||
props: {
|
||||
vehicles: Array,
|
||||
vehicleSelected: Object,
|
||||
|
|
@ -53,12 +55,11 @@ export default {
|
|||
displayMatchedDifferentVehicleAlert: Boolean,
|
||||
displayMatchedTwoIdenticalYMMVehicleAlert: Boolean
|
||||
},
|
||||
emits: ['update: modelValue'],
|
||||
computed: {
|
||||
differentVehicleAlertHeader() {
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'HeadlineText').replaceAll(
|
||||
'{custom:damage}',
|
||||
getDamageString()
|
||||
);
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'HeadlineText').replaceAll('{custom:damage}',
|
||||
getDamageString());
|
||||
},
|
||||
differentVehicleAlertBody() {
|
||||
const vinYmmFound = `${this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model}`;
|
||||
|
|
@ -70,10 +71,8 @@ export default {
|
|||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader() {
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:damage}', getDamageString());
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText').replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleBody() {
|
||||
const vinYmmsFound = `${this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model} ${this.selectedVehicle?.vehicle.style}`;
|
||||
|
|
@ -88,10 +87,10 @@ export default {
|
|||
return this.getCmsContent('VehicleConfirmationQuestion', 'QuestionText');
|
||||
},
|
||||
selectedVehicleVin: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
|
|
@ -99,17 +98,13 @@ export default {
|
|||
// this computed is only needed for the computed differentVehicleAlertBody text above
|
||||
return this.vehicles.find(({ vin }) => vin === this.selectedVehicleVin);
|
||||
},
|
||||
vehicleSelected(){
|
||||
vehicleSelected() {
|
||||
return this.vehicleSelected;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion,
|
||||
alert
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.address-vehicles-question {
|
||||
.question-text {
|
||||
margin-bottom: 0.5rem;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,104 @@ jest.mock('@/helpers/layout-helper.js', () => ({
|
|||
settleAllPromises: jest.fn()
|
||||
}));
|
||||
|
||||
function setupMocks({
|
||||
route = null,
|
||||
lookupVehicleByVinResponse
|
||||
}) {
|
||||
useMainStore().applicationUser = {
|
||||
pageData: {
|
||||
'address-vehicles':
|
||||
[
|
||||
{
|
||||
vehicle: {
|
||||
carId: 'CR00069309',
|
||||
category: 'SUV',
|
||||
imageUrl:
|
||||
'https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg',
|
||||
imageVifColor: 'white',
|
||||
imageVifNumber: '13769',
|
||||
make: 'Hyundai',
|
||||
model: 'Santa Fe',
|
||||
style: '4 door utility',
|
||||
year: 2020
|
||||
},
|
||||
vin: '5NMS3CADXLH233004'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
useMainStore().lookupVehicleByVin = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: lookupVehicleByVinResponse || {
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const mountOptions = getMountOptions({
|
||||
route: route || undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId: 'CR00069309',
|
||||
category: 'SUV',
|
||||
imageUrl:
|
||||
'https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg',
|
||||
imageVifColor: 'white',
|
||||
imageVifNumber: '13769',
|
||||
make: 'Hyundai',
|
||||
model: 'Santa Fe',
|
||||
style: '4 door utility',
|
||||
year: 2020
|
||||
},
|
||||
vin: '5NMS3CADXLH233004'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const apiResponses = {
|
||||
cmsContent: {}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||
|
||||
// Mock props
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((contentName) => {
|
||||
if (contentName === 'FoundMultipleVehicles') {
|
||||
return 'FoundMultipleVehiclesTestReturn';
|
||||
}
|
||||
if (contentName === 'ProvideVinAlert') {
|
||||
return 'ProvideVinAlertTestReturn';
|
||||
}
|
||||
return null;
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
dynamicStrings() {
|
||||
return { ROUTER_LINK: 'routerLink:' };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mountOptions.mixins = [mockMixin];
|
||||
|
||||
const wrapper = shallowMount(addressVehicles, mountOptions);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('address-vehicles.vue', () => {
|
||||
test('Should navigate to CLICKED_BACK if backButtonAction is run', async () => {
|
||||
// Arrange
|
||||
|
|
@ -132,118 +230,14 @@ describe('address-vehicles.vue', () => {
|
|||
useMainStore().order.vehicle.carId = 'CR00000395';
|
||||
|
||||
// Act
|
||||
addressVehicles.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
addressVehicles.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'address-vehicles' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
// Assert
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
route = null,
|
||||
lookupVehicleByVinResponse
|
||||
}) {
|
||||
useMainStore().applicationUser = {
|
||||
pageData: {
|
||||
'address-vehicles':
|
||||
[
|
||||
{
|
||||
vehicle: {
|
||||
carId: 'CR00069309',
|
||||
category: 'SUV',
|
||||
imageUrl:
|
||||
'https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg',
|
||||
imageVifColor: 'white',
|
||||
imageVifNumber: '13769',
|
||||
make: 'Hyundai',
|
||||
model: 'Santa Fe',
|
||||
style: '4 door utility',
|
||||
year: 2020
|
||||
},
|
||||
vin: '5NMS3CADXLH233004'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
useMainStore().lookupVehicleByVin = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: lookupVehicleByVinResponse
|
||||
? lookupVehicleByVinResponse : {
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const mountOptions = getMountOptions({
|
||||
route: route ? route : undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId: 'CR00069309',
|
||||
category: 'SUV',
|
||||
imageUrl:
|
||||
'https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg',
|
||||
imageVifColor: 'white',
|
||||
imageVifNumber: '13769',
|
||||
make: 'Hyundai',
|
||||
model: 'Santa Fe',
|
||||
style: '4 door utility',
|
||||
year: 2020
|
||||
},
|
||||
vin: '5NMS3CADXLH233004'
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const apiResponses = {
|
||||
cmsContent: {}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||
|
||||
// Mock props
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((contentName) => {
|
||||
if (contentName === 'FoundMultipleVehicles') {
|
||||
return 'FoundMultipleVehiclesTestReturn';
|
||||
}
|
||||
if (contentName === 'ProvideVinAlert') {
|
||||
return 'ProvideVinAlertTestReturn';
|
||||
}
|
||||
return null;
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
dynamicStrings() {
|
||||
return { ROUTER_LINK: 'routerLink:' };
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
mountOptions.mixins = [mockMixin];
|
||||
|
||||
const wrapper = shallowMount(addressVehicles, mountOptions);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
ref="theForm"
|
||||
v-slot="{ meta }">
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="fade-on-route-transition sub-container overflow-scroll px-5">
|
||||
|
|
@ -13,44 +13,51 @@
|
|||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
cmsWidgetName="FoundMultipleVehicles"
|
||||
id="multiple-vehicles-alert"
|
||||
ref="alertFoundMultipleVehicles"
|
||||
cmsWidgetName="FoundMultipleVehicles"
|
||||
class="my-5"
|
||||
alertClass="alert-warning"
|
||||
:manualHeadline="AlertFoundMultipleVehiclesHeader"
|
||||
manualCopy=""
|
||||
v-bind:isDismissible="false"
|
||||
id="multiple-vehicles-alert" />
|
||||
:isDismissible="false" />
|
||||
<addressVehiclesQuestion
|
||||
ref="addressVehiclesQuestion"
|
||||
v-model="selectedVehicleVin"
|
||||
cmsWidgetName="VehicleConfirmationQuestion"
|
||||
:vehicles="VehiclesForQuestions"
|
||||
:vehicleSelected ="VehicleSelected"
|
||||
:vehicleSelected="VehicleSelected"
|
||||
validationRules="vehicle-required"
|
||||
v-model="selectedVehicleVin"
|
||||
:isCarIdDifferent="isCarIdDifferent"
|
||||
:displayMatchedDifferentVehicleAlert = "displayMatchedDifferentVehicleAlert"
|
||||
:displayMatchedTwoIdenticalYMMVehicleAlert = "displayMatchedTwoIdenticalYMMVehicleAlert" />
|
||||
<div class="alert-provide-vin my-3"
|
||||
v-if="splitAlertProvideVinBodyForLink.length">
|
||||
<span v-for="copy in splitAlertProvideVinBodyForLink" :key="copy">
|
||||
<span v-if="doesCopyContainRouterLink(copy)" class="text-body">
|
||||
:displayMatchedDifferentVehicleAlert="displayMatchedDifferentVehicleAlert"
|
||||
:displayMatchedTwoIdenticalYMMVehicleAlert="displayMatchedTwoIdenticalYMMVehicleAlert" />
|
||||
<div
|
||||
v-if="splitAlertProvideVinBodyForLink.length"
|
||||
class="alert-provide-vin my-3">
|
||||
<span
|
||||
v-for="copy in splitAlertProvideVinBodyForLink"
|
||||
:key="copy">
|
||||
<span
|
||||
v-if="doesCopyContainRouterLink(copy)"
|
||||
class="text-body">
|
||||
<router-link
|
||||
:to="{
|
||||
query: { issPage: `${getRouterLinkRouteFromCopy(copy)}` },
|
||||
name: 'root',
|
||||
}"
|
||||
>{{ getRouterLinkDisplayTextFromCopy(copy) }}</router-link >
|
||||
}">{{ getRouterLinkDisplayTextFromCopy(copy) }}</router-link>
|
||||
</span>
|
||||
<span v-else class="m-0 text-body" v-html="copy"></span>
|
||||
<span
|
||||
v-else
|
||||
class="m-0 text-body"
|
||||
v-html="copy"></span>
|
||||
</span>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="backButtonAction"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
ref="siteFooter" />
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -58,7 +65,6 @@
|
|||
|
||||
<script>
|
||||
// Import Supporting Files
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import { settleAllPromises } from '@/helpers/layout-helper';
|
||||
import { useMainStore } from '@/store';
|
||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||
|
|
@ -67,20 +73,21 @@ import { required } from '@/helpers/validation-rules';
|
|||
import { Form, defineRule } from 'vee-validate';
|
||||
import { isGlassAvailableForCarId } from '@/helpers/damage-helper';
|
||||
import {
|
||||
fetchCmsContentForPage,
|
||||
doesCopyContainRouterLink,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy
|
||||
} from '@/helpers/cms-content-helper';
|
||||
} from '@/helpers/cms-content-helper.js';
|
||||
import { routerParams } from '@/router/router-constants/router-params';
|
||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||
|
||||
// Import Component
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import siteHeader from '@/iss-components/site-header/site-header';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
import addressVehiclesQuestion from '@/layouts/address-vehicles/address-vehicles-question/address-vehicles-question';
|
||||
|
||||
|
|
@ -89,6 +96,16 @@ defineRule('vehicle-required', required(errorMessages.VEHICLE_REQUIRED));
|
|||
|
||||
export default {
|
||||
name: 'address-vehicles',
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleBanner,
|
||||
alert,
|
||||
addressVehiclesQuestion
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
|
@ -131,15 +148,13 @@ export default {
|
|||
return this.VehiclesForQuestions.length;
|
||||
},
|
||||
AlertFoundMultipleVehiclesHeader() {
|
||||
return this.getCmsContent(
|
||||
'FoundMultipleVehicles',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:vehicleCount}', this.vehicleCount);
|
||||
return this.getCmsContent('FoundMultipleVehicles',
|
||||
'HeadlineText').replaceAll('{custom:vehicleCount}', this.vehicleCount);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${ this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model}`;
|
||||
const vinYmmFound = `${this.selectedVehicle?.vehicle.year} ${this.selectedVehicle?.vehicle.make} ${this.selectedVehicle?.vehicle.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
},
|
||||
AlertProvideVinBody() {
|
||||
return this.getCmsContent('ProvideVinAlert', 'BodyText');
|
||||
|
|
@ -157,9 +172,9 @@ export default {
|
|||
return {
|
||||
vin: v.vin,
|
||||
vehicle: v.vehicle,
|
||||
Text: v.vehicle.year + ' ' + v.vehicle.make + ' ' + v.vehicle.model,
|
||||
Text: `${v.vehicle.year} ${v.vehicle.make} ${v.vehicle.model}`,
|
||||
Name: v.vin,
|
||||
SubText: 'VIN ' + vinStart + vinEnd
|
||||
SubText: `VIN ${vinStart}${vinEnd}`
|
||||
};
|
||||
});
|
||||
return mappedData;
|
||||
|
|
@ -168,14 +183,37 @@ export default {
|
|||
return useMainStore().pageData(issPageValues.ADDRESS_VEHICLES);
|
||||
},
|
||||
selectedVehicle() {
|
||||
return this.VehiclesForQuestions.find(
|
||||
({ vin }) => vin === this.selectedVehicleVin
|
||||
);
|
||||
return this.VehiclesForQuestions.find(({ vin }) => vin === this.selectedVehicleVin);
|
||||
},
|
||||
VehicleSelected() {
|
||||
return this.mainStore.order.vehicle;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedVehicleVin: {
|
||||
handler() {
|
||||
this.resetWarningsAndErrors();
|
||||
// does this vehicle match the previously selected carId?
|
||||
this.isCarIdDifferent
|
||||
= this.selectedVehicle?.vehicle.carId !== useMainStore().vehicle.carId;
|
||||
if (this.isCarIdDifferent
|
||||
&& this.selectedVehicle?.vehicle.carId !== this.previouslyEnteredCarId) {
|
||||
this.previouslyEnteredCarId = this.selectedVehicle?.vehicle.carId;
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
const carStyle = this.selectedVehicle?.vehicle.style;
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
|
||||
this.forwardButtonCarStyle = carStyle;
|
||||
} else {
|
||||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
this.$refs.siteFooter.updateButtonText(`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model} ${this.forwardButtonCarStyle}`);
|
||||
} else {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doesCopyContainRouterLink,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
|
|
@ -199,19 +237,15 @@ export default {
|
|||
if (!vinLookup) {
|
||||
return;
|
||||
}
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||
vinLookup.data.carId
|
||||
);
|
||||
await useMainStore().saveVin(
|
||||
{
|
||||
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, {
|
||||
vin: this.selectedVehicle.vin
|
||||
}),
|
||||
isSelectedGlassAvailableForVehicle:
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.carId);
|
||||
await useMainStore().saveVin({
|
||||
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, {
|
||||
vin: this.selectedVehicle.vin
|
||||
}),
|
||||
isSelectedGlassAvailableForVehicle:
|
||||
this.isSelectedGlassAvailableForVehicle
|
||||
},
|
||||
false
|
||||
);
|
||||
},
|
||||
false);
|
||||
|
||||
return await this.navigateForward();
|
||||
},
|
||||
|
|
@ -219,12 +253,10 @@ export default {
|
|||
// If the vehicle selected on this page is different from the one originally entered and the selected glass is not available
|
||||
// for that vehicle, then navigate back to "vehicle-damage" and display vehicle changed alert on that page.
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true });
|
||||
} else {
|
||||
await this.navigateForwardWithSingleCarMatch();
|
||||
}
|
||||
|
|
@ -234,49 +266,11 @@ export default {
|
|||
this.displayMatchedTwoIdenticalYMMVehicleAlert = false;
|
||||
this.forwardButtonCarStyle = '';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedVehicleVin: {
|
||||
handler() {
|
||||
this.resetWarningsAndErrors();
|
||||
// does this vehicle match the previously selected carId?
|
||||
this.isCarIdDifferent =
|
||||
this.selectedVehicle?.vehicle.carId !== useMainStore().vehicle.carId;
|
||||
if (this.isCarIdDifferent &&
|
||||
this.selectedVehicle?.vehicle.carId !== this.previouslyEnteredCarId) {
|
||||
this.previouslyEnteredCarId = this.selectedVehicle?.vehicle.carId;
|
||||
if(this.isTwoIdenticalYMMVehicleFound){
|
||||
const carStyle = this.selectedVehicle?.vehicle.style;
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
|
||||
this.forwardButtonCarStyle= carStyle;
|
||||
} else {
|
||||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
`Continue with ${this.selectedVehicle.vehicle.year} ${this.selectedVehicle.vehicle.make} ${this.selectedVehicle.vehicle.model} ${this.forwardButtonCarStyle}`
|
||||
);
|
||||
} else {
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
Form,
|
||||
vehicleBanner,
|
||||
alert,
|
||||
addressVehiclesQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.alert-provide-vin {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.4;
|
||||
|
|
@ -290,8 +284,8 @@ export default {
|
|||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
}
|
||||
|
||||
.overflow-scroll {
|
||||
height: calc(100% - 180px);
|
||||
.overflow-scroll {
|
||||
height: calc(100% - 180px);
|
||||
overflow-X: hidden !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2">
|
||||
<p>Placeholder for bailout page</p>
|
||||
<siteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
/>
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -30,15 +33,14 @@ import { useMainStore } from '@/store';
|
|||
|
||||
export default {
|
||||
name: 'bailout-page',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
data() {
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
async beforeRouteEnter(to, from, next)
|
||||
{
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
// Settle promises and get results
|
||||
|
|
@ -48,11 +50,17 @@ export default {
|
|||
promise: cmsContentPromise
|
||||
}];
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
},
|
||||
methods:
|
||||
{
|
||||
backButtonAction() {
|
||||
|
|
@ -62,13 +70,6 @@ export default {
|
|||
},
|
||||
navigateForward() {
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import capabilityQuestions from '@/layouts/capability-questions/capability-quest
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import baseMixin from '../../mixins/base-mixin';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { nextTick } from 'vue';
|
||||
import baseMixin from '@/mixins/base-mixin';
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock('@/helpers/layout-helper.js', () => ({
|
||||
|
|
@ -19,78 +19,134 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
|||
fetchCmsContentForPage: jest.fn()
|
||||
}));
|
||||
|
||||
const baseStoreGettersPageData = () => {
|
||||
return {
|
||||
partsOrQuestions: [
|
||||
{
|
||||
parts: [
|
||||
{
|
||||
childPartQuestions: []
|
||||
}
|
||||
],
|
||||
capabilityQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
const baseStoreGettersPageData = () => ({
|
||||
partsOrQuestions: [
|
||||
{
|
||||
parts: [
|
||||
{
|
||||
childPartQuestions: []
|
||||
}
|
||||
],
|
||||
capabilityQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
'Is your vehicle equipped with the optional Lane-Keeping System which tugs on the steering wheel and/or beeps to alert you if you drift too close to the edge of the lane?',
|
||||
answers: [
|
||||
{
|
||||
answerResult1: 'DYNAMIC',
|
||||
answerResult2: '1',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: null,
|
||||
answerResult: 'DYNAMIC'
|
||||
},
|
||||
{
|
||||
answerResult1: 'Unknown',
|
||||
answerResult2: '0',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: null,
|
||||
answerResult: 'Unknown'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
partQuestions: [],
|
||||
questions: [],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
const baseStoreGettersDamage = () => {
|
||||
return {
|
||||
partsQuestionAnswers: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
result: 'FW04848',
|
||||
answeredQuestions: [
|
||||
{
|
||||
questionText:
|
||||
answers: [
|
||||
{
|
||||
answerResult1: 'DYNAMIC',
|
||||
answerResult2: '1',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: null,
|
||||
answerResult: 'DYNAMIC'
|
||||
},
|
||||
{
|
||||
answerResult1: 'Unknown',
|
||||
answerResult2: '0',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: null,
|
||||
answerResult: 'Unknown'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
partQuestions: [],
|
||||
questions: [],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
}
|
||||
]
|
||||
});
|
||||
const baseStoreGettersDamage = () => ({
|
||||
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?',
|
||||
selectedAnswer: '1|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
selectedAnswer: '1|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?',
|
||||
selectedAnswer: '2|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
selectedAnswer: '2|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
useMainStore().pageData = baseStoreGettersPageData;
|
||||
useMainStore().damage = baseStoreGettersDamage;
|
||||
|
||||
function setupMocks({
|
||||
mountOptionsMockData = {
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
actionList: [
|
||||
{
|
||||
actionName: 'saveCapabilityQuestionAnswers',
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
actionName: 'getPartsOrQuestions',
|
||||
data: {}
|
||||
}
|
||||
],
|
||||
route: {
|
||||
query: {
|
||||
issPage: 'capability-questions'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedSwitcher: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerData: {
|
||||
answerResult: 'FW04848',
|
||||
answeredQuestions: []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
questionsData: {
|
||||
get() {
|
||||
return this.computedSwitcher;
|
||||
},
|
||||
set(val) {
|
||||
this.computedSwitcher = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}) {
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
const mountOptions = getMountOptions({
|
||||
...mountOptionsMockData,
|
||||
mixins: [baseMixin, vehicleQuestionsMixin]
|
||||
});
|
||||
mountOptions.attachTo = document.body;
|
||||
|
||||
const wrapper = shallowMount(capabilityQuestions, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('capabilityQuestions.vue', () => {
|
||||
describe('method arePagePrerequisitesValid...', () => {
|
||||
test('Should return true for valid page requisites if pageData exists', () => {
|
||||
|
|
@ -109,9 +165,7 @@ describe('capabilityQuestions.vue', () => {
|
|||
test('Should return false for valid page requisites if partsOrQuestions in pageData is missing', () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
useMainStore().pageData = jest.fn(() => {
|
||||
return undefined;
|
||||
});
|
||||
useMainStore().pageData = jest.fn(() => undefined);
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
|
@ -124,11 +178,9 @@ describe('capabilityQuestions.vue', () => {
|
|||
|
||||
test('Should be at least one item in partsOrQuestions', () => {
|
||||
// Arrange
|
||||
useMainStore().pageData = jest.fn(() => {
|
||||
return {
|
||||
partsOrQuestions: []
|
||||
};
|
||||
});
|
||||
useMainStore().pageData = jest.fn(() => ({
|
||||
partsOrQuestions: []
|
||||
}));
|
||||
useMainStore().damage = baseStoreGettersDamage;
|
||||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
|
@ -207,11 +259,9 @@ describe('capabilityQuestions.vue', () => {
|
|||
]
|
||||
}
|
||||
];
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: []
|
||||
};
|
||||
});
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => ({
|
||||
data: []
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -242,13 +292,11 @@ describe('capabilityQuestions.vue', () => {
|
|||
]
|
||||
}
|
||||
];
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -279,11 +327,9 @@ describe('capabilityQuestions.vue', () => {
|
|||
]
|
||||
}
|
||||
];
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: []
|
||||
};
|
||||
});
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => ({
|
||||
data: []
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -316,13 +362,11 @@ describe('capabilityQuestions.vue', () => {
|
|||
]
|
||||
}
|
||||
];
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
wrapper.vm.navigateForward = jest.fn();
|
||||
|
||||
// Act
|
||||
|
|
@ -335,65 +379,3 @@ describe('capabilityQuestions.vue', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
mountOptionsMockData = {
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
actionList: [
|
||||
{
|
||||
actionName: 'saveCapabilityQuestionAnswers',
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
actionName: 'getPartsOrQuestions',
|
||||
data: {}
|
||||
}
|
||||
],
|
||||
route: {
|
||||
query: {
|
||||
issPage: 'capability-questions'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedSwitcher: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerData: {
|
||||
answerResult: 'FW04848',
|
||||
answeredQuestions: []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
questionsData: {
|
||||
get() {
|
||||
return this.computedSwitcher;
|
||||
},
|
||||
set(val) {
|
||||
this.computedSwitcher = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}) {
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
const mountOptions = getMountOptions({
|
||||
...mountOptionsMockData,
|
||||
mixins: [baseMixin, vehicleQuestionsMixin]
|
||||
});
|
||||
mountOptions['attachTo'] = document.body;
|
||||
|
||||
const wrapper = shallowMount(capabilityQuestions, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,21 @@
|
|||
<template>
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit" ref="theForm"
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
>
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
isRequired
|
||||
ref="questionsPageLayout"
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
v-model="selectedAnswers"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@back-click="navigateBack"
|
||||
:index="currentGlassIndex" />
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
:index="currentGlassIndex"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@back-click="navigateBack" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
|
|
@ -30,25 +30,16 @@ import { Form } from 'vee-validate';
|
|||
import { useMainStore } from '@/store';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import questionsPageLayout from '@/iss-components/questions-page-layout/questions-page-layout.vue';
|
||||
import questionsPageLayout from '@/iss-components/questions-page-layout/questions-page-layout';
|
||||
|
||||
export default {
|
||||
name: 'capability-questions',
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
questionsPageLayout
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
questionsData: [],
|
||||
selectedAnswers: {},
|
||||
currentGlassIndex: 0,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
},
|
||||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
|
|
@ -66,6 +57,16 @@ export default {
|
|||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
questionsData: [],
|
||||
selectedAnswers: {},
|
||||
currentGlassIndex: 0,
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
AlertFewMoreQuestionsHeader() {
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert', 'HeadlineText');
|
||||
|
|
@ -85,9 +86,8 @@ export default {
|
|||
arePagePrerequisitesValid() {
|
||||
const capabilityQuestionsFromPageData = useMainStore().pageData(issPageValues.CAPABILITY_QUESTIONS);
|
||||
return (
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName) &&
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some(
|
||||
(part) => part?.capabilityQuestions?.length > 0)
|
||||
capabilityQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)
|
||||
&& capabilityQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.capabilityQuestions?.length > 0)
|
||||
);
|
||||
},
|
||||
getInitialQuestionData() {
|
||||
|
|
@ -98,24 +98,20 @@ export default {
|
|||
.map((glass, index) => {
|
||||
// NOTE: questions for property "questions" can differ between layouts
|
||||
glass.questions = glass.capabilityQuestions;
|
||||
glass.answerKey = glass.glassLocation + '-' + glass.glassName;
|
||||
glass.answerKey = `${glass.glassLocation}-${glass.glassName}`;
|
||||
// reset selectedAnswers for this glass
|
||||
this.selectedAnswers[glass.answerKey] = [];
|
||||
const updatedGlass = this.setupInitialData(
|
||||
glass,
|
||||
const updatedGlass = this.setupInitialData(glass,
|
||||
index,
|
||||
alreadyAnsweredQuestions
|
||||
);
|
||||
alreadyAnsweredQuestions);
|
||||
// Set up watch for each set of glass questions
|
||||
this.$watch(
|
||||
'selectedAnswers.' + glass.answerKey,
|
||||
this.$watch(`selectedAnswers.${glass.answerKey}`,
|
||||
(newValue) => {
|
||||
if (newValue && Object.keys(newValue).length > 0) {
|
||||
this.handleAnswerUpdates(newValue, glass.answerKey);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
{ deep: true });
|
||||
return updatedGlass;
|
||||
});
|
||||
},
|
||||
|
|
@ -124,9 +120,7 @@ export default {
|
|||
// get answerResult2 of returned answer
|
||||
let selectedAnswerResult2;
|
||||
glass.questions.forEach((q) => {
|
||||
const idx = q.answers.findIndex(
|
||||
(a) => a.answerResult === glass.answerData.answerResult
|
||||
);
|
||||
const idx = q.answers.findIndex((a) => a.answerResult === glass.answerData.answerResult);
|
||||
if (idx !== -1) {
|
||||
selectedAnswerResult2 = q.answers[idx].answerResult2;
|
||||
}
|
||||
|
|
@ -149,13 +143,11 @@ export default {
|
|||
await this.mainStore.saveCapabilityQuestionAnswers(questionAnswersArray);
|
||||
// get parts from the capabilityQuestionAnswers
|
||||
const partsOrQuestions = this.partsOrQuestionsData;
|
||||
for (let answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => {
|
||||
return (
|
||||
partOrQuestion.glassLocation === answer.glassLocation &&
|
||||
partOrQuestion.glassName === answer.glassName
|
||||
);
|
||||
}).parts[0].childParts = [
|
||||
for (const answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => (
|
||||
partOrQuestion.glassLocation === answer.glassLocation
|
||||
&& partOrQuestion.glassName === answer.glassName
|
||||
)).parts[0].childParts = [
|
||||
{
|
||||
partNumber: answer.partNum
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,8 +76,7 @@ describe('contactDetails.vue', () => {
|
|||
const checkboxLabel = getRandomString(50, 100);
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() =>
|
||||
checkboxLabel),
|
||||
getCmsContent: jest.fn().mockImplementation(() => checkboxLabel),
|
||||
setCmsContent: jest.fn()
|
||||
}
|
||||
};
|
||||
|
|
@ -107,8 +106,7 @@ describe('contactDetails.vue', () => {
|
|||
const disclaimerText = getRandomString(50, 100);
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() =>
|
||||
disclaimerText),
|
||||
getCmsContent: jest.fn().mockImplementation(() => disclaimerText),
|
||||
setCmsContent: jest.fn()
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
describe ('test', () => {
|
||||
test ('dummy test', () => {
|
||||
describe('test', () => {
|
||||
test('dummy test', () => {
|
||||
// Arrange
|
||||
let test = "test";
|
||||
let test = 'test';
|
||||
|
||||
// Act
|
||||
test = "test2"
|
||||
test = 'test2';
|
||||
|
||||
// Assert
|
||||
expect(test.length).toBe(5);
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
// *Testing to be completed on SSR-603
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ describe ('test', () => {
|
|||
// test("Should return false for valid page requisites if vin is missing", () => {
|
||||
// // Arrange
|
||||
// const { wrapper } = setupMocks({});
|
||||
|
||||
|
||||
// useMainStore().order.vehicle.vin = null;
|
||||
|
||||
// // Act
|
||||
|
|
@ -222,9 +222,9 @@ describe ('test', () => {
|
|||
// mountOptions.global = {
|
||||
// plugins: [createTestingPinia()]
|
||||
// }
|
||||
|
||||
|
||||
// const wrapper = shallowMount(coverageStatement, mountOptions);
|
||||
|
||||
|
||||
// wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||
|
||||
// return { wrapper };
|
||||
|
|
|
|||
|
|
@ -283,8 +283,7 @@ export default {
|
|||
if (!store.order.damage.isRepair) {
|
||||
const parts = store.order.lineItems.glassParts;
|
||||
|
||||
if (parts != null && parts.filter((part) =>
|
||||
part.requiresRecalibration).length > 0) {
|
||||
if (parts != null && parts.filter((part) => part.requiresRecalibration).length > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -427,7 +426,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.body-text {
|
||||
p {
|
||||
font-size: 14px;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,19 @@
|
|||
import { shallowMount, mount } from '@vue/test-utils';
|
||||
import recalModal from '@/layouts/coverage-statement/recal-modal/recal-modal.vue';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import recalModal from '@/layouts/coverage-statement/recal-modal/recal-modal';
|
||||
|
||||
const mockCmsContent = {
|
||||
HeaderText: 'Sample header text here.',
|
||||
SubheaderText: 'Sample subheader text here.',
|
||||
Image: 'https://www.sampleImage.sample',
|
||||
BodyText: 'Sample body text here.',
|
||||
FooterText: 'Sample footer text here.'
|
||||
};
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => mockCmsContent[cmsFieldName])
|
||||
}
|
||||
};
|
||||
|
||||
describe('modal.vue', () => {
|
||||
it('Should display header text when HeaderText is defined in the CMS', async () => {
|
||||
|
|
@ -11,7 +25,7 @@ describe('modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['HeaderText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.HeaderText));
|
||||
});
|
||||
|
||||
it('Should display subheader text when SubheaderText is defined in the CMS', async () => {
|
||||
|
|
@ -23,7 +37,7 @@ describe('modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['SubheaderText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.SubheaderText));
|
||||
});
|
||||
|
||||
it('Should insert image url when Image is defined in the CMS', async () => {
|
||||
|
|
@ -35,7 +49,7 @@ describe('modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['Image']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.Image));
|
||||
});
|
||||
|
||||
it('Should display body text when BodyText is defined in the CMS', async () => {
|
||||
|
|
@ -47,22 +61,6 @@ describe('modal.vue', () => {
|
|||
},
|
||||
attachTo: document.body
|
||||
});
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent['BodyText']));
|
||||
expect(wrapper.html()).toEqual(expect.stringContaining(mockCmsContent.BodyText));
|
||||
});
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||
return mockCmsContent[cmsFieldName];
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
const mockCmsContent = {
|
||||
HeaderText: 'Sample header text here.',
|
||||
SubheaderText: 'Sample subheader text here.',
|
||||
Image: 'https://www.sampleImage.sample',
|
||||
BodyText: 'Sample body text here.',
|
||||
FooterText: 'Sample footer text here.'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,21 +3,28 @@
|
|||
:ref="ModalName"
|
||||
:modalId="ModalName"
|
||||
:footerButtonText="ModalCloseButtonText"
|
||||
@footer-button-event="closeModal"
|
||||
>
|
||||
@footer-button-event="closeModal">
|
||||
<div class="recal-modal-body ps-4 pe-4 pt-0 pb-5">
|
||||
<h5 class="mb-4 text-center" v-html="ModalHeadline"></h5>
|
||||
<img :src="ModalImage" class="mw-100 d-flex mx-auto mb-4" alt="" />
|
||||
<p class="fw-bold mb-2 subheader-text" v-html="ModalSubheadertext"></p>
|
||||
<p class="mb-0 small" v-html="ModalBodyText"></p>
|
||||
<h5
|
||||
class="mb-4 text-center"
|
||||
v-html="ModalHeadline"></h5>
|
||||
<img
|
||||
:src="ModalImage"
|
||||
class="mw-100 d-flex mx-auto mb-4"
|
||||
alt="" />
|
||||
<p
|
||||
class="fw-bold mb-2 subheader-text"
|
||||
v-html="ModalSubheadertext"></p>
|
||||
<p
|
||||
class="mb-0 small"
|
||||
v-html="ModalBodyText"></p>
|
||||
<p
|
||||
class="my-4 caption modal-sub-body"
|
||||
v-if="ModalSubBodyText"
|
||||
class="my-4 caption modal-sub-body"
|
||||
v-html="ModalSubBodyText">
|
||||
</p>
|
||||
</div>
|
||||
</modal>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -25,17 +32,12 @@ import modal from '@/digital-components/modal/modal';
|
|||
|
||||
export default {
|
||||
name: 'recal-modal',
|
||||
components: {
|
||||
modal
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName: String
|
||||
},
|
||||
methods: {
|
||||
openModal() {
|
||||
this.$refs[this.ModalName].openModal();
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs[this.ModalName].closeModal();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ModalName() {
|
||||
return this.cmsWidgetName;
|
||||
|
|
@ -59,13 +61,18 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'FooterText');
|
||||
}
|
||||
},
|
||||
components: {
|
||||
modal
|
||||
methods: {
|
||||
openModal() {
|
||||
this.$refs[this.ModalName].openModal();
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs[this.ModalName].closeModal();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
|
||||
.recal-modal-body {
|
||||
.modal-sub-body {
|
||||
|
|
@ -83,6 +90,5 @@ export default {
|
|||
color: $black;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
// Components
|
||||
import entryPage from '@/layouts/entry-page/entry-page.vue';
|
||||
import entryPage from '@/layouts/entry-page/entry-page';
|
||||
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { settleAllPromises } from '@/helpers/layout-helper.js';
|
||||
import { fetchCmsContentForPage, setupModalLinks } from '@/helpers/cms-content-helper';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock('@/helpers/layout-helper.js', () => ({
|
||||
|
|
@ -18,16 +17,6 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
|||
setupModalLinks: jest.fn()
|
||||
}));
|
||||
|
||||
describe('entry-page.vue', () => {
|
||||
test('should render', () => {
|
||||
const queryString = 'policynumber="123456"'
|
||||
const { wrapper } = setupMocks(queryString);
|
||||
|
||||
console.log(wrapper.vm.$route.query);
|
||||
expect(wrapper).toBeTruthy();
|
||||
})
|
||||
});
|
||||
|
||||
function setupMocks(queryString) {
|
||||
const mountOptions = getMountOptions({
|
||||
router: {
|
||||
|
|
@ -36,15 +25,23 @@ function setupMocks(queryString) {
|
|||
route: { queryString }
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(
|
||||
entryPage,
|
||||
mountOptions
|
||||
);
|
||||
const wrapper = shallowMount(entryPage,
|
||||
mountOptions);
|
||||
|
||||
const apiResponses = {};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
fetchCmsContentForPage.mockImplementation (() => {});
|
||||
fetchCmsContentForPage.mockImplementation(() => { });
|
||||
|
||||
return { wrapper };
|
||||
};
|
||||
}
|
||||
|
||||
describe('entry-page.vue', () => {
|
||||
test('should render', () => {
|
||||
const queryString = 'policynumber="123456"';
|
||||
const { wrapper } = setupMocks(queryString);
|
||||
|
||||
console.log(wrapper.vm.$route.query);
|
||||
expect(wrapper).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<p id="message" v-show="unauthorized">Unauthorized Access.</p>
|
||||
<p
|
||||
v-show="unauthorized"
|
||||
id="message">
|
||||
Unauthorized Access.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -10,40 +14,42 @@ import { useMainStore } from '@/store';
|
|||
|
||||
export default {
|
||||
name: 'entry-page',
|
||||
mixins: [],
|
||||
data() {
|
||||
return {
|
||||
unauthorized: false
|
||||
}
|
||||
components: {
|
||||
},
|
||||
mixins: [],
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
mainStore.resetISSConfigState();
|
||||
mainStore.resetPageFields();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
unauthorized: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
mounted() {
|
||||
this.validateClientTagOnEntry();
|
||||
},
|
||||
methods:
|
||||
{
|
||||
navigateForward() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.MOVE_FORWARD_ENTRY_PAGE,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.MOVE_FORWARD_ENTRY_PAGE,
|
||||
this.$route);
|
||||
},
|
||||
parseQueryParms() {
|
||||
// Dump the query string parameters into an array. Remove casing on the key for easy compare.
|
||||
let queryStringParams = [];
|
||||
for (let param in this.$route.query) {
|
||||
const queryStringParams = [];
|
||||
for (const param in this.$route.query) {
|
||||
queryStringParams[param.toLowerCase()] = this.$route.query[param];
|
||||
}
|
||||
return queryStringParams;
|
||||
},
|
||||
async validateClientTagOnEntry() {
|
||||
const queryStringParams = this.parseQueryParms();
|
||||
const clientTag = queryStringParams['clienttag'];
|
||||
const clientTag = queryStringParams.clienttag;
|
||||
const clientTagPresent = !!clientTag;
|
||||
let authorized = false;
|
||||
|
||||
|
|
@ -66,7 +72,7 @@ export default {
|
|||
|
||||
if (authorized) {
|
||||
// Forced full location redirect here. We do not want the entry page as part of the router/flow/path history.
|
||||
window.location = '/?issPage=' + issPageValues.WELCOME_PAGE;
|
||||
window.location = `/?issPage=${issPageValues.WELCOME_PAGE}`;
|
||||
}
|
||||
},
|
||||
populateISSConfigValues(data) {
|
||||
|
|
@ -76,9 +82,9 @@ export default {
|
|||
this.mainStore.issConfig.styleSheet = data.styleSheet;
|
||||
this.mainStore.issConfig.isCoverageEnabled = data.coverageEnabled;
|
||||
|
||||
// NOTE: This is only here for testing purposes. Will be removed and replaced by actual token/signature validation when work is completed.
|
||||
if (data.authentication == 'RSAToken')
|
||||
this.mainStore.issConfig.isAuthenticated = true;
|
||||
// NOTE: This is only here for testing purposes.
|
||||
// Will be removed and replaced by actual token / signature validation when work is completed.
|
||||
if (data.authentication === 'RSAToken') this.mainStore.issConfig.isAuthenticated = true;
|
||||
|
||||
try {
|
||||
if (data.clientFlags) {
|
||||
|
|
@ -97,20 +103,20 @@ export default {
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error parsing client flags: ' + e);
|
||||
console.error(`Error parsing client flags: ${e}`);
|
||||
}
|
||||
},
|
||||
combineClientParameters(configParams, queryStringParams) {
|
||||
let finalParams = [];
|
||||
const finalParams = [];
|
||||
|
||||
try {
|
||||
const clientParams = JSON.parse(configParams);
|
||||
|
||||
for (let cparam in clientParams) {
|
||||
let cname = clientParams[cparam].toLowerCase();
|
||||
for (const cparam in clientParams) {
|
||||
const cname = clientParams[cparam].toLowerCase();
|
||||
|
||||
for (let qsparam in queryStringParams) {
|
||||
let qsname = qsparam.toLowerCase();
|
||||
for (const qsparam in queryStringParams) {
|
||||
const qsname = qsparam.toLowerCase();
|
||||
|
||||
if (cname === qsname) {
|
||||
finalParams[cname] = queryStringParams[cname];
|
||||
|
|
@ -118,16 +124,16 @@ export default {
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error combining client parameters: ' + e);
|
||||
console.error(`Error combining client parameters: ${e}`);
|
||||
}
|
||||
|
||||
return finalParams;
|
||||
},
|
||||
populateStoreItemsFromParams(params) {
|
||||
// Populate store items from parameters.
|
||||
for (let param in params) {
|
||||
let name = param.toLowerCase();
|
||||
let value = params[param];
|
||||
for (const param in params) {
|
||||
const name = param.toLowerCase();
|
||||
const value = params[param];
|
||||
|
||||
switch (name) {
|
||||
case 'policynumber':
|
||||
|
|
@ -158,18 +164,15 @@ export default {
|
|||
case 'token':
|
||||
case 'signature':
|
||||
break;
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
},
|
||||
components: {
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
#message {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Components
|
||||
import licensePlateLookup from '@/layouts/license-plate-lookup/license-plate-lookup.vue';
|
||||
import licensePlateLookup from '@/layouts/license-plate-lookup/license-plate-lookup';
|
||||
|
||||
// Supporting Files
|
||||
import { settleAllPromises } from '@/helpers/layout-helper.js';
|
||||
|
|
@ -23,6 +23,83 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
|||
fetchCmsContentForPage: jest.fn()
|
||||
}));
|
||||
|
||||
function setupMocks({
|
||||
isZipValid = true,
|
||||
isZipServiceable = true,
|
||||
lookupVinByPlateResponse,
|
||||
partsOrQuestions = [],
|
||||
vehicle = {},
|
||||
vin = null,
|
||||
carId = 'C0000',
|
||||
vinLookupResponseError = null,
|
||||
route = null
|
||||
}) {
|
||||
useMainStore().validateZip = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: {
|
||||
isValid: isZipValid,
|
||||
isServiceable: isZipServiceable
|
||||
}
|
||||
}));
|
||||
|
||||
useMainStore().lookupVinByPlate = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: lookupVinByPlateResponse || {
|
||||
vin: 'TEST_VIN',
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
useMainStore().getPartsOrQuestions = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: {
|
||||
partsOrQuestions
|
||||
}
|
||||
}));
|
||||
|
||||
const wrapper = shallowMount(licensePlateLookup,
|
||||
getMountOptions({
|
||||
route: route || undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId,
|
||||
registration: {
|
||||
licensePlate: 'TESTPLATE',
|
||||
zipCode: '12345'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}));
|
||||
|
||||
const apiResponses = {
|
||||
serviceZipValidationResponse: {
|
||||
isValid: isZipValid,
|
||||
isServiceable: isZipServiceable
|
||||
},
|
||||
vinLookupResponse: {
|
||||
vin,
|
||||
vehicle,
|
||||
error: vinLookupResponseError
|
||||
}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.enableForwardButton = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
describe('license-plate-lookup.vue', () => {
|
||||
describe('page level alerts', () => {
|
||||
test('If license plate matches a different vehicle, display MatchedDifferentVehicleAlert', async () => {
|
||||
|
|
@ -43,9 +120,7 @@ describe('license-plate-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedDifferentVehicle' }).isVisible()).toBe(
|
||||
true
|
||||
);
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedDifferentVehicle' }).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
test('If license plate matches two identical YMM vehicles, display alertMatchedTwoIdenticalYMMVehicle', async () => {
|
||||
|
|
@ -67,9 +142,7 @@ describe('license-plate-lookup.vue', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(
|
||||
true
|
||||
);
|
||||
expect(wrapper.findComponent({ ref: 'alertMatchedTwoIdenticalYMMVehicle' }).isVisible()).toBe(true);
|
||||
});
|
||||
|
||||
test('If no vehicles found, display VinNotFound alert', async () => {
|
||||
|
|
@ -101,7 +174,7 @@ describe('license-plate-lookup.vue', () => {
|
|||
describe('navigation', () => {
|
||||
test('Clicking back button navigates back', async () => {
|
||||
// Arrange
|
||||
const { wrapper, apiPromise } = setupMocks({
|
||||
const { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
|
|
@ -109,12 +182,10 @@ describe('license-plate-lookup.vue', () => {
|
|||
}
|
||||
});
|
||||
// Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
licensePlateLookup.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'license-plate-lookup' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
await wrapper.vm.backButtonAction();
|
||||
|
||||
// Assert
|
||||
|
|
@ -155,7 +226,7 @@ describe('license-plate-lookup.vue', () => {
|
|||
|
||||
useMainStore().order.vehicle.carId = 'CARID';
|
||||
|
||||
let carsFound = [
|
||||
const carsFound = [
|
||||
{
|
||||
vin: 'TEST_VIN2',
|
||||
vehicle: {
|
||||
|
|
@ -168,12 +239,10 @@ describe('license-plate-lookup.vue', () => {
|
|||
await wrapper.vm.navigateForward(carsFound);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
undefined,
|
||||
{},
|
||||
{ displayVehicleChangeAlert: true }
|
||||
);
|
||||
{ displayVehicleChangeAlert: true });
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -184,103 +253,15 @@ describe('license-plate-lookup.vue', () => {
|
|||
useMainStore().order.vehicle.carId = 'CR00000395';
|
||||
|
||||
// Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
licensePlateLookup.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'license-plate-lookup' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
||||
// Assert
|
||||
expect(arePagePrerequisitesValid).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
isZipValid = true,
|
||||
isZipServiceable = true,
|
||||
lookupVinByPlateResponse,
|
||||
partsOrQuestions = [],
|
||||
vehicle = {},
|
||||
vin = null,
|
||||
carId = 'C0000',
|
||||
vinLookupResponseError = null,
|
||||
route = null
|
||||
}) {
|
||||
useMainStore().validateZip = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
isValid: isZipValid,
|
||||
isServiceable: isZipServiceable
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useMainStore().lookupVinByPlate = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: lookupVinByPlateResponse
|
||||
? lookupVinByPlateResponse : {
|
||||
vin: 'TEST_VIN',
|
||||
vehicle: {
|
||||
carId: 'CARID'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
useMainStore().getPartsOrQuestions = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: {
|
||||
partsOrQuestions: partsOrQuestions
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const wrapper = shallowMount(
|
||||
licensePlateLookup,
|
||||
getMountOptions({
|
||||
route: route ? route : undefined,
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
mainStore: {
|
||||
order: {
|
||||
vehicle: {
|
||||
carId: carId,
|
||||
registration: {
|
||||
licensePlate: 'TESTPLATE',
|
||||
zipCode: '12345'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
);
|
||||
|
||||
const apiResponses = {
|
||||
serviceZipValidationResponse: {
|
||||
isValid: isZipValid,
|
||||
isServiceable: isZipServiceable
|
||||
},
|
||||
vinLookupResponse: {
|
||||
vin: vin,
|
||||
vehicle: vehicle,
|
||||
error: vinLookupResponseError
|
||||
}
|
||||
};
|
||||
|
||||
settleAllPromises.mockImplementation(() => apiResponses);
|
||||
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => '');
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.updateButtonText = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.disableForwardButton = jest.fn();
|
||||
wrapper.vm.$refs.siteFooter.enableForwardButton = jest.fn();
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -8,57 +12,60 @@
|
|||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner class="mt-2 mb-4" cms-widget-name="VehicleBannerWidget" :display-generic-vehicle-image="false" />
|
||||
<siteSubHeader cms-widget-name="SiteSubHeaderWidget" />
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
ref="alertVinNotFound"
|
||||
v-if="displayVinNotFoundAlert"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayVinNotFoundAlert"
|
||||
ref="alertVinNotFound"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayMatchedDifferentVehicleAlert"
|
||||
ref="alertMatchedDifferentVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<alert
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false" />
|
||||
v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
|
||||
ref="alertMatchedTwoIdenticalYMMVehicle"
|
||||
class="mb-4"
|
||||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
|
||||
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<textboxQuestion
|
||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||
v-model="licensePlate"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
id="license-plate-question-wrapper"
|
||||
inputId="license-plate-question"
|
||||
validationRules="license-plate-required" />
|
||||
id="license-plate-question-wrapper"
|
||||
v-model="licensePlate"
|
||||
cmsWidgetName="LicensePlateNumberQuestionWidget"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
inputId="license-plate-question"
|
||||
validationRules="license-plate-required" />
|
||||
<dropdownQuestion
|
||||
cmsWidgetName="StateQuestionWidget"
|
||||
v-model="licenseState"
|
||||
ref="state"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="stateOptions"
|
||||
disableAutoFill
|
||||
validationRules="state-required"
|
||||
class="mt-4 mb-2"/>
|
||||
ref="state"
|
||||
v-model="licenseState"
|
||||
cmsWidgetName="StateQuestionWidget"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="stateOptions"
|
||||
disableAutoFill
|
||||
validationRules="state-required"
|
||||
class="mt-4 mb-2" />
|
||||
<siteFooter
|
||||
class="mt-5"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
cms-widget-name="SiteFooterWidget"
|
||||
@back-clicked="backButtonAction"
|
||||
@forward-clicked="forwardButtonAction"
|
||||
ref="siteFooter" />
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
@back-clicked="backButtonAction"
|
||||
@forward-clicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -75,21 +82,21 @@ import { settleAllPromises } from '@/helpers/layout-helper';
|
|||
import { useMainStore } from '@/store';
|
||||
import { errorMessages } from '@/constants/error-messages';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { defineRule, Form } from 'vee-validate';
|
||||
import { getDamageString, isGlassAvailableForCarId } from '@/helpers/damage-helper.js';
|
||||
import { routerParams } from '@/router/router-params.js'
|
||||
import { routerParams } from '@/router/router-params.js';
|
||||
import { states } from '@/constants/states';
|
||||
|
||||
// Import Component
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import vinPagesMixin from '@/mixins/vin-pages-mixin';
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import siteHeader from '@/iss-components/site-header/site-header';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
|
||||
// Define Validation Rules
|
||||
|
|
@ -98,6 +105,17 @@ defineRule('state-required', required(errorMessages.STATE_REQUIRED));
|
|||
|
||||
export default {
|
||||
name: 'license-plate-lookup',
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
alert
|
||||
},
|
||||
mixins: [baseFormMixin, vinPagesMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -134,6 +152,56 @@ export default {
|
|||
forwardButtonCarStyle: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
AlertMatchedDifferentVehicleHeader() {
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget',
|
||||
'HeadlineText').replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedDifferentVehicleBody() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader() {
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText').replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleBody() {
|
||||
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
|
||||
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
},
|
||||
stateOptions: {
|
||||
get() {
|
||||
return states;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
licensePlate() {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
},
|
||||
registrationZipCode() {
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
this.loadDefaultsFromStore();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return this.mainStore.order.vehicle.carId !== null;
|
||||
|
|
@ -147,12 +215,10 @@ export default {
|
|||
},
|
||||
attachCustomEvents() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.pushEventToGA(this.$route.query[this.queryStrings.ISS_PAGE],
|
||||
this.GaActions.SUBMITTED,
|
||||
this.GaLabels.LICENSE_PLATE_LOOKUP,
|
||||
true
|
||||
);
|
||||
true);
|
||||
});
|
||||
},
|
||||
// NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
|
||||
|
|
@ -160,8 +226,7 @@ export default {
|
|||
this.resetWarningsAndErrors();
|
||||
|
||||
// Lookup VIN
|
||||
const vinLookupResponse = await useMainStore().lookupVinByPlate(
|
||||
this.licensePlate, this.licenseState);
|
||||
const vinLookupResponse = await useMainStore().lookupVinByPlate(this.licensePlate, this.licenseState);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
|
|
@ -178,33 +243,31 @@ export default {
|
|||
this.displayVinNotFoundAlert = true;
|
||||
this.$refs.siteFooter.disableForwardButton();
|
||||
return this.$refs.siteFooter.removeLoader();
|
||||
};
|
||||
}
|
||||
|
||||
// Vehicle found from VIN lookup
|
||||
const vehicleFromLookup = resultMap.vinLookupResponse.vehicle;
|
||||
|
||||
// Check if the CarId has changed
|
||||
this.isCarIdDifferent =
|
||||
vehicleFromLookup.carId !== useMainStore().order.vehicle.carId;
|
||||
this.isCarIdDifferent
|
||||
= vehicleFromLookup.carId !== useMainStore().order.vehicle.carId;
|
||||
// Handle changing car
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
vehicleFromLookup.carId !== this.previouslyEnteredCarId
|
||||
this.isCarIdDifferent
|
||||
&& vehicleFromLookup.carId !== this.previouslyEnteredCarId
|
||||
) {
|
||||
// Display Alert
|
||||
this.previouslyEnteredCarId = vehicleFromLookup.carId;
|
||||
this.customAlertData.vehicleInfo = vehicleFromLookup;
|
||||
|
||||
if (this.isTwoIdenticalYMMVehicleFound){
|
||||
if (this.isTwoIdenticalYMMVehicleFound) {
|
||||
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
|
||||
this.forwardButtonCarStyle= vehicleFromLookup.style;
|
||||
this.forwardButtonCarStyle = vehicleFromLookup.style;
|
||||
} else {
|
||||
this.displayMatchedDifferentVehicleAlert = true;
|
||||
}
|
||||
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
|
||||
vehicleFromLookup.carId
|
||||
);
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleFromLookup.carId);
|
||||
|
||||
// Update button "Continue with..."
|
||||
this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`);
|
||||
|
|
@ -212,17 +275,15 @@ export default {
|
|||
}
|
||||
|
||||
// Save vehicle, license plate, and registration information
|
||||
await useMainStore().saveRegistrationLicensePlateLookup(
|
||||
{
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, { vin: vinLookupResponse.data.vin }),
|
||||
registrationInfo: {
|
||||
licensePlate: this.licensePlate,
|
||||
state: this.licenseState
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
await useMainStore().saveRegistrationLicensePlateLookup({
|
||||
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
|
||||
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, { vin: vinLookupResponse.data.vin }),
|
||||
registrationInfo: {
|
||||
licensePlate: this.licensePlate,
|
||||
state: this.licenseState
|
||||
}
|
||||
},
|
||||
false);
|
||||
|
||||
return await this.navigateForward();
|
||||
},
|
||||
|
|
@ -230,12 +291,10 @@ export default {
|
|||
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage"
|
||||
// display vehicle changed alert on that page.
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true });
|
||||
} else {
|
||||
await this.navigateForwardWithSingleCarMatch();
|
||||
}
|
||||
|
|
@ -244,79 +303,11 @@ export default {
|
|||
this.displayVinNotFoundAlert = false;
|
||||
this.displayMatchedDifferentVehicleAlert = false;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
this.loadDefaultsFromStore();
|
||||
},
|
||||
computed: {
|
||||
AlertMatchedDifferentVehicleHeader() {
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedDifferentVehicleWidget',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedDifferentVehicleBody() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedDifferentVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmFound}', vinYmmFound)
|
||||
.replaceAll('{custom:vinYmmExpected}', vinYmmExpected);
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleHeader() {
|
||||
return this.getCmsContent(
|
||||
'AlertMatchedTwoIdenticalYMMVehicleWidget',
|
||||
'HeadlineText'
|
||||
).replaceAll('{custom:damage}', getDamageString());
|
||||
},
|
||||
AlertMatchedTwoIdenticalYMMVehicleBody() {
|
||||
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
|
||||
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
|
||||
|
||||
return this.getCmsContent('AlertMatchedTwoIdenticalYMMVehicleWidget', 'BodyText')
|
||||
.replaceAll('{custom:damage}', getDamageString())
|
||||
.replaceAll('{custom:vinYmmsFound}', vinYmmsFound)
|
||||
.replaceAll('{custom:vinYmmsExpected}', vinYmmsExpected);
|
||||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
|
||||
},
|
||||
stateOptions: {
|
||||
get: function () {
|
||||
return states;
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
licensePlate() {
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
},
|
||||
registrationZipCode() {
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Form,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
alert
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
#license-plate-question-wrapper .form-test-error {
|
||||
/**
|
||||
Override extra margin-bottom in the error message in TextboxQuestion
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ import moldingQuestions from '@/layouts/molding-questions/molding-questions';
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import baseMixin from '../../mixins/base-mixin';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { nextTick } from 'vue';
|
||||
import baseMixin from '@/mixins/base-mixin';
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock('@/helpers/layout-helper.js', () => ({
|
||||
|
|
@ -19,79 +19,136 @@ jest.mock('@/helpers/cms-content-helper', () => ({
|
|||
fetchCmsContentForPage: jest.fn()
|
||||
}));
|
||||
|
||||
const baseStoreGettersPageData = () => {
|
||||
return {
|
||||
partsOrQuestions: [
|
||||
function setupMocks({
|
||||
mountOptionsMockData = {
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
actionList: [
|
||||
{
|
||||
parts: [
|
||||
{
|
||||
childPartQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
'Does the rubber seal around your windshield have a chrome strip running through it?',
|
||||
answers: [
|
||||
{
|
||||
answerResult: 'WKT D1106 C',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: null
|
||||
},
|
||||
{
|
||||
answerResult: 'WKT D1106 B',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
basePartNumber: 'DW01105',
|
||||
color: 'Green Tint, Blue Shade',
|
||||
requiresRecalibration: false,
|
||||
recalibrationType: '',
|
||||
canSafeliteRecalibrate: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
partNumber: 'DW01105GBNN',
|
||||
description: 'solar',
|
||||
partType: 'WINDSHIELD'
|
||||
}
|
||||
],
|
||||
partQuestions: [],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
actionName: 'saveMoldingQuestionAnswers',
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
actionName: 'getPartsOrQuestions',
|
||||
data: {}
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
const baseStoreGettersDamage = () => {
|
||||
return {
|
||||
partsQuestionAnswers: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
result: 'FW04848',
|
||||
answeredQuestions: [
|
||||
],
|
||||
route: {
|
||||
query: {
|
||||
issPage: 'molding-questions'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedSwitcher: [
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?',
|
||||
selectedAnswer: '1|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?',
|
||||
selectedAnswer: '2|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerData: {
|
||||
answerResult: 'FW04848',
|
||||
answeredQuestions: []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
questionsData: {
|
||||
get() {
|
||||
return this.computedSwitcher;
|
||||
},
|
||||
set(val) {
|
||||
this.computedSwitcher = val;
|
||||
}
|
||||
]
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
}) {
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
|
||||
const mountOptions = getMountOptions({
|
||||
...mountOptionsMockData,
|
||||
mixins: [baseMixin, vehicleQuestionsMixin]
|
||||
});
|
||||
mountOptions.attachTo = document.body;
|
||||
|
||||
const wrapper = shallowMount(moldingQuestions, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
const baseStoreGettersPageData = () => ({
|
||||
partsOrQuestions: [
|
||||
{
|
||||
parts: [
|
||||
{
|
||||
childPartQuestions: [
|
||||
{
|
||||
questionSequence: 1,
|
||||
questionText:
|
||||
'Does the rubber seal around your windshield have a chrome strip running through it?',
|
||||
answers: [
|
||||
{
|
||||
answerResult: 'WKT D1106 C',
|
||||
answerText: 'Yes',
|
||||
nextQuestionSequence: null
|
||||
},
|
||||
{
|
||||
answerResult: 'WKT D1106 B',
|
||||
answerText: 'No',
|
||||
nextQuestionSequence: null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
basePartNumber: 'DW01105',
|
||||
color: 'Green Tint, Blue Shade',
|
||||
requiresRecalibration: false,
|
||||
recalibrationType: '',
|
||||
canSafeliteRecalibrate: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
partNumber: 'DW01105GBNN',
|
||||
description: 'solar',
|
||||
partType: 'WINDSHIELD'
|
||||
}
|
||||
],
|
||||
partQuestions: [],
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerKey: 'Windshield-Single',
|
||||
answerData: null
|
||||
}
|
||||
]
|
||||
});
|
||||
const baseStoreGettersDamage = () => ({
|
||||
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?',
|
||||
selectedAnswer: '1|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 1
|
||||
},
|
||||
{
|
||||
questionText:
|
||||
'Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?',
|
||||
selectedAnswer: '2|nextQuestion|3|Yes',
|
||||
selectedAnswerText: 'Yes',
|
||||
questionNum: 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
useMainStore().pageData = baseStoreGettersPageData;
|
||||
useMainStore().damage = baseStoreGettersDamage;
|
||||
|
|
@ -114,9 +171,7 @@ describe('moldingQuestions.vue', () => {
|
|||
test('Should return false for valid page requisites if partsOrQuestions in pageData is missing', () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
useMainStore().pageData = jest.fn(() => {
|
||||
return undefined;
|
||||
});
|
||||
useMainStore().pageData = jest.fn(() => undefined);
|
||||
|
||||
// Act
|
||||
const result = wrapper.vm.arePagePrerequisitesValid();
|
||||
|
|
@ -129,11 +184,9 @@ describe('moldingQuestions.vue', () => {
|
|||
|
||||
test('Should be at least one item in partsOrQuestions', () => {
|
||||
// Arrange
|
||||
useMainStore().pageData = jest.fn(() => {
|
||||
return {
|
||||
partsOrQuestions: []
|
||||
};
|
||||
});
|
||||
useMainStore().pageData = jest.fn(() => ({
|
||||
partsOrQuestions: []
|
||||
}));
|
||||
useMainStore().damage = baseStoreGettersDamage;
|
||||
|
||||
const { wrapper } = setupMocks({});
|
||||
|
|
@ -207,13 +260,11 @@ describe('moldingQuestions.vue', () => {
|
|||
}
|
||||
}
|
||||
];
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
wrapper.vm.dispatchStoreAction = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -238,13 +289,11 @@ describe('moldingQuestions.vue', () => {
|
|||
}
|
||||
}
|
||||
];
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -270,13 +319,11 @@ describe('moldingQuestions.vue', () => {
|
|||
}
|
||||
}
|
||||
];
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
|
||||
// Act
|
||||
wrapper.vm.forwardButtonAction();
|
||||
|
|
@ -303,13 +350,11 @@ describe('moldingQuestions.vue', () => {
|
|||
}
|
||||
}
|
||||
];
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => ({
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
}));
|
||||
wrapper.vm.navigateForward = jest.fn();
|
||||
|
||||
// Act
|
||||
|
|
@ -322,66 +367,3 @@ describe('moldingQuestions.vue', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
mountOptionsMockData = {
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
},
|
||||
actionList: [
|
||||
{
|
||||
actionName: 'saveMoldingQuestionAnswers',
|
||||
data: {}
|
||||
},
|
||||
{
|
||||
actionName: 'getPartsOrQuestions',
|
||||
data: {}
|
||||
}
|
||||
],
|
||||
route: {
|
||||
query: {
|
||||
issPage: 'molding-questions'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
computedSwitcher: [
|
||||
{
|
||||
glassLocation: 'Windshield',
|
||||
glassName: 'Single',
|
||||
answerData: {
|
||||
answerResult: 'FW04848',
|
||||
answeredQuestions: []
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
questionsData: {
|
||||
get() {
|
||||
return this.computedSwitcher;
|
||||
},
|
||||
set(val) {
|
||||
this.computedSwitcher = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}) {
|
||||
useMainStore().getPartsOrQuestions = jest.fn(() => {
|
||||
return {
|
||||
data: {
|
||||
partsOrQuestions: []
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const mountOptions = getMountOptions({
|
||||
...mountOptionsMockData,
|
||||
mixins: [baseMixin, vehicleQuestionsMixin]
|
||||
});
|
||||
mountOptions['attachTo'] = document.body;
|
||||
|
||||
const wrapper = shallowMount(moldingQuestions, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,22 @@
|
|||
<template>
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit"
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
>
|
||||
@submit="onSubmit"
|
||||
@invalidSubmit="onInvalidSubmit">
|
||||
<questionsPageLayout
|
||||
isRequired
|
||||
id="molding-question-wrapper"
|
||||
ref="questionsPageLayout"
|
||||
v-model="selectedAnswers"
|
||||
isRequired
|
||||
:isMetaValid="meta.valid"
|
||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||
:questionsData="questionsData"
|
||||
:validationRules="rules.optionRequired"
|
||||
v-model="selectedAnswers"
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@back-click="navigateBack"
|
||||
:index="currentGlassIndex"
|
||||
id="molding-question-wrapper"
|
||||
/>
|
||||
@forwardButtonAction="forwardButtonAction"
|
||||
@back-click="navigateBack" />
|
||||
</Form>
|
||||
</template>
|
||||
<script>
|
||||
|
|
@ -33,10 +31,15 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
|||
|
||||
// Import Component
|
||||
import { Form } from 'vee-validate';
|
||||
import questionsPageLayout from '@/iss-components/questions-page-layout/questions-page-layout.vue';
|
||||
import questionsPageLayout from '@/iss-components/questions-page-layout/questions-page-layout';
|
||||
|
||||
export default {
|
||||
name: 'molding-questions',
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
questionsPageLayout
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
|
@ -67,10 +70,8 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
AlertFewMoreQuestionsHeader() {
|
||||
return this.getCmsContent(
|
||||
'AdditionalPartsQuestionsAlert',
|
||||
'HeadlineText'
|
||||
);
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert',
|
||||
'HeadlineText');
|
||||
},
|
||||
AlertFewMoreQuestionsCopy() {
|
||||
return this.getCmsContent('AdditionalPartsQuestionsAlert', 'BodyText');
|
||||
|
|
@ -85,62 +86,48 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
const moldingQuestionsFromPageData = useMainStore().pageData(
|
||||
issPageValues.MOLDING_QUESTIONS
|
||||
);
|
||||
const moldingQuestionsFromPageData = useMainStore().pageData(issPageValues.MOLDING_QUESTIONS);
|
||||
return (
|
||||
// has childPartQuestions array and has glassName not null
|
||||
moldingQuestionsFromPageData?.partsOrQuestions?.some(
|
||||
(part) => part?.glassName
|
||||
) &&
|
||||
moldingQuestionsFromPageData.partsOrQuestions.some((glass) =>
|
||||
glass.parts?.some((part) => part?.childPartQuestions?.length > 0)
|
||||
)
|
||||
moldingQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)
|
||||
&& moldingQuestionsFromPageData.partsOrQuestions.some((glass) => glass.parts?.some((part) => part?.childPartQuestions?.length > 0))
|
||||
);
|
||||
},
|
||||
getInitialQuestionData() {
|
||||
// get any questions that were already answered
|
||||
const alreadyAnsweredQuestions =
|
||||
useMainStore().damage.moldingQuestionAnswers;
|
||||
const alreadyAnsweredQuestions
|
||||
= useMainStore().damage.moldingQuestionAnswers;
|
||||
this.questionsData = this.partsOrQuestionsData
|
||||
.filter((x) => x.parts[0].childPartQuestions.length)
|
||||
.map((glass, index) => {
|
||||
// NOTE: questions for property "questions" can differ between layouts
|
||||
glass.questions = glass.parts[0].childPartQuestions;
|
||||
glass.answerKey = glass.glassLocation + '-' + glass.glassName;
|
||||
glass.answerKey = `${glass.glassLocation}-${glass.glassName}`;
|
||||
// reset selectedAnswers for this glass
|
||||
this.selectedAnswers[glass.answerKey] = [];
|
||||
const updatedGlass = this.setupInitialData(
|
||||
glass,
|
||||
const updatedGlass = this.setupInitialData(glass,
|
||||
index,
|
||||
alreadyAnsweredQuestions
|
||||
);
|
||||
alreadyAnsweredQuestions);
|
||||
// Set up watch for each set of glass questions
|
||||
this.$watch(
|
||||
'selectedAnswers.' + glass.answerKey,
|
||||
this.$watch(`selectedAnswers.${glass.answerKey}`,
|
||||
(newValue) => {
|
||||
if (newValue && Object.keys(newValue).length > 0) {
|
||||
this.handleAnswerUpdates(
|
||||
newValue,
|
||||
glass.answerKey
|
||||
);
|
||||
this.handleAnswerUpdates(newValue,
|
||||
glass.answerKey);
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
{ deep: true });
|
||||
return updatedGlass;
|
||||
});
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const questionAnswersArray = this.questionsData.map((glass) => {
|
||||
return {
|
||||
glassLocation: glass.glassLocation,
|
||||
glassName: glass.glassName,
|
||||
partNum: glass.answerData.answerResult,
|
||||
answeredQuestions: glass.answerData.answeredQuestions,
|
||||
isSuppressedPart: glass.isSuppressedPart
|
||||
};
|
||||
});
|
||||
const questionAnswersArray = this.questionsData.map((glass) => ({
|
||||
glassLocation: glass.glassLocation,
|
||||
glassName: glass.glassName,
|
||||
partNum: glass.answerData.answerResult,
|
||||
answeredQuestions: glass.answerData.answeredQuestions,
|
||||
isSuppressedPart: glass.isSuppressedPart
|
||||
}));
|
||||
// clear out answerData for future page loads; must occur prior to store save
|
||||
this.questionsData.forEach((glass) => {
|
||||
glass.answerData = {};
|
||||
|
|
@ -149,14 +136,12 @@ export default {
|
|||
await this.mainStore.saveMoldingQuestionAnswers(questionAnswersArray);
|
||||
|
||||
// get parts from the questionAnswers
|
||||
let partsOrQuestions = this.partsOrQuestionsData;
|
||||
for (let answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => {
|
||||
return (
|
||||
partOrQuestion.glassLocation === answer.glassLocation &&
|
||||
partOrQuestion.glassName === answer.glassName
|
||||
);
|
||||
}).parts[0].childParts = [
|
||||
const partsOrQuestions = this.partsOrQuestionsData;
|
||||
for (const answer of questionAnswersArray) {
|
||||
partsOrQuestions.find((partOrQuestion) => (
|
||||
partOrQuestion.glassLocation === answer.glassLocation
|
||||
&& partOrQuestion.glassName === answer.glassName
|
||||
)).parts[0].childParts = [
|
||||
{
|
||||
partNumber: answer.partNum
|
||||
}
|
||||
|
|
@ -165,15 +150,11 @@ export default {
|
|||
|
||||
this.navigateForward(partsOrQuestions, null);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Form,
|
||||
questionsPageLayout
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
#molding-question-wrapper p.text-body.small {
|
||||
margin-bottom: 0 !important; // Overrides extra margin-bottom on alert body text
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2">
|
||||
<p>Placeholder for order confirmation page</p>
|
||||
<siteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
/>
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -26,8 +29,15 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|||
import { settleAllPromises } from '@/helpers/layout-helper';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
|
||||
export default {
|
||||
name: 'order-confirmation',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -39,7 +49,7 @@ export default {
|
|||
promise: cmsContentPromise
|
||||
}];
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
|
|
@ -53,16 +63,9 @@ export default {
|
|||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue