Unit tests

This commit is contained in:
FrankRua 2022-06-30 17:25:34 -04:00
parent ec05b56e51
commit 3929c90954
24 changed files with 526 additions and 930 deletions

View file

@ -1,7 +1,10 @@
const storeActions = {
// Content Actions
GET_ROUTE_INFO_ACTION: "getRouteInfo",
GET_HOMEPAGE_NAME: "getHomepageName",
GET_PAGE_DATA: "getPageData",
// Vehicle Actions
GET_VEHICLE_YEARS: "getVehicleYears",
GET_VEHICLE_MAKES: "getVehicleMakes",
GET_VEHICLE_MODELS: "getVehicleModels",
@ -9,10 +12,13 @@ const storeActions = {
SET_VEHICLE: "setVehicle",
GET_DAMAGE_OPTIONS: "getDamageOptions",
GET_EVOX_IMAGE: "getEvoxImage",
// Lookup Actions
LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms",
LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin",
LOOKUP_VIN_BY_PLATE: "lookupVinByPlate",
LOOKUP_VIN_BY_ADDRESS: "lookupVinByAddress",
GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions",
SAVE_ORDER: "saveOrder",
LOAD_ORDER: "loadOrder",
@ -23,8 +29,8 @@ const storeActions = {
LOG_CUSTOM_EVENT: "logCustomEvent",
INITIALIZE_SESSION: "initializeSession",
GET_EXPERIMENTS_BY_USER: "GetExperimentsByUser",
UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION: "updateServiceLocationWithVehicleRegistration",
UPDATE_VEHICLE_INFO: 'updateVehicleInfo',
CLEAR_VIN: "clearVin",
// DEPENDENCY MUTATIONS
RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleAndDependencies",
@ -33,7 +39,7 @@ const storeActions = {
RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies",
RESET_STATE: "resetState",
//RESET COMPONENT STATE
// SAVE COMPONENT STATE
SAVE_VEHICLE_YEAR: "saveVehicleYear",
SAVE_VEHICLE_MAKE:"saveVehicleMake",
SAVE_VEHICLE_MODEL:"saveVehicleModel",
@ -44,8 +50,7 @@ const storeActions = {
SAVE_EMAIL: "saveEmail",
SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: "saveRegistrationLicensePlateLookup",
SAVE_VIN: "saveVin",
SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup",
SAVE_PARTS_QUESTION_ANSWERS: "savePartQuestionAnswers",
SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup",
SAVE_GLASS_PARTS: "saveGlassParts",
};

View file

@ -53,7 +53,6 @@ const storeMutations = {
// OTHER MUTATIONS
UPDATE_PAGE_DATA: "updatePageData",
UPDATE_STATE_WITH_ORDER_INFORMATION: "updateStateWithOrderInformation",
UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION: "updateServiceLocationWithVehicleRegistration"
};
export { storeMutations };

View file

@ -320,7 +320,7 @@ describe("address-lookup.vue", () => {
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, undefined, {}, {}, carsFound);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, undefined, {}, {}, carsFound);
});
test("if the car entered matches one of the vehicles found but the zip is NOT serviceable, do not navigate forward", async () => {
@ -419,7 +419,7 @@ describe("address-lookup.vue", () => {
await wrapper.vm.navigateForward(carEntered, carsFound);
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, undefined, {}, { "displayVehicleChangeAlert": true }, {});
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, undefined, {}, { "displayVehicleChangeAlert": true }, {});
});
@ -486,25 +486,6 @@ describe("address-lookup.vue", () => {
});
});
describe("resetting dependent state", () => {
test("when reseting dependent state, license plate is set to null and parts state and dependencies are reset", async () => {
// Arrange
const commitSpy = jest.spyOn(store, "commit");
const dispatchSpy = jest.spyOn(store, "dispatch");
const { wrapper } = setupMocks({
isZipServiceable: true
});
// Act
wrapper.vm.resetDependentState();
// Assert
expect(commitSpy).toBeCalledWith(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, null);
expect(dispatchSpy).toBeCalledWith(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
});
});
describe("registration and service zips", () => {
describe("if registration zip is serviceable", () => {
test("if registration address is provided => update service address on successful continue", async () => {
@ -728,7 +709,25 @@ function setupMocks({ isZipServiceable = true, lookupVinbyAddressResponse, parts
],
router: {
navigate: jest.fn(),
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
store: {
getters: {
vehicle: {
registration: {
licensePlate: "TESTPLATE",
zipCode: "12345"
}
},
order: {
customer: {
emailAddress: "test@test.com"
},
serviceLocation: {
zipCode: "11111"
}
}
}
},
}));

View file

@ -1,67 +1,32 @@
<template>
<Form
@submit="onSubmit"
@invalid-submit="onInvalidSubmit"
ref="theForm"
v-slot="{ meta }"
autocomplete="off" >
<div class="page-container-grouped-styles">
<loadingModal ref="loadingModal"/>
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
<vehicleBanner cmsWidgetName="VehicleBannerWidget" ref="vehicleBanner" :displayGenericVehicleImage=false />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
<div class="fade-on-route-transition sub-container make-tall">
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
<alert ref="alertVinNotFound" v-if="displayVinNotFoundAlert"
class="mb-4"
cmsWidgetName="AlertVinNotFoundWidget"
alertClass="alert-danger"
v-bind:isDismissible="false"
/>
<alert ref="alertMatchedDifferentVehicle" v-if="displayMatchedDifferentVehicleAlert"
class="mb-4"
:manualHeadline="AlertMatchedDifferentVehicleHeader"
:manualCopy="AlertMatchedDifferentVehicleBody"
alertClass="alert-warning"
v-bind:isDismissible="false"
/>
<alert ref="alertNonServiceableZip" v-if="displayNonServiceableZipAlert"
class="mb-4"
alertClass="alert-danger"
:manualHeadline="AlertNonServiceableZipHeader"
:manualCopy="AlertNonServiceableZipBody"
v-bind:isDismissible="false"
/>
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-if="displayVinLookupByHomeAddressNotAllowedAlert"
class="mb-4"
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
alertClass="alert-danger"
v-bind:isDismissible="false"
/>
<transition name="fade" mode="out-in">
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
<div class="row mb-4">
<div class="col">
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZipCode" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" validationRules="service-zip-required|service-zip-format" />
</div>
</div>
</div>
</transition>
<funnel-footer
cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter"
:isDisabled="!meta.valid"
@ForwardClicked="forwardButtonAction"
@back-clicked="backButtonAction"
:isForwardActionDisabled="!meta.valid"
/>
</div>
</div>
</Form>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" autocomplete="off">
<div class="page-container-grouped-styles">
<loadingModal ref="loadingModal" />
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
<vehicleBanner cmsWidgetName="VehicleBannerWidget" ref="vehicleBanner" :displayGenericVehicleImage=false />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
<div class="fade-on-route-transition sub-container make-tall">
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
<alert ref="alertVinNotFound" v-if="displayVinNotFoundAlert" class="mb-4" cmsWidgetName="AlertVinNotFoundWidget" alertClass="alert-danger" v-bind:isDismissible="false" />
<alert ref="alertMatchedDifferentVehicle" v-if="displayMatchedDifferentVehicleAlert" class="mb-4" :manualHeadline="AlertMatchedDifferentVehicleHeader" :manualCopy="AlertMatchedDifferentVehicleBody" alertClass="alert-warning" v-bind:isDismissible="false" />
<alert ref="alertNonServiceableZip" v-if="displayNonServiceableZipAlert" class="mb-4" alertClass="alert-danger" :manualHeadline="AlertNonServiceableZipHeader" :manualCopy="AlertNonServiceableZipBody" v-bind:isDismissible="false" />
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-if="displayVinLookupByHomeAddressNotAllowedAlert" class="mb-4" cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget" alertClass="alert-danger" v-bind:isDismissible="false" />
<transition name="fade" mode="out-in">
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
<div class="row mb-4">
<div class="col">
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZipCode" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" validationRules="service-zip-required|service-zip-format" />
</div>
</div>
</div>
</transition>
<funnel-footer cmsWidgetName="FunnelFooterWidget" ref="funnelFooter" :isDisabled="!meta.valid" @ForwardClicked="forwardButtonAction" @back-clicked="backButtonAction" :isForwardActionDisabled="!meta.valid" />
</div>
</div>
</Form>
</template>
<script>
// Components
import funnelHeader from "@/common-components/funnel-header/funnel-header";
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
@ -72,398 +37,318 @@ import alert from "@/ux-components/alert/alert";
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
import { Form, defineRule } from "vee-validate";
import { required, regex } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import {Form,defineRule} from "vee-validate";
import {required,regex} from "@/helpers/validation-rules";
import {errorMessages} from "@/constants/error-messages";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import {fetchCmsContentForPage} from "@/helpers/cms-content-helper";
import {settleAllPromises} from "@/helpers/layout-helper";
import {storeActions} from "@/constants/store-actions";
import {routerParams} from "@/router/router-constants/router-params";
import {getDamageString,isGlassAvailableForCarId} from "@/helpers/damage-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
defineRule("service-zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
export default {
name: "address-lookup",
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
name: "address-lookup",
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
// Settle promises and get results
const promiseResultMap = [{
resultKey: "cmsContent",
promise: cmsContentPromise,
}, ];
const resultMap = await settleAllPromises(promiseResultMap);
const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
data() {
return {
customerQuestions: {
addressQuestions: {
streetAddress: this.getRegistrationAddressFromStore(),
city: this.getRegistrationCityFromStore(),
state: this.getRegistrationStateFromStore(),
zipCode: this.getRegistrationZipFromStore(),
},
firstName: this.getRegistrationFirstNameFromStore(),
lastName: this.getRegistrationLastNameFromStore(),
emailAddress: this.getEmailFromStore(),
},
serviceZipCode: this.getServiceZipFromStore(),
displayNonServiceableZipAlert: false,
displayVinNotFoundAlert: false,
displayMatchedDifferentVehicleAlert: false,
displayVinLookupByHomeAddressNotAllowedAlert: false,
previouslyEnteredCarId: "",
isSelectedGlassAvailableForVehicle: false,
customAlertData: {},
showServiceZipField: this.getServiceZipFromStore(),
isZipServiceable: false,
}
},
methods: {
arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null;
},
backButtonAction() {
// route to move backwards
this.$router.navigate(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
this.pushEventToGA(
this.$route.query[this.queryStrings.FMG_PAGE],
this.GaActions.SUBMITTED,
this.GaLabels.ADDRESS_LOOKUP,
true
);
});
},
getRegistrationAddressFromStore() {
return store.getters.vehicle.registration.address;
},
getRegistrationCityFromStore() {
return store.getters.vehicle.registration.city;
},
getRegistrationStateFromStore() {
return store.getters.vehicle.registration.state;
},
getRegistrationZipFromStore() {
return store.getters.vehicle.registration.zipCode;
},
getRegistrationFirstNameFromStore() {
return store.getters.vehicle.registration.firstName;
},
getRegistrationLastNameFromStore() {
return store.getters.vehicle.registration.lastName;
},
getEmailFromStore() {
return store.getters.order.customer.emailAddress;
},
getServiceZipFromStore() {
return store.getters.order.serviceLocation.zipCode;
},
async forwardButtonAction() {
this.resetWarningsAndErrors();
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
data() {
return {
customerQuestions: {
addressQuestions: {
streetAddress: this.getRegistrationAddressFromStore(),
city: this.getRegistrationCityFromStore(),
state: this.getRegistrationStateFromStore(),
zipCode: this.getRegistrationZipFromStore(),
},
firstName: this.getRegistrationFirstNameFromStore(),
lastName: this.getRegistrationLastNameFromStore(),
emailAddress: this.getEmailFromStore(),
},
serviceZipCode: this.getServiceZipFromStore(),
displayNonServiceableZipAlert: false,
displayVinNotFoundAlert: false,
displayMatchedDifferentVehicleAlert: false,
displayVinLookupByHomeAddressNotAllowedAlert: false,
previouslyEnteredCarId: "",
isSelectedGlassAvailableForVehicle: false,
customAlertData: {},
showServiceZipField: this.getServiceZipFromStore(),
isZipServiceable: false,
}
},
methods: {
arePagePrerequisitesValid() {
return store.getters.vehicle.carId !== null;
},
backButtonAction() {
// route to move backwards
this.$router.navigate(
this.navigationScenarios.CLICKED_BACK,
this.$route
);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
this.pushEventToGA(
this.$route.query[this.queryStrings.FMG_PAGE],
this.GaActions.SUBMITTED,
this.GaLabels.ADDRESS_LOOKUP,
true
);
});
},
getRegistrationAddressFromStore() {
return this.$store.getters.vehicle.registration.address;
},
getRegistrationCityFromStore() {
return this.$store.getters.vehicle.registration.city;
},
getRegistrationStateFromStore() {
return this.$store.getters.vehicle.registration.state;
},
getRegistrationZipFromStore() {
return this.$store.getters.vehicle.registration.zipCode;
},
getRegistrationFirstNameFromStore() {
return this.$store.getters.vehicle.registration.firstName;
},
getRegistrationLastNameFromStore() {
return this.$store.getters.vehicle.registration.lastName;
},
getEmailFromStore() {
return this.$store.getters.order.customer.emailAddress;
},
getServiceZipFromStore() {
return this.$store.getters.order.serviceLocation.zipCode;
},
async forwardButtonAction() {
this.resetWarningsAndErrors();
let vehicleInfoToCommit = {};
let registrationInfoToCommit = {};
// Vehicle info change in the flow, use a variable to keep track and commit to state at the end.
let vehicleInfoToCommit = {};
const vinLookupResponse = this.dispatchStoreAction(
storeActions.LOOKUP_VIN_BY_ADDRESS,
{
licenseLastName: this.customerQuestions.lastName,
licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress,
licenseZip: this.customerQuestions.addressQuestions.zipCode,
licenseState: this.customerQuestions.addressQuestions.state
}, false);
const vinLookupResponse = this.dispatchStoreAction(
storeActions.LOOKUP_VIN_BY_ADDRESS, {
licenseLastName: this.customerQuestions.lastName,
licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress,
licenseZip: this.customerQuestions.addressQuestions.zipCode,
licenseState: this.customerQuestions.addressQuestions.state
}, false);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "vinLookupResponse",
promise: vinLookupResponse
},
{
resultKey: "serviceZipValidationResponse",
promise: this.serviceZipCode ?
this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.serviceZipCode }) :
this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.customerQuestions.addressQuestions.zipCode })
}
];
const resultMap = await settleAllPromises(promiseResultMap);
// Settle promises and get results
const promiseResultMap = [{
resultKey: "vinLookupResponse",
promise: vinLookupResponse
},
{
resultKey: "serviceZipValidationResponse",
promise: this.serviceZipCode ?
this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.serviceZipCode}) :
this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {zip: this.customerQuestions.addressQuestions.zipCode})
}
];
// Verify if the service zip code or registration zip code provided is serviceable
if (!resultMap.vinLookupResponse.isStatePermissible) {
// State Restrictions forbid lookup by address
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
return this.$refs.funnelFooter.removeLoader();
}
const resultMap = await settleAllPromises(promiseResultMap);
// if the neither the registration zip code or service zip code are not serviceable
this.isZipServiceable = resultMap.serviceZipValidationResponse.isServiceable;
// Verify if the service zip code or registration zip code provided is serviceable
if (!resultMap.vinLookupResponse.isStatePermissible) {
// State Restrictions forbid lookup by address
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
return this.$refs.funnelFooter.removeLoader();
}
if (!this.isZipServiceable) {
this.displayNonServiceableZipAlert = true;
this.showServiceZipField = true;
return this.$refs.funnelFooter.removeLoader();
}
// If the neither the registration zip code or service zip code are not serviceable
this.isZipServiceable = resultMap.serviceZipValidationResponse.isServiceable;
// if the registration zip code is serviceable and nothing was entered for the service zip code
// then set the service zip code to the registration zip code
if (!this.serviceZipCode) {
this.serviceZipCode = this.customerQuestions.addressQuestions.zipCode;
}
if (!this.isZipServiceable) {
this.displayNonServiceableZipAlert = true;
this.showServiceZipField = true;
return this.$refs.funnelFooter.removeLoader();
}
//const carEntered = store.getters.vehicle;
const vinsFound = resultMap.vinLookupResponse.vinVehicles;
// If the registration zip code is serviceable and nothing was entered for the service zip code
// then set the service zip code to the registration zip code
if (!this.serviceZipCode) {
this.serviceZipCode = this.customerQuestions.addressQuestions.zipCode;
}
// No VINs found
if (vinsFound.length == 0) {
this.displayVinNotFoundAlert = true;
return this.$refs.funnelFooter.removeLoader();
}
// Single VIN found
if (vinsFound.length == 1) {
const carFound = vinsFound[0].vehicle;
this.isCarIdDifferent = carFound.carId !== this.$store.getters.vehicle.carId;
const carsFound = resultMap.vinLookupResponse.vinVehicles;
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
// Display Alert
this.previouslyEnteredCarId = carFound.carId;
this.customAlertData.vehicleInfo = carFound;
this.displayMatchedDifferentVehicleAlert = true;
// Handle cases for different amounts of VINS found for the address.
if (carsFound.length == 1) {
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(carFound.carId);
// Single VIN found
const carFound = carsFound[0].vehicle;
// Update button "Continue with..."
this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`);
return this.$refs.funnelFooter.removeLoader();
}
this.isCarIdDifferent = carFound.carId !== this.$store.getters.vehicle.carId;
if (!this.isZipServiceable) {
return;
}
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
// Display Alert
this.previouslyEnteredCarId = carFound.carId;
this.customAlertData.vehicleInfo = carFound;
this.displayMatchedDifferentVehicleAlert = true;
// update data if the zip or service zip is serviceable
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(carFound.carId);
// --> New Save Method
// Update button "Continue with..."
this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`);
return this.$refs.funnelFooter.removeLoader();
}
// state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
// state.order.vehicle.registration.address = registrationInfo?.address;
// state.order.vehicle.registration.city = registrationInfo?.city;
// state.order.vehicle.registration.state = registrationInfo?.state;
// state.order.vehicle.registration.zipCode = registrationInfo?.zipCode;
// state.order.vehicle.registration.firstName = registrationInfo?.firstName;
// state.order.vehicle.registration.lastName = registrationInfo?.lastName;
if (!this.isZipServiceable) {
return;
}
vehicleInfoToCommit = Object.assign(carFound, { vin: vinsFound[0].vin});
registrationInfoToCommit = {
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
};
// update data if the zip or service zip is serviceable
vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin });
} else if (carsFound.length > 1) {
this.updateVehicleInfo(vinsFound[0].vin, carFound);
this.updateCustomerInfo(resultMap.serviceZipValidationResponse.state);
// Multiple VINS found
if (!this.isZipServiceable) {
return;
}
}
// Found more than one VIN.
if (vinsFound.length > 1) {
if (!this.isZipServiceable) {
return;
}
// if multiple cars were found
const matchingCars = vinsFound.filter(vin => vin.vehicle.carId === this.$store.getters.vehicle.carId);
// and one and only one of them matches the carId entered, save the vehicle info
// If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info
// so we can go to the Heritage Funnel directly
if (matchingCars.length === 1) {
this.updateVehicleInfo(matchingCars[0].vin, matchingCars[0].vehicle);
}
const matchingCars = carsFound.filter(vin => vin.vehicle.carId === this.$store.getters.vehicle.carId);
// update data if the zip or service zip is serviceable.
this.updateCustomerInfo(resultMap.serviceZipValidationResponse.state);
}
if (matchingCars.length === 1) {
vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {vin: matchingCars[0].vin});
}
} else {
// store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, this.customerQuestions.addressQuestions.streetAddress);
// store.commit(storeMutations.UPDATE_REGISTRATION_CITY, this.customerQuestions.addressQuestions.city);
// store.commit(storeMutations.UPDATE_REGISTRATION_STATE, this.customerQuestions.addressQuestions.state);
// store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
// store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
// store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
// store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZipCode);
// store.commit(storeMutations.UPDATE_SERVICE_LOCATION_STATE, serviceState);
// store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.emailAddress);
// Save vin, vehicle, customer, service and registration information
await this.dispatchStoreAction(storeActions.SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP, {
isCarIdDifferent: this.isCarIdDifferent,
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
vehicleInfo: Object.assign(vinLookup.data.vehicle, { vin: vinLookup.data.vin }),
serviceLocationInfo: {
zipCode: this.serviceZip,
state: resultMap.serviceZipValidationResponse.state,
},
registrationInfo: {
licensePlate: this.licensePlate,
state: resultMap.registrationZipValidationResponse.state,
zipCode: this.registrationZip,
},
customerEmail: this.email,
}, false);
// No VINS found.
this.displayVinNotFoundAlert = true;
return this.$refs.funnelFooter.removeLoader();
}
return await this.navigateForward(carEntered, vinsFound);
},
async navigateForward(carEntered, vinsFound) {
this.updateServiceLocationIfNecessary();
// Save vehicle, customer, service and registration information
await this.dispatchStoreAction(storeActions.SAVE_REGISTRATION_ADDRESS_LOOKUP, {
isCarIdDifferent: this.isCarIdDifferent,
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
vehicleInfo: vehicleInfoToCommit,
serviceLocationInfo: {
zipCode: this.serviceZipCode,
state: resultMap.serviceZipValidationResponse.state,
},
registrationInfo: {
firstName: this.customerQuestions.firstName,
lastName: this.customerQuestions.lastName,
address: this.customerQuestions.addressQuestions.streetAddress,
city: this.customerQuestions.addressQuestions.city,
state: resultMap.serviceZipValidationResponse.state,
zipCode: this.customerQuestions.addressQuestions.zipCode
},
customerEmail: this.customerQuestions.emailAddress,
}, false);
if (vinsFound.length == 1) {
// if a different vehicle is found than the one entered and the selected glass
// is not available for that vehicle
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigate(
// then navigate back to "vehicle-damage", and display vehicle changed alert
// on that page
this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS,
this.$route, {}, {
displayVehicleChangeAlert: true
}, {}
);
} else {
// otherwise
await this.navigateForwardWithSingleCarMatch();
}
} else if (vinsFound.length > 1) {
// if multiple cars were found
let matchingCars = vinsFound.filter(car => car.vehicle.carId === carEntered.carId);
if (matchingCars.length === 1) {
// and one and only of them matches the car id entered
const matchingCar = matchingCars[0];
this.updateVehicleInfo(matchingCar.vin, matchingCar.vehicle);
this.navigateForwardWithSingleCarMatch();
} else {
// if there are no matches or there are multiple matches, navigate to "address-vehicles" page
this.$router.navigate(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, vinsFound);
}
}
return await this.navigateForward(carsFound);
},
async navigateForward(carsFound) {
},
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayNonServiceableZipAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
},
// Match vehicles found to vehicles in state.
const matchingCars = carsFound.filter(car => car.vehicle.carId === this.$store.getters.vehicle.carId);
updateCustomerInfo(serviceState) {
store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, this.customerQuestions.addressQuestions.streetAddress);
store.commit(storeMutations.UPDATE_REGISTRATION_CITY, this.customerQuestions.addressQuestions.city);
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, this.customerQuestions.addressQuestions.state);
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZipCode);
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_STATE, serviceState);
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.emailAddress);
},
updateServiceLocationIfNecessary() {
const serviceLocation = store.getters.order.serviceLocation;
// 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 && matchingCars.length === 1) {
this.$router.navigate(this.navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, this.$route, {}, {[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true});
} else if (matchingCars.length === 1) {
await this.navigateForwardWithSingleCarMatch();
} else {
this.$router.navigate(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, carsFound);
}
},
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayNonServiceableZipAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
},
},
mounted() {
this.attachCustomEvents();
},
computed: {
AlertNonServiceableZipHeader() {
const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode;
const text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode);
return text;
},
AlertNonServiceableZipBody() {
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
},
AlertMatchedDifferentVehicleHeader() {
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.$store.getters.vehicle.year} ${this.$store.getters.vehicle.make} ${this.$store.getters.vehicle.model}`;
if (!serviceLocation.address && serviceLocation.zipCode && serviceLocation.zipCode == store.getters.vehicle.registration.zipCode) {
this.dispatchStoreAction(storeActions.UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION);
}
}
},
mounted() {
this.attachCustomEvents();
},
computed: {
AlertNonServiceableZipHeader() {
const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode;
const text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode);
return text;
},
AlertNonServiceableZipBody() {
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
},
AlertMatchedDifferentVehicleHeader() {
const text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
return text;
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
const content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
.replaceAll("{custom:glassText}", getDamageString())
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
return content;
},
},
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.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
this.showServiceZipField = false;
this.resetWarningsAndErrors();
},
deep: true
},
serviceZipCode: {
handler(newValue) {
// if they modify the service zip code, then hide the error message
this.displayNonServiceableZipAlert = false;
},
},
showServiceZipField: {
handler(newValue) {
// if the Service Zip Code field is ever hidden, clear out it's value
if (!newValue) {
this.serviceZipCode = null;
}
},
}
},
components: {
funnelHeader,
funnelFooter,
vehicleBanner,
funnelSubHeader,
customerQuestions,
textboxQuestion,
alert,
loadingModal,
Form
},
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
.replaceAll("{custom:glassText}", getDamageString())
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
},
},
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.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
this.showServiceZipField = false;
this.resetWarningsAndErrors();
},
deep: true
},
serviceZipCode: {
handler(newValue) {
// If they modify the service zip code, then hide the error message.
this.displayNonServiceableZipAlert = false;
},
},
showServiceZipField: {
handler(newValue) {
// If the Service Zip Code field is ever hidden, clear out it's value
if (!newValue) {
this.serviceZipCode = null;
}
},
}
},
components: {
funnelHeader,
funnelFooter,
vehicleBanner,
funnelSubHeader,
customerQuestions,
textboxQuestion,
alert,
loadingModal,
Form
},
};
</script>

View file

@ -577,7 +577,7 @@ function setupMocks({ mountOptions, props, isShallowMount = true, querySelectorF
...mountOptions,
router: {
navigate: jest.fn(),
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
loadScript: jest.fn().mockResolvedValue()
});

View file

@ -81,7 +81,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse));
wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.$router.navigate = jest.fn();
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {});
wrapper.vm.navigateForward = jest.fn().mockImplementation(()=> {});
@ -112,7 +112,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
wrapper.vm.lookupVin = jest.fn(() => Promise.reject(lookupVinResponse));
wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.$router.navigate = jest.fn();
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {});
// Act
@ -128,88 +128,11 @@ describe("addressVehicles.vue", () => {
wrapper.unmount();
});
test("Should send dispatch reset if carId is different and selected glass not available for vehicle on updateCustomerInfo", async () => {
// Arrange
const { wrapper } = setupMocks({});
const lookupVinResponse = {
data: {
carId: "456"
}
}
// the following has to be set BEFORE changing the data which is being watched, and requires updateButtonText to be mocked
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.lookupVin = jest.fn(() => Promise.resolve(lookupVinResponse));
wrapper.vm.$router.navigateAfterSave = jest.fn();
// Act
await wrapper.setData({
selectedVehicleVin: '5NMS3CADXLH233004',
isSelectedGlassAvailableForVehicle: false,
isCarIdDifferent: true,
});
await wrapper.vm.updateCustomerInfo(wrapper.vm.selectedVehicle.vin, wrapper.vm.selectedVehicle.vehicle);
//Assert
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith("resetDamageAndDependencies");
wrapper.unmount();
});
// NOTE: this test is only here to meet code coverage; it does not test any logic in the original function
test("Should send dispatch store action if lookupVin is called", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
await wrapper.vm.lookupVin('1234567890');
//Assert
expect(wrapper.vm.dispatchStoreAction).toBeCalledWith("lookupVehicleByVin", {"vin": "1234567890"});
wrapper.unmount();
});
test("If selectedVehicleVin changes, then should update isCarIdDifferent", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Act
await wrapper.setData({
selectedVehicleVin: '5NMS3CADXLH233004',
isCarIdDifferent: false,
});
await wrapper.vm.resetDependentState();
//Assert
expect(wrapper.vm.isCarIdDifferent).toBe(true);
wrapper.unmount();
});
test("If selectedVehicleVin changes, then text on funnel footer should be updated", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
// Act
await wrapper.setData({
selectedVehicleVin: '5NMS3CADXLH233004',
isCarIdDifferent: false,
});
await wrapper.vm.resetDependentState();
//Assert
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toBeCalled();
wrapper.unmount();
});
test("Should navigate to CLICKED_FORWARD scenario if carId is different and selected glass not available for vehicle on navigateForward", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.$router.navigate = jest.fn();
// Act
await wrapper.setData({
@ -220,7 +143,7 @@ describe("addressVehicles.vue", () => {
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toBeCalledTimes(1);
expect(wrapper.vm.$router.navigate).toBeCalledTimes(1);
wrapper.unmount();
});

View file

@ -60,7 +60,6 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { errorMessages } from "@/constants/error-messages";
import { required } from "@/helpers/validation-rules";
@ -70,6 +69,7 @@ import { doesCopyContainRouterLink,
splitCopyOnCMSPlaceHolder,
getRouterLinkRouteFromCopy,
getRouterLinkDisplayTextFromCopy, } from "@/helpers/cms-content-helper";
import { routerParams } from "@/router/router-constants/router-params";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
// DEFINE VALIDATION RULES
@ -112,8 +112,7 @@ export default {
return this.VehiclesForQuestions.length;
},
AlertFoundMultipleVehiclesHeader() {
let text = this.getCmsContent("FoundMultipleVehicles", "HeadlineText").replaceAll("{custom:vehicleCount}", this.vehicleCount);
return text;
return this.getCmsContent("FoundMultipleVehicles", "HeadlineText").replaceAll("{custom:vehicleCount}", this.vehicleCount);
},
AlertProvideVinBody() {
return this.getCmsContent("ProvideVinAlert", "BodyText");
@ -123,10 +122,8 @@ export default {
return this.splitCopyOnCMSPlaceHolder(this.AlertProvideVinBody);
},
VehiclesForQuestions() {
const vehiclesData = this.VehiclesFromApi;
// Map API result data, to address-vehicles data structure
const mappedData = vehiclesData.map((v) => {
const mappedData = this.VehiclesFromApi.map((v) => {
const maskSymbol = "X";
const vinStart = maskSymbol.repeat(v.vin.length-4);
const vinEnd = v.vin.substring(v.vin.length-4);
@ -168,52 +165,31 @@ export default {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
const vinLookup = await this.lookupVin(this.selectedVehicle.vin).catch(() => {
this.$refs.funnelFooter.removeLoader();
});
const vinLookup = await this.dispatchStoreAction(storeActions.LOOKUP_VEHICLE_BY_VIN,{ vin: this.selectedVehicle.vin })
.catch(() => {this.$refs.funnelFooter.removeLoader();});
if (!vinLookup) {
return;
}
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.carId);
this.updateCustomerInfo(this.selectedVehicle.vin, this.selectedVehicle.vehicle);
this.navigateForward();
await this.dispatchStoreAction(storeActions.SAVE_VIN, {
vehicleInfo: Object.assign(this.selectedVehicle.vehicle, { vin: this.selectedVehicle.vin }),
isCarIdDifferent: this.isCarIdDifferent,
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle
}, false);
return await this.navigateForward();
},
navigateForward() {
async navigateForward() {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD,
this.$route,
{},
{ displayVehicleChangeAlert: true },
);
return;
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,this.$route,{},{[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true },);
} else {
this.navigateForwardWithSingleCarMatch();
return;
await this.navigateForwardWithSingleCarMatch();
}
},
lookupVin(vin) {
return this.dispatchStoreAction(
storeActions.LOOKUP_VEHICLE_BY_VIN,
{ vin }
);
},
//this.dispatchStoreAction(storeActions.SAVE_VIN, vin,vehicle),
updateCustomerInfo(vin, vehicle) {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.dispatchStoreAction(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
store.commit(storeMutations.UPDATE_YEAR, vehicle.year);
store.commit(storeMutations.UPDATE_MAKE, vehicle.make);
store.commit(storeMutations.UPDATE_MODEL, vehicle.model);
store.commit(storeMutations.UPDATE_STYLE, vehicle.style);
store.commit(storeMutations.UPDATE_CAR_ID, vehicle.carId);
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicle.category);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicle.imageUrl);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicle.imageVifNumber);
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicle.imageColor);
},
},
watch: {

View file

@ -101,7 +101,7 @@ describe("estimate.vue", () => {
})
//Act
wrapper.vm.forwardButtonAction();
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
@ -146,12 +146,9 @@ describe("estimate.vue", () => {
});
function setupMocks({
modelValueProp = ["Provide my VIN manually most specific to your vehicle"],
isMultiSelect = false,
groupName = "estimate",
cmsQuestionText = "Let's get your VIN. Or we can look it up for you!",
cmsAnswers = [{ Name: "Provide my VIN manually Most specific to your vehicle" }, { Name: "Provide my license plate # Most accurate VIN match" }, { Name: "Provide my home address Most convenient VIN match" }],
dataFromApi = [],
mountOptionsMockData = {
router: {
navigate: jest.fn(),
@ -166,13 +163,6 @@ function setupMocks({
Answers: cmsAnswers
};
//Mock props
const mockMixin = {
methods: {
getCmsContent: jest.fn()
}
}
const apiPromise = Promise.resolve(cmsContent);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());

View file

@ -52,7 +52,7 @@ import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js";
// Define Validation Rules
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
@ -93,28 +93,25 @@ export default {
this.$route
);
},
forwardButtonAction() {
async forwardButtonAction() {
if (this.selectedValues[0] === vinLookupMethodSelections.MANUALVIN) {
store.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
this.$router.navigate(
await this.dispatchStoreAction(storeActions.CLEAR_VIN);
return this.$router.navigate(
this.navigationScenarios.SELECTED_MANUAL_VIN,
this.$route
);
return;
}
if (this.selectedValues[0] === vinLookupMethodSelections.LICENSEPLATE) {
this.$router.navigate(
return this.$router.navigate(
this.navigationScenarios.SELECTED_LICENSE_PLATE,
this.$route
);
return;
);
}
if (this.selectedValues[0] === vinLookupMethodSelections.HOMEADDRESS) {
this.$router.navigate(
return this.$router.navigate(
this.navigationScenarios.SELECTED_HOME_ADDRESS,
this.$route
);
return;
}
},
},

View file

@ -25,6 +25,12 @@ jest.mock("@/helpers/cms-content-helper", () => ({
fetchCmsContentForPage: jest.fn(),
}));
// Mock damage helper
jest.mock("@/helpers/damage-helper", () => ({
isGlassAvailableForCarId: () => { return false;},
getDamageString: () => {return 'damage string'; }
}));
describe("license-plate-lookup.vue", () => {
describe("get values from store", () => {
test("getLicensePlateFromStore returns store license plate", async () => {
@ -69,7 +75,7 @@ describe("license-plate-lookup.vue", () => {
test("getServiceZipFromStore returns store service zip", async () => {
// Arrange
const { wrapper } = setupMocks({});
const mockServiceZip = "11111";
const mockServiceZip = "12345";
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, mockServiceZip);
// ACT
@ -103,11 +109,9 @@ describe("license-plate-lookup.vue", () => {
describe("on forwardButtonAction click", () => {
test("Navigate forward should be called and isCarIdDifferent should be set to false when data entered matches store data on forwardButtonAction click", async () => {
// Arrange
const { wrapper } = setupMocks({});
const mockCarId = "TESTID";
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []);
store.commit(storeMutations.UPDATE_CAR_ID, mockCarId);
const { wrapper } = setupMocks({ carId: mockCarId, isServiceable: true});
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
return { data: { isServiceable: true } };
});
@ -116,7 +120,15 @@ describe("license-plate-lookup.vue", () => {
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
return new Promise(resolve => resolve(vinLookup));
});
wrapper.vm.navigateForward = jest.fn();
wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({
data:{
vehicle: {
carId: mockCarId
}
}
}));
//Act
licensePlateLookup.beforeRouteEnter.call(
@ -133,46 +145,27 @@ describe("license-plate-lookup.vue", () => {
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
});
test("Function should stop and datam isRegistrationZipServicable should be set to false when service zip entered returns false on forwardButtonAction click", async () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
return { data: { isServiceable: false } };
});
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return '';
});
//Act
licensePlateLookup.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "license-plate-lookup" } },
undefined,
(c) => c(wrapper.vm)
);
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.isRegistrationZipServicable).toEqual(false);
});
test("Function should stop and datam isCarIdDifferent should be set to true when carId entered doesn't match store carId or previously entered carId on forwardButtonAction click", async () => {
// Arrange
const { wrapper } = setupMocks({});
// Setup state data / return data.
const { wrapper } = setupMocks({carId: "C111111", isServiceable: true});
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []);
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
return { data: { isServiceable: true } };
});
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return '';
});
const vinLookup = { data: { vehicle: { carId: "TESTID1" } } }
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
return new Promise(resolve => resolve(vinLookup));
});
// Mock store action call
wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({
data:{
vehicle: {
carId: "C00000" // Make sure carId returned from call does not match carId in state.
}
}
}));
//Act
licensePlateLookup.beforeRouteEnter.call(
@ -191,21 +184,24 @@ describe("license-plate-lookup.vue", () => {
test("Navigate forward should be called and isCarId should be set to true when carId entered matches previously entered carId and rest of data entered matches store data on forwardButtonAction click", async () => {
// Arrange
const { wrapper } = setupMocks({});
const { wrapper } = setupMocks({carId: "C10000", isServiceable: true});
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
return { data: { isServiceable: true } };
});
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return '';
});
const vinLookup = { data: { vehicle: { carId: "TESTID1" } } }
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
return new Promise(resolve => resolve(vinLookup));
});
wrapper.vm.previouslyEnteredCarId = "TESTID1";
wrapper.vm.previouslyEnteredCarId = "C00000";
wrapper.vm.navigateForward = jest.fn();
// Mock store action call
wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({
data:{
vehicle: {
carId: "C00000" // Make sure carId returned from call does not match carId in state.
}
}
}));
//Act
licensePlateLookup.beforeRouteEnter.call(
wrapper.vm,
@ -223,7 +219,7 @@ describe("license-plate-lookup.vue", () => {
});
describe("navigateForward", () => {
test("navigateAfterSave should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when navigateForward is called", async () => {
test("navigate should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when navigateForward is called", async () => {
// Arrange
const { wrapper } = setupMocks({});
@ -234,7 +230,7 @@ describe("license-plate-lookup.vue", () => {
isSelectedGlassAvailableForVehicle: false
})
wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.$router.navigate = jest.fn();
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return '';
});
@ -243,7 +239,7 @@ describe("license-plate-lookup.vue", () => {
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
});
test("navigateToHeritageFunnel should be called if isCarIdDifferent is false or isSelectedGlassAvailableForVehicle is true when navigateForward is called", async () => {
@ -353,17 +349,7 @@ describe("license-plate-lookup.vue", () => {
test("registrationZip is serviceable and vehicle match is found => sets service zip/state to registration zip/state", async () => {
// Arrange
const { wrapper } = setupMocks({});
const mockCarId = "TESTID";
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, []);
store.commit(storeMutations.UPDATE_CAR_ID, mockCarId)
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => {
if (zip)
return { data: { isServiceable: true, state: "OH" } };
return
});
const vinLookup = { data: { vehicle: { carId: mockCarId } } }
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => new Promise(resolve => resolve(vinLookup)));
await wrapper.setData({ registrationZip: "00000" });
navigateToHeritage.navigateToHeritageFunnel = jest.fn();
@ -372,9 +358,9 @@ describe("license-plate-lookup.vue", () => {
await wrapper.vm.forwardButtonAction();
// Assert
expect(store.getters.order.serviceLocation.zipCode).toEqual(store.getters.vehicle.registration.zipCode);
expect(store.getters.vehicle.registration.zipCode).toEqual("00000");
expect(store.getters.order.serviceLocation.zipCode).toEqual("00000");
expect(wrapper.vm.$store.getters.order.serviceLocation.zipCode).toEqual(wrapper.vm.$store.getters.vehicle.registration.zipCode);
expect(wrapper.vm.$store.getters.vehicle.registration.zipCode).toEqual("12345");
expect(wrapper.vm.$store.getters.order.serviceLocation.zipCode).toEqual("12345");
})
test("vehicle match is found but registrationZip is not serviceable => shows service zip/state field", async () => {
@ -406,7 +392,7 @@ describe("license-plate-lookup.vue", () => {
await wrapper.setData({ registrationZip: "00000" });
navigateToHeritage.navigateToHeritageFunnel = jest.fn();
await wrapper.vm.forwardButtonAction();
wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.$router.navigate = jest.fn();
// At this point, serviceZip field is shown
// Act
@ -418,7 +404,7 @@ describe("license-plate-lookup.vue", () => {
expect(serviceZipField.exists()).toBe(true);
expect(serviceZipField.isVisible()).toBe(true); 3
expect(navigateToHeritage.navigateToHeritageFunnel).not.toHaveBeenCalled();
expect(wrapper.vm.$router.navigateAfterSave).not.toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).not.toHaveBeenCalled();
});
test("registrationZip is not serviceable so serviceZip field is shown, user enters serviceZip => user can continue", async () => {
@ -426,16 +412,9 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({});
const registrationZip = "00000";
const serviceZip = "99999";
const mockCarId = "TestCarId";
store.commit(storeMutations.UPDATE_CAR_ID, mockCarId);
wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => {
return { data: { isServiceable: zip == registrationZip ? false : true, state: "XX" } };
});
const vinLookup = { data: { vehicle: { carId: mockCarId } } }
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
return new Promise(resolve => resolve(vinLookup));
});
wrapper.vm.navigateForward = jest.fn();
await wrapper.setData({ registrationZip: registrationZip });
await wrapper.vm.forwardButtonAction();
// At this point, serviceZip field is shown
@ -453,34 +432,35 @@ describe("license-plate-lookup.vue", () => {
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
});
test("registrationZip is not serviceable so serviceZip field is shown, user enters serviceZip => service and registration zips/states saved", async () => {
test.only("registrationZip is not serviceable so serviceZip field is shown, user enters serviceZip => service and registration zips/states saved", async () => {
// Arrange
const { wrapper } = setupMocks({});
const registrationZip = "00000";
const serviceZip = "99999";
const mockCarId = "TestCarId";
store.commit(storeMutations.UPDATE_CAR_ID, mockCarId);
wrapper.vm.validateZip = jest.fn().mockImplementation((zip) => {
return { data: { isServiceable: zip == registrationZip ? false : true, state: "XX" } };
});
const vinLookup = { data: { vehicle: { carId: mockCarId } } }
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
return new Promise(resolve => resolve(vinLookup));
});
const { wrapper } = setupMocks({isServiceable: true});
const registrationZip = "12345";
const serviceZip = "12345";
wrapper.vm.navigateForward = jest.fn();
await wrapper.setData({ registrationZip: registrationZip });
await wrapper.vm.forwardButtonAction();
// At this point, serviceZip field is shown
await wrapper.setData({ serviceZip: serviceZip });
wrapper.vm.dispatchStoreAction = jest.fn().mockImplementation(() => Promise.resolve({
data:{
vehicle: {
carId: "C00000"
}
}
}));
// Act
// Continue after entering value into service zip field
await wrapper.vm.forwardButtonAction();
// Assert
expect(store.getters.vehicle.registration.zipCode).toEqual(registrationZip);
expect(store.getters.order.serviceLocation.zipCode).toEqual(serviceZip);
expect(wrapper.vm.$store.getters.vehicle.registration.zipCode).toEqual(registrationZip);
expect(wrapper.vm.$store.getters.order.serviceLocation.zipCode).toEqual(serviceZip);
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
});
})
@ -506,60 +486,15 @@ describe("license-plate-lookup.vue", () => {
expect(arePagePrerequisitesValid).toBe(true);
});
test("Dispatch reset damage and dependencies should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when updateCustomerInfo is called", async () => {
// Arrange
const { wrapper } = setupMocks({});
//Act
await wrapper.setData({
isCarIdDifferent: true,
isSelectedGlassAvailableForVehicle: false
})
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return '';
});
store.commit = jest.fn();
const vehicleInfo = { year: "2020", make: "honda", model: "civic", style: "2 door", carId: "TestId", category: "testCat", imageUrl: "image.jpg", imageVifNumber: "123", imageColor: "blue" }
await wrapper.vm.updateCustomerInfo('vin', vehicleInfo, 'registrationState');
//Assert
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
})
test("dispatchStoreAction called on validate zip", async () => {
// Arrange
const { wrapper } = setupMocks({});
//Act
await wrapper.vm.validateZip("12345");
//Assert
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
});
test("dispatchStoreAction called on lookup vin", async () => {
// Arrange
const { wrapper } = setupMocks({});
//Act
await wrapper.vm.lookupVin("zzz123fqsfwg");
//Assert
expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
});
})
});
function setupMocks({
pageHeaderWidgetHeaderText = {},
mountOptionsMockData = {},
partsOrQuestions = []
partsOrQuestions = [],
isServiceable = false,
carId = ""
}) {
store.commit(storeMutations.RESET_STATE);
//Mock api responses
@ -575,6 +510,12 @@ function setupMocks({
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
},
},
serviceZipValidationResponse: {
isServiceable: isServiceable
},
registrationZipValidationResponse: {
state: "CO"
}
};
mountOptionsMockData = {
@ -582,6 +523,25 @@ function setupMocks({
router: {
navigate: jest.fn(),
},
store: {
getters: {
vehicle: {
registration: {
licensePlate: "TESTPLATE",
zipCode: "12345"
},
carId: carId
},
order: {
customer: {
emailAddress: "test@test.com"
},
serviceLocation: {
zipCode: "12345"
}
}
}
},
actionList: [
{
actionName: storeActions.GET_PARTS_OR_QUESTIONS,

View file

@ -176,8 +176,7 @@ export default {
},
computed: {
MatchedDifferentVehicleAlertHeader() {
return this.getCmsContent("MatchedDifferentVehicleAlertWidget","HeadlineText")
.replaceAll("{custom:damage}", getDamageString());
return this.getCmsContent("MatchedDifferentVehicleAlertWidget","HeadlineText").replaceAll("{custom:damage}", getDamageString());
},
MatchedDifferentVehicleAlertBody() {
return this.getCmsContent("MatchedDifferentVehicleAlertWidget","BodyText")
@ -249,14 +248,13 @@ export default {
this.zipToDisplay = this.serviceZip ? this.serviceZip : this.registrationZip;
return this.$refs.funnelFooter.removeLoader();
}
if (!this.serviceZip) {
this.serviceZip = this.registrationZip;
}
//Lookup vin
const vinLookup = await this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE,
{ licensePlate: this.licensePlate, licenseState: resultMap.registrationZipValidationResponse.state }, false)
const vinLookup = await this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE, {licensePlate: this.licensePlate, licenseState: resultMap.registrationZipValidationResponse.state}, false)
.catch(() => {
this.isVinValid = false;
this.isCarIdDifferent = false;

View file

@ -24,12 +24,6 @@ import {
import {
settleAllPromises
} from "@/helpers/layout-helper";
import {
storeMutations
} from "@/constants/store-mutations";
import {
storeActions
} from "@/constants/store-actions";
import store from "@/store";
import {
fmgPageValues
@ -65,13 +59,6 @@ export default {
arePagePrerequisitesValid() {
return Object.keys(store.getters.pageData(fmgPageValues.PART_QUESTIONS)).length !== 0;
},
resetDependentState() {
// Set
store.commit(storeMutations.UPDATE_GLASS_PARTS, null);
// Invokes
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
},
},
data() {},
components: {

View file

@ -51,7 +51,6 @@ export default {
resetDependentState() {
// Set
store.commit(storeMutations.UPDATE_GLASS_PARTS, null);
// Invokes
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
},

View file

@ -78,7 +78,7 @@ describe("vehicle-damage.vue", () => {
});
test("Replace several pieces of glass on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
test("Replace several pieces of glass on ForwardButtonAction triggers a router.navigate and saves selections to store", async () => {
//Arrange
const partsData = {
partsOrQuestions: [{
@ -119,7 +119,7 @@ describe("vehicle-damage.vue", () => {
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigateAfterSave: jest.fn(), },
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
@ -159,13 +159,12 @@ describe("vehicle-damage.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(storeActions.GET_DAMAGE_OPTIONS, {"carId": "C00000000"});
});
test("Windshield replace with multiple parts on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
test("Windshield replace with multiple parts on ForwardButtonAction triggers a router.navigate and saves selections to store", async () => {
//Arrange
const partsData = {
partsOrQuestions: [
@ -219,7 +218,7 @@ describe("vehicle-damage.vue", () => {
const { wrapper } = setupMocks({
pageHeaderWidgetHeaderText: "",
mountOptionsMockData: {
router: { navigateAfterSave: jest.fn(), },
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
store: {
getters: {
@ -250,10 +249,9 @@ describe("vehicle-damage.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
expect(baseMixin.methods.dispatchStoreAction).toBeCalledWith(storeActions.GET_DAMAGE_OPTIONS, {"carId": "C00000000"});
});
@ -465,25 +463,6 @@ describe("vehicle-damage.vue", () => {
expect(arePagePrerequisitesValid).toBe(true);
});
test("Call invalidation, ResetPartsAndState should be called", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleDamage.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-damage" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.resetDependentState();
//Assert
expect(store.dispatch).toBeCalledWith(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES)
});
});
describe("input validations", () => {
@ -531,7 +510,7 @@ describe("vehicle-damage.vue", () => {
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation }] }, isRepair: true };
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ glassLocation: damageLocation }] }, isRepair: true };
var glassSelections = wrapper.vm.getDamageLocationsFromStore();
@ -575,7 +554,7 @@ describe("vehicle-damage.vue", () => {
eventBusItem: jest.fn(),
damage:
{
glassToReplace: [{ location: damageLocation, name: damageName }],
glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }],
isRepair: isRepair,
numberOfChips: 2
},
@ -605,7 +584,7 @@ describe("vehicle-damage.vue", () => {
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getDriverSideReplaceOptionsFromStore();
@ -632,7 +611,7 @@ describe("vehicle-damage.vue", () => {
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getPassengerSideReplaceOptionsFromStore();
@ -656,7 +635,7 @@ describe("vehicle-damage.vue", () => {
(c) => c(wrapper.vm)
);
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ location: damageLocation, name: damageName }] }, isRepair: true };
store.getters = { vehicle: { carId: "C0000000" }, eventBusItem: jest.fn(), damage: { glassToReplace: [{ glassLocation: damageLocation, glassName: damageName }] }, isRepair: true };
var glassSelections = wrapper.vm.getRearReplaceOptionsFromStore();
@ -682,7 +661,7 @@ describe("vehicle-damage.vue", () => {
// Arrange
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: { navigateAfterSave: jest.fn(), },
router: { navigate: jest.fn(), },
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: {}, },],
store: {
getters: {

View file

@ -285,13 +285,13 @@ export default {
async forwardButtonAction() {
this.dispatchStoreAction(this.storeActions.SAVE_VEHICLE_DAMAGE, {
await this.dispatchStoreAction(this.storeActions.SAVE_VEHICLE_DAMAGE, {
isWindshieldRepair: this.isWindshieldRepair,
selectedGlassToReplace: this.selectedGlassToReplace(),
selectedWindshieldChipCount: this.selectedWindshieldOptions.selectedWindshieldChipCount
}, false);
this.navigateForward();
return this.navigateForward();
},
navigateForward(){
@ -299,11 +299,9 @@ export default {
// If vin already exists, navigate directly to vin-lookup
if(store.getters.vehicle.vin) {
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, this.$route);
return;
}
else {
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, this.$route);
return;
}
},

View file

@ -4,14 +4,11 @@ import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { nextTick } from "vue";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import baseMixin from "@/mixins/base-mixin.js";
// Components
import vehicleMake from "@/layouts/vehicle-make/vehicle-make.vue";
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import store from "@/store";
jest.mock("@/store", () => ({
commit: jest.fn(),
@ -110,33 +107,6 @@ describe("vehicle-make.vue", () => {
});
});
describe("vehicle-make.vue", () => {
test("Year set, call invalidation, model, style, carId, category should be null", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleMake.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-make" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.resetDependentState();
//Assert
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
});
});
function setupMocks({
vehicleMakeQuestionCmsContent = {},

View file

@ -8,10 +8,7 @@ import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { nextTick } from "vue";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
@ -106,32 +103,6 @@ describe("vehicle-model.vue", () => {
});
});
describe("vehicle-model.vue", () => {
test("Year set, call invalidation, style, carId, category should be null", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleModel.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-model" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.resetDependentState();
//Assert
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
});
});
function setupMocks({
buttonQuestionContent = {},

View file

@ -71,7 +71,7 @@ describe("vehicle-parts.vue", () => {
{
mountOptionsMockData: {
router: {
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
route: {
query: {
@ -109,7 +109,7 @@ describe("vehicle-parts.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
route: {
query: {
@ -146,7 +146,7 @@ describe("vehicle-parts.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
route: {
query: {
@ -182,7 +182,7 @@ describe("vehicle-parts.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigateAfterSave: jest.fn(),
navigate: jest.fn(),
navigate: jest.fn()
},
route: {
@ -223,7 +223,7 @@ describe("vehicle-parts.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
router: {
navigateAfterSave: jest.fn(),
navigate: jest.fn(),
navigate: jest.fn()
},
route: {
@ -251,7 +251,7 @@ describe("vehicle-parts.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
// expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
// expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
// expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);

View file

@ -67,6 +67,7 @@ import store from "@/store";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { storeActions } from "@/constants/store-actions";
// DEFINE VALIDATION RULES
defineRule("replace-options-required", required(errorMessages.OPTION_REQUIRED));
@ -164,7 +165,7 @@ methods: {
backButtonAction() {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
forwardButtonAction() {
async forwardButtonAction() {
const selectedGlassPartNumbers = [];
const matchedParts = [];
@ -198,15 +199,11 @@ methods: {
}
// Save parts to the store.
store.commit(storeMutations.UPDATE_GLASS_PARTS, matchedParts);
// Save parts to the store.
store.commit(storeMutations.UPDATE_PARTS, matchedParts);
await this.dispatchStoreAction(storeActions.SAVE_GLASS_PARTS, matchedParts);
// Navigate to the next page.
this.$router.navigate(
this.navigationScenarios.SELECTED_PARTS,
this.$route
);
// Navigate to the next page.
this.$router.navigate(this.navigationScenarios.SELECTED_PARTS,this.$route);
},
LoadInitialPartsData() {

View file

@ -74,34 +74,6 @@ describe("vehicle-year.vue", () => {
});
});
describe("vehicle-year.vue", () => {
test("Year set, call invalidation, make, model, style, carId, category should be null", async () => {
//Arrange
const { wrapper } = setupMocks({});
//Act
vehicleYear.beforeRouteEnter.call(
wrapper.vm,
{ query: { fmgPage: "vehicle-year" } },
undefined,
(c) => c(wrapper.vm)
);
wrapper.vm.resetDependentState();
//Assert
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MAKE, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_MODEL, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_STYLE, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
});
});
function setupMocks({
vehicleYearQuestionCmsContent = {},
yearQuestionInitialData = {},

View file

@ -200,7 +200,7 @@ describe("vin-lookup.vue", () => {
const { wrapper } = setupMocks({
customMountOptions: {
router: {
navigateAfterSave: jest.fn()
navigate: jest.fn()
}
}
});
@ -214,8 +214,8 @@ describe("vin-lookup.vue", () => {
await wrapper.vm.navigateForward();
//Assert
expect(wrapper.vm.$router.navigateAfterSave).toBeCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, wrapper.vm.$route, expect.anything(), expect.anything(), expect.anything());
expect(wrapper.vm.$router.navigate).toBeCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_HAS_MISMATCHED_GLASS, wrapper.vm.$route, expect.anything(), expect.anything(), expect.anything());
})
test("carId matches => navigateForwardWithSingleCarMatch", async () => {

View file

@ -125,7 +125,6 @@ import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { errorMessages } from "@/constants/error-messages";
import { getDamageString, getIsWindshieldOnly, isGlassAvailableForCarId } from "@/helpers/damage-helper";
import { required, regex } from "@/helpers/validation-rules";
@ -191,9 +190,7 @@ export default {
watch: {
vin() {
this.vinNotFound = false;
this.$refs.funnelFooter.updateButtonText(
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
);
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
},
zip() {
this.noServiceZip = false;

View file

@ -55,8 +55,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
test("multiple glass locations have part questions => go to parts-questions", async () => {
@ -163,8 +163,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
test("multiple glass locations selected, one has part question => go to parts-questions", async () => {
@ -263,8 +263,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
test("a selected glass location has part questions and multiple parts => go to parts-questions", async () => {
@ -411,8 +411,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_PART_QUESTIONS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
});
@ -453,8 +453,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
test("multiple glass locations selected, one of them has multiple parts => go to vehicle parts", async () => {
@ -559,8 +559,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
test("multiple glass locations selected, multiple have multiple parts => go to vehicle-parts", async () => {
@ -731,8 +731,8 @@ describe("vin-pages-mixin", () => {
await wrapper.vm.navigateForwardWithSingleCarMatch();
// Assert
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.SELECTED_VIN_WITH_MULTIPLE_PARTS, wrapper.vm.$route, {}, {}, { partsOrQuestions });
});
});
@ -894,7 +894,7 @@ function setupMocks({ partsOrQuestions = [] }) {
const mocks = getMountOptions({
router: {
navigateAfterSave: jest.fn()
navigate: jest.fn()
},
});

View file

@ -214,7 +214,7 @@ export const mutations = {
}
},
// DEPENDENCY MUTATIONS
// RESET DEPENDENCY MUTATIONS
resetVehicleState(state) {
state.order.vehicle.year = null;
state.order.vehicle.make = null;
@ -292,13 +292,6 @@ export const mutations = {
state.order.customer.emailAddress = orderInformation.customer.emailAddress;
},
updateServiceLocationWithVehicleRegistration(state) {
state.order.serviceLocation.address = state.order.vehicle.registration.address;
state.order.serviceLocation.city = state.order.vehicle.registration.city;
state.order.serviceLocation.state = state.order.vehicle.registration.state;
state.order.serviceLocation.zipCode = state.order.vehicle.registration.zipCode;
}
}
// Export Getters
@ -545,9 +538,6 @@ export const actions = {
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
},
updateServiceLocationWithVehicleRegistration(context) {
context.commit(storeMutations.UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION);
},
GetExperimentsByUser(context, { userId }) {
return globalMethods.callHttpClient({
@ -556,6 +546,7 @@ export const actions = {
payload: {}
});
},
getEvoxImage(context, { relativeUrl }) {
return globalMethods.callHttpClient({
method: endpoints.GetPageData.method,
@ -653,7 +644,7 @@ export const actions = {
// Business domain actions
// Vehicle domain
// Vehicle
saveVehicleYear(context, year) {
//Reset dependent state when changing
@ -733,7 +724,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_STYLE, style);
},
saveVehicleDamage(context, { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }) {
const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort();
const isGlassToReplaceTheSame = (context.state.order.damage.glassToReplace?.length === selectedGlassToReplace.length)
&& context.state.order.damage.glassToReplace
@ -752,7 +743,7 @@ export const actions = {
}
},
// Vin domain
// Vin lookup
saveVinLookup(context, { isCarIdDifferent, isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo, serviceLocationInfo, customerEmail }) {
//Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
@ -761,7 +752,7 @@ export const actions = {
if (isCarIdDifferent && !isSelectedGlassAvailableForVehicle) {
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
}
}
//Save new values
@ -789,7 +780,7 @@ export const actions = {
context.dispatch(storeActions.SAVE_EMAIL, customerEmail);
context.dispatch(storeActions.SAVE_SERVICE_LOCATION, serviceLocationInfo);
},
saveRegistrationAddressLookup(context, { isCarIdDifferent, isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo, serviceLocationInfo, customerEmail}) {
saveRegistrationAddressLookup(context, { isCarIdDifferent, isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo, serviceLocationInfo, customerEmail }) {
//Reset dependent state when changing
if (registrationInfo?.address !== context.state.order.vehicle.registration?.address || registrationInfo?.city !== context.state.order.vehicle.registration?.city || registrationInfo?.state !== context.state.order.vehicle.registration?.state || registrationInfo?.zipCode !== context.state.order.vehicle.registration?.zipCode || registrationInfo?.firstName !== context.state.order.vehicle.registration?.firstName || registrationInfo?.lastName !== context.state.order.vehicle.registration?.lastName) {
@ -808,7 +799,7 @@ export const actions = {
context.dispatch(storeActions.SAVE_SERVICE_LOCATION, serviceLocationInfo);
},
// Misc order actions
saveServiceLocation(context, serviceLocationInfo) {
context.commit(storeMutations.UPDATE_SERVICE_LOCATION, serviceLocationInfo);
},
@ -816,18 +807,21 @@ export const actions = {
context.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, email);
},
saveVin(context, { isCarIdDifferent, isSelectedGlassAvailableForVehicle, vehicleInfo }) {
//Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
if (isCarIdDifferent && !isSelectedGlassAvailableForVehicle) {
context.dispatch(storeMutations.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
if (isCarIdDifferent && !isSelectedGlassAvailableForVehicle) {
context.dispatch(storeMutations.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
context.commit(storeMutations.UPDATE_VEHICLE, vehicleInfo);
}
context.dispatch(storeActions.UPDATE_VEHICLE_INFO, vehicleInfo);
},
savePartQuestionAnswers(context) {
// to be implemented later
saveGlassParts(context, parts) {
context.commit(storeMutations.UPDATE_GLASS_PARTS, parts);
},
saveGlassParts(context) {
// to be implemented later
clearVin(context) {
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
}
}