Merge branch 'develop' into feature/CSR-92 and fix / update unit tests
This commit is contained in:
commit
fef7a2227e
15 changed files with 530 additions and 140 deletions
|
|
@ -26,7 +26,6 @@ module.exports = {
|
||||||
"!src/common-components/dropdown-question/dropdown-question.vue",
|
"!src/common-components/dropdown-question/dropdown-question.vue",
|
||||||
"!src/common-components/textbox-question/textbox-question.vue",
|
"!src/common-components/textbox-question/textbox-question.vue",
|
||||||
"!src/helpers/validation-rules.js",
|
"!src/helpers/validation-rules.js",
|
||||||
"!src/helpers/damage-helper.js",
|
|
||||||
// END
|
// END
|
||||||
], //! means exclude from coverage.
|
], //! means exclude from coverage.
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,17 @@
|
||||||
import {getDamageString, isGlassAvailableForCarId} from "./damage-helper";
|
import {getDamageString, isGlassAvailableForCarId} from "./damage-helper";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
||||||
|
// Mock basemixin.
|
||||||
|
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||||
|
methods: {
|
||||||
|
dispatchStoreAction: jest.fn().mockImplementation(() => { return {
|
||||||
|
data: {
|
||||||
|
windshieldOptions: {availableReplacementOptions: ["windshield"]}
|
||||||
|
}
|
||||||
|
} }),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe("damage-helper.js", () => {
|
describe("damage-helper.js", () => {
|
||||||
it("Should return match when multiple selected damage options are in the store", () => {
|
it("Should return match when multiple selected damage options are in the store", () => {
|
||||||
|
|
||||||
|
|
@ -59,16 +69,7 @@ import store from "@/store";
|
||||||
// Arrange
|
// Arrange
|
||||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}];
|
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}];
|
||||||
|
|
||||||
const updatedOptions = {
|
|
||||||
data: {
|
|
||||||
windshieldOptions: {availableReplacementOptions: ["windshield"]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn().mockImplementation(()=> {
|
|
||||||
return updatedOptions;
|
|
||||||
});
|
|
||||||
const isGlassAvailable = await isGlassAvailableForCarId();
|
const isGlassAvailable = await isGlassAvailableForCarId();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
@ -79,18 +80,8 @@ import store from "@/store";
|
||||||
describe("damage-helper.js", () => {
|
describe("damage-helper.js", () => {
|
||||||
it("Should return false if any mismatches between each array exist", async () => {
|
it("Should return false if any mismatches between each array exist", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}];
|
store.getters.damage.glassToReplace = [{location: "Windshield", name: "sideWindow"}];
|
||||||
|
|
||||||
const updatedOptions = {
|
|
||||||
data: {
|
|
||||||
windshieldOptions: {availableReplacementOptions: ["Crack"]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Act
|
|
||||||
baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn().mockImplementation(()=> {
|
|
||||||
return updatedOptions;
|
|
||||||
});
|
|
||||||
const isGlassAvailable = await isGlassAvailableForCarId();
|
const isGlassAvailable = await isGlassAvailableForCarId();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ async function getLatestPageForRedirection() {
|
||||||
if (store.getters.vehicle.vin) {
|
if (store.getters.vehicle.vin) {
|
||||||
return fmgPageValues.LICENSE_PLATE_LOOKUP;
|
return fmgPageValues.LICENSE_PLATE_LOOKUP;
|
||||||
} else {
|
} else {
|
||||||
return fmgPageValues.VIN_LOOKUP;
|
return fmgPageValues.ESTIMATE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ describe("getPageToRouteExistingOrderTo", () => {
|
||||||
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
const result = await getPageToRouteExistingOrderTo(toRoute, false);
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(result).toBe('vin-lookup');
|
expect(result).toBe('estimate');
|
||||||
});
|
});
|
||||||
|
|
||||||
test("getPageToRouteExistingOrderTo, existing order, should return heritage", async () => {
|
test("getPageToRouteExistingOrderTo, existing order, should return heritage", async () => {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ export function getMountOptions(mockData) {
|
||||||
mocks.pushPageViewToGA = jest.fn();
|
mocks.pushPageViewToGA = jest.fn();
|
||||||
mocks.logEvent = jest.fn();
|
mocks.logEvent = jest.fn();
|
||||||
mocks.pushExperimentsToDataLayer = jest.fn();
|
mocks.pushExperimentsToDataLayer = jest.fn();
|
||||||
|
mocks.prependActionToMethod = jest.fn();
|
||||||
|
|
||||||
mocks.dispatchStoreAction = jest.fn();
|
mocks.dispatchStoreAction = jest.fn();
|
||||||
mocks.dispatchStoreAction.mockImplementation((actionName) => {
|
mocks.dispatchStoreAction.mockImplementation((actionName) => {
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ import store from "@/store";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||||
|
|
||||||
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { validate } from "vee-validate";
|
|
||||||
|
|
||||||
// Mock our module for promises.
|
// Mock our module for promises.
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
|
@ -146,24 +143,19 @@ describe("license-plate-lookup.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("license-plate-lookup.vue", () => {
|
describe("license-plate-lookup.vue", () => {
|
||||||
test("Navigate forward should be called when data entered matches store data", async () => {
|
test("Navigate forward should be called and isCarId should be set to false when data entered matches store data on forwardButtonAction click", async () => {
|
||||||
|
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks({
|
const { wrapper } = setupMocks({});
|
||||||
pageHeaderWidgetHeaderText: "",
|
|
||||||
mountOptionsMockData: {
|
|
||||||
router: { navigateAfterSave: jest.fn(), },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
wrapper.vm.licensePlate = "TESTPLATE";
|
|
||||||
wrapper.vm.registrationZip = "12345";
|
|
||||||
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||||
return {data: {isServiceable: true}};
|
return {data: {isServiceable: true}};
|
||||||
});
|
});
|
||||||
|
const vinLookup = {data: {vehicle: {carId: "TESTID"}}}
|
||||||
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||||
return {data: {vehicle: {carId: 'TESTID'}}, catch: () => "test"};
|
return {catch: () => vinLookup};
|
||||||
});
|
});
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
licensePlateLookup.beforeRouteEnter.call(
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
|
@ -176,11 +168,255 @@ describe("license-plate-lookup.vue", () => {
|
||||||
await wrapper.vm.forwardButtonAction();
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||||
expect(wrapper.vm.isCarIdDifferent).toEqual(false);
|
expect(wrapper.vm.isCarIdDifferent).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
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.$refs.funnelFooter.removeLoader = jest.fn();
|
||||||
|
//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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
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({});
|
||||||
|
|
||||||
|
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||||
|
return {data: {isServiceable: true}};
|
||||||
|
});
|
||||||
|
const vinLookup = {data: {vehicle: {carId: "TESTID1"}}}
|
||||||
|
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||||
|
return {catch: () => vinLookup};
|
||||||
|
});
|
||||||
|
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isCarIdDifferent).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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({});
|
||||||
|
|
||||||
|
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||||
|
return {data: {isServiceable: true}};
|
||||||
|
});
|
||||||
|
const vinLookup = {data: {vehicle: {carId: "TESTID1"}}}
|
||||||
|
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||||
|
return {catch: () => vinLookup};
|
||||||
|
});
|
||||||
|
wrapper.vm.previouslyEnteredCarId = "TESTID1";
|
||||||
|
wrapper.vm.navigateForward = jest.fn();
|
||||||
|
|
||||||
|
//Act
|
||||||
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.isCarIdDifferent).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("Button Text should revert to initial value when licensePlate textfield has new text", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.licensePlate = "NEWPLATE";
|
||||||
|
wrapper.vm.getCmsContent = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("Button Text should revert to initial value when registrationZip textfield has new text", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.registrationZip = "55555";
|
||||||
|
wrapper.vm.getCmsContent = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("Button Text should revert to initial value when serviceZip textfield has new text", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.serviceZip = "55555";
|
||||||
|
wrapper.vm.getCmsContent = jest.fn();
|
||||||
|
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
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
|
||||||
|
wrapper.vm.isCarIdDifferent = true;
|
||||||
|
wrapper.vm.isSelectedGlassAvailableForVehicle = false;
|
||||||
|
store.commit = jest.fn();
|
||||||
|
store.dispatch = jest.fn();
|
||||||
|
|
||||||
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
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(store.dispatch).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("NavigateAfterSave should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when navigateForward is called", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.isCarIdDifferent = true;
|
||||||
|
wrapper.vm.isSelectedGlassAvailableForVehicle = false;
|
||||||
|
wrapper.vm.$router.navigateAfterSave = jest.fn();
|
||||||
|
store.dispatch = jest.fn();
|
||||||
|
|
||||||
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
await wrapper.vm.navigateForward();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("navigateAfterSaveToHeritageFunnel should be called if isCarIdDifferent is false or isSelectedGlassAvailableForVehicle is true when navigateForward is called", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.isCarIdDifferent = false;
|
||||||
|
wrapper.vm.$router.navigateAfterSaveToHeritageFunnel = jest.fn();
|
||||||
|
|
||||||
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
await wrapper.vm.navigateForward();
|
||||||
|
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSaveToHeritageFunnel).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("dispatch non blocking store action called on validate zip", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.validateZip("12345");
|
||||||
|
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("license-plate-lookup.vue", () => {
|
||||||
|
test("dispatch non blocking store action called on lookup vin", async () => {
|
||||||
|
|
||||||
|
// Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.lookupVin("zzz123fqsfwg");
|
||||||
|
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function setupMocks({
|
function setupMocks({
|
||||||
|
|
@ -189,6 +425,8 @@ function setupMocks({
|
||||||
router: {
|
router: {
|
||||||
navigate: jest.fn(),
|
navigate: jest.fn(),
|
||||||
},
|
},
|
||||||
|
licensePlate: "TESTPLATE",
|
||||||
|
registrationZip: "12345"
|
||||||
},
|
},
|
||||||
}) {
|
}) {
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,45 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
>
|
>
|
||||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
<div
|
||||||
|
class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5"
|
||||||
|
>
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="false"
|
||||||
|
/>
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="LicensePlateNumber" v-model="licensePlate" isRequired inputId="license_plate" validationRules="license-plate-required" />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="LicensePlateNumber"
|
||||||
|
v-model="licensePlate"
|
||||||
|
isRequired
|
||||||
|
inputId="license_plate"
|
||||||
|
validationRules="license-plate-required"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="RegistrationZip" v-model="registrationZip" isRequired inputId="zip" mask="#####" validationRules="zip-required" />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="RegistrationZip"
|
||||||
|
v-model="registrationZip"
|
||||||
|
inputId="zip"
|
||||||
|
mask="#####"
|
||||||
|
validationRules="zip-required"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" isRequired inputId="email" validationRules="email-address-required|email-address-format" />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="EmailAddress"
|
||||||
|
v-model="email"
|
||||||
|
inputId="email"
|
||||||
|
validationRules="email-address-required|email-address-format"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<alert
|
<alert
|
||||||
|
|
@ -33,7 +55,13 @@
|
||||||
/>
|
/>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion v-if="!isRegistrationZipServicable" cmsWidgetName="ServiceZip" v-model="serviceZip" inputId="serviceZip" validationRules="zip-required" />
|
<textboxQuestion
|
||||||
|
v-if="!isRegistrationZipServicable"
|
||||||
|
cmsWidgetName="ServiceZip"
|
||||||
|
v-model="serviceZip"
|
||||||
|
inputId="serviceZip"
|
||||||
|
validationRules="zip-required"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<alert
|
<alert
|
||||||
|
|
@ -68,7 +96,6 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
|
@ -77,24 +104,35 @@ import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
import {
|
||||||
|
getDamageString,
|
||||||
|
isGlassAvailableForCarId,
|
||||||
|
} from "@/helpers/damage-helper";
|
||||||
import { required, regex } from "@/helpers/validation-rules";
|
import { required, regex } from "@/helpers/validation-rules";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
|
defineRule(
|
||||||
|
"license-plate-required",
|
||||||
|
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
||||||
|
);
|
||||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
||||||
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
defineRule(
|
||||||
defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT));
|
"email-address-required",
|
||||||
|
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||||
|
);
|
||||||
|
defineRule(
|
||||||
|
"email-address-format",
|
||||||
|
regex(
|
||||||
|
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/,
|
||||||
|
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||||
|
)
|
||||||
|
);
|
||||||
export default {
|
export default {
|
||||||
name: "license-plate-lookup",
|
name: "license-plate-lookup",
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
|
|
@ -102,9 +140,7 @@ export default {
|
||||||
promise: cmsContentPromise,
|
promise: cmsContentPromise,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
|
@ -122,25 +158,47 @@ export default {
|
||||||
registrationZip: this.getRegistrationZipFromStore(),
|
registrationZip: this.getRegistrationZipFromStore(),
|
||||||
email: this.getEmailFromStore(),
|
email: this.getEmailFromStore(),
|
||||||
serviceZip: this.getServiceZipFromStore(),
|
serviceZip: this.getServiceZipFromStore(),
|
||||||
previouslyEnteredCarId: '',
|
previouslyEnteredCarId: "",
|
||||||
customAlertData: {},
|
customAlertData: {},
|
||||||
isSelectedGlassAvailableForVehicle: true,
|
isSelectedGlassAvailableForVehicle: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.attachCustomEvents();
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
MatchedDifferentVehicleAlertHeader() {
|
MatchedDifferentVehicleAlertHeader() {
|
||||||
let text = this.getCmsContent("MatchedDifferentVehicleAlertWidget", "HeadlineText").replaceAll("{custom:damage}", getDamageString());
|
let text = this.getCmsContent(
|
||||||
|
"MatchedDifferentVehicleAlertWidget",
|
||||||
|
"HeadlineText"
|
||||||
|
).replaceAll("{custom:damage}", getDamageString());
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
MatchedDifferentVehicleAlertBody() {
|
MatchedDifferentVehicleAlertBody() {
|
||||||
let text = this.getCmsContent("MatchedDifferentVehicleAlertWidget", "BodyText").replaceAll("{custom:damage}", getDamageString()).replaceAll("{custom:plateLookupYear}", this.customAlertData?.vehicleInfo?.year).replaceAll("{custom:plateLookupMake}", this.customAlertData?.vehicleInfo?.make).replaceAll("{custom:plateLookupModel}", this.customAlertData?.vehicleInfo?.model);
|
let text = this.getCmsContent(
|
||||||
|
"MatchedDifferentVehicleAlertWidget",
|
||||||
|
"BodyText"
|
||||||
|
)
|
||||||
|
.replaceAll("{custom:damage}", getDamageString())
|
||||||
|
.replaceAll(
|
||||||
|
"{custom:plateLookupYear}",
|
||||||
|
this.customAlertData?.vehicleInfo?.year
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
"{custom:plateLookupMake}",
|
||||||
|
this.customAlertData?.vehicleInfo?.make
|
||||||
|
)
|
||||||
|
.replaceAll(
|
||||||
|
"{custom:plateLookupModel}",
|
||||||
|
this.customAlertData?.vehicleInfo?.model
|
||||||
|
);
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
NoServiceZipHeader() {
|
NoServiceZipHeader() {
|
||||||
let text = this.getCmsContent("NoServiceZipWidget", "HeadlineText").replaceAll("{custom:zip}", this.registrationZip);
|
let text = this.getCmsContent(
|
||||||
|
"NoServiceZipWidget",
|
||||||
|
"HeadlineText"
|
||||||
|
).replaceAll("{custom:zip}", this.registrationZip);
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
NoServiceZipBody() {
|
NoServiceZipBody() {
|
||||||
|
|
@ -158,26 +216,35 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null);
|
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null);
|
||||||
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
|
attachCustomEvents() {
|
||||||
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
|
this.GaActions.SUBMITTED,
|
||||||
|
this.GaLabels.LICENSE_PLATE_LOOKUP,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
getLicensePlateFromStore() {
|
getLicensePlateFromStore() {
|
||||||
return store.getters.vehicle.registration.licensePlate
|
return store.getters.vehicle.registration.licensePlate;
|
||||||
},
|
},
|
||||||
getRegistrationZipFromStore() {
|
getRegistrationZipFromStore() {
|
||||||
return store.getters.vehicle.registration.zipCode
|
return store.getters.vehicle.registration.zipCode;
|
||||||
},
|
},
|
||||||
getEmailFromStore() {
|
getEmailFromStore() {
|
||||||
return store.getters.order.customer.emailAddress
|
return store.getters.order.customer.emailAddress;
|
||||||
},
|
},
|
||||||
getServiceZipFromStore() {
|
getServiceZipFromStore() {
|
||||||
return store.getters.order.serviceLocation.zip
|
return store.getters.order.serviceLocation.zip;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
|
const zipValidation = this.serviceZip
|
||||||
this.pushEventToGA(this.$route.query[this.queryStrings.FMG_PAGE], this.GaActions.SUBMITTED, this.GaLabels.LICENSE_PLATE_LOOKUP , true);
|
? await this.validateZip(this.serviceZip)
|
||||||
|
: await this.validateZip(this.registrationZip);
|
||||||
const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.registrationZip);
|
|
||||||
if (!zipValidation.data.isServiceable) {
|
if (!zipValidation.data.isServiceable) {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
this.isVinValid = true;
|
this.isVinValid = true;
|
||||||
|
|
@ -185,44 +252,58 @@ export default {
|
||||||
this.isCarIdDifferent = false;
|
this.isCarIdDifferent = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const vinLookup = await this.lookupVin(
|
||||||
const vinLookup = await this.lookupVin(this.licensePlate, zipValidation.data.state).catch(() => {
|
this.licensePlate,
|
||||||
|
zipValidation.data.state
|
||||||
|
).catch(() => {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
this.isVinValid = false;
|
this.isVinValid = false;
|
||||||
this.isCarIdDifferent = false;
|
this.isCarIdDifferent = false;
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
this.isCarIdDifferent =
|
||||||
this.isCarIdDifferent = vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
||||||
|
if (
|
||||||
if (this.isCarIdDifferent && (vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId)) {
|
this.isCarIdDifferent &&
|
||||||
|
vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId
|
||||||
|
) {
|
||||||
this.previouslyEnteredCarId = vinLookup.data.vehicle.carId;
|
this.previouslyEnteredCarId = vinLookup.data.vehicle.carId;
|
||||||
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
|
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
|
||||||
this.$refs.funnelFooter.updateButtonText(`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`);
|
this.$refs.funnelFooter.updateButtonText(
|
||||||
|
`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`
|
||||||
|
);
|
||||||
this.isVinValid = true;
|
this.isVinValid = true;
|
||||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vinLookup.data.vehicle.carId);
|
this.isSelectedGlassAvailableForVehicle =
|
||||||
|
await isGlassAvailableForCarId(vinLookup.data.vehicle.carId);
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.updateCustomerInfo(
|
||||||
this.updateStoreInfo(vinLookup.data.vin, vinLookup.data.vehicle, zipValidation.data.state);
|
vinLookup.data.vin,
|
||||||
|
vinLookup.data.vehicle,
|
||||||
|
zipValidation.data.state
|
||||||
|
);
|
||||||
this.navigateForward();
|
this.navigateForward();
|
||||||
},
|
},
|
||||||
navigateForward() {
|
navigateForward() {
|
||||||
if(this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle){
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
this.$router.navigateAfterSave(
|
||||||
return;
|
this.navigationScenarios.CLICKED_FORWARD,
|
||||||
} else {
|
this.$route,
|
||||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
{},
|
||||||
return;
|
{ displayVehicleChangeAlert: true },
|
||||||
}
|
{}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
this.$router.navigateAfterSaveToHeritageFunnel(this.$route);
|
||||||
|
return;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
validateZip(zip) {
|
validateZip(zip) {
|
||||||
return baseMixin.methods.dispatchStoreAction(
|
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||||
storeActions.VALIDATE_ZIP,
|
zip,
|
||||||
{ zip }
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
lookupVin(plate, state) {
|
lookupVin(plate, state) {
|
||||||
return baseMixin.methods.dispatchStoreAction(
|
return baseMixin.methods.dispatchStoreAction(
|
||||||
|
|
@ -230,9 +311,9 @@ export default {
|
||||||
{ licensePlate: plate, licenseState: state }
|
{ licensePlate: plate, licenseState: state }
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
updateStoreInfo(vin, vehicleInfo, registrationState) {
|
updateCustomerInfo(vin, vehicleInfo, registrationState) {
|
||||||
if(this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle){
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
}
|
}
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
||||||
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
||||||
|
|
@ -240,28 +321,34 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
||||||
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
||||||
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
|
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY,vehicleInfo.category);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicleInfo.imageUrl);
|
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL,vehicleInfo.imageUrl);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber);
|
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER,vehicleInfo.imageVifNumber);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageColor);
|
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR,vehicleInfo.imageColor);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate);
|
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE,this.licensePlate);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
|
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE,this.registrationZip);
|
||||||
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.serviceZip);
|
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP, this.serviceZip);
|
||||||
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
|
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
licensePlate() {
|
licensePlate() {
|
||||||
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
|
this.$refs.funnelFooter.updateButtonText(
|
||||||
},
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
registrationZip() {
|
);
|
||||||
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
|
|
||||||
},
|
|
||||||
serviceZip() {
|
|
||||||
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
registrationZip() {
|
||||||
|
this.$refs.funnelFooter.updateButtonText(
|
||||||
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
serviceZip() {
|
||||||
|
this.$refs.funnelFooter.updateButtonText(
|
||||||
|
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
Form,
|
Form,
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,8 @@ export default {
|
||||||
vm.$refs.backGlassOptions.initializeComponent(
|
vm.$refs.backGlassOptions.initializeComponent(
|
||||||
resultMap.damageOptions.backGlassOptions.availableReplacementOptions
|
resultMap.damageOptions.backGlassOptions.availableReplacementOptions
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
data(){
|
data(){
|
||||||
|
|
@ -149,10 +151,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted(){
|
mounted(){
|
||||||
if(this.$store.getters.vehicle.imageVifNumber){
|
this.attachCustomEvents();
|
||||||
this.pushEventToGA(this.GaCategories.EVOX, `${this.GaActions.VIF}_${this.$store.getters.vehicle.imageVifNumber}`,
|
|
||||||
this.$store.getters.vehicle.carId, true);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
|
|
@ -166,6 +165,13 @@ export default {
|
||||||
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
attachCustomEvents(){
|
||||||
|
if(this.$store.getters.vehicle.imageVifNumber){
|
||||||
|
this.pushEventToGA(this.GaCategories.EVOX, `${this.GaActions.VIF}_${this.$store.getters.vehicle.imageVifNumber}`,
|
||||||
|
this.$store.getters.vehicle.carId, true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
// route to move backwards
|
// route to move backwards
|
||||||
this.$router.navigate(
|
this.$router.navigate(
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { experimentUniverses } from "@/constants/experiments";
|
import { experimentUniverses } from "@/constants/experiments";
|
||||||
import { getDeviceIdValue, getSessionIdValue, getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
|
import { getDeviceIdValue, getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
@ -94,7 +94,6 @@ export default {
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
resetDependentState() {
|
resetDependentState() {
|
||||||
|
|
||||||
// Set
|
// Set
|
||||||
store.commit(storeMutations.UPDATE_MAKE, null);
|
store.commit(storeMutations.UPDATE_MAKE, null);
|
||||||
store.commit(storeMutations.UPDATE_MODEL, null);
|
store.commit(storeMutations.UPDATE_MODEL, null);
|
||||||
|
|
@ -106,7 +105,7 @@ export default {
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
yearQuestion,
|
yearQuestion,
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,26 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
>
|
>
|
||||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
<div
|
||||||
|
class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5"
|
||||||
|
>
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="false"
|
||||||
|
/>
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="VinNumber" v-model="vin" inputId="vin" isRequired disableAutoFill validationRules="vin-required|vin-format" :isDisabled=isVinFieldReadOnly />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="VinNumber"
|
||||||
|
v-model="vin"
|
||||||
|
inputId="vin"
|
||||||
|
isRequired
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="vin-required|vin-format"
|
||||||
|
:isDisabled="isVinFieldReadOnly"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
|
|
@ -21,12 +34,27 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="ServiceZIP" v-model="zip" inputId="zip" mask="#####" isRequired disableAutoFill validationRules="zip-required" />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="ServiceZIP"
|
||||||
|
v-model="zip"
|
||||||
|
inputId="zip"
|
||||||
|
mask="#####"
|
||||||
|
isRequired
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="zip-required"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row my-2">
|
<div class="row my-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" isRequired disableAutoFill validationRules="email-address-required|email-address-format" />
|
<textboxQuestion
|
||||||
|
cmsWidgetName="EmailAddress"
|
||||||
|
v-model="email"
|
||||||
|
inputId="email"
|
||||||
|
isRequired
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="email-address-required|email-address-format"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<alert
|
<alert
|
||||||
|
|
@ -76,7 +104,7 @@
|
||||||
<funnelFooter
|
<funnelFooter
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
ref="funnelFooter"
|
ref="funnelFooter"
|
||||||
:isDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction"
|
@ForwardClicked="forwardButtonAction"
|
||||||
/>
|
/>
|
||||||
|
|
@ -109,10 +137,22 @@ import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integratio
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
||||||
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
defineRule(
|
||||||
defineRule("email-address-format", regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/, errorMessages.EMAIL_ADDRESS_FORMAT));
|
"email-address-required",
|
||||||
|
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||||
|
);
|
||||||
|
defineRule(
|
||||||
|
"email-address-format",
|
||||||
|
regex(
|
||||||
|
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/,
|
||||||
|
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||||
|
)
|
||||||
|
);
|
||||||
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
|
defineRule("vin-required", required(errorMessages.VIN_REQUIRED));
|
||||||
defineRule("vin-format", regex(/^[A-HJ-NPR-Z0-9]{17}$/, errorMessages.VIN_FORMAT));
|
defineRule(
|
||||||
|
"vin-format",
|
||||||
|
regex(/^[A-HJ-NPR-Z0-9]{17}$/, errorMessages.VIN_FORMAT)
|
||||||
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "vin-lookup",
|
name: "vin-lookup",
|
||||||
|
|
@ -120,7 +160,6 @@ export default {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
|
|
@ -211,12 +250,20 @@ export default {
|
||||||
getZipFromStore(){
|
getZipFromStore(){
|
||||||
return store.getters.vehicle.registration.zipCode
|
return store.getters.vehicle.registration.zipCode
|
||||||
},
|
},
|
||||||
|
attachCustomEvents() {
|
||||||
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
|
this.GaActions.SUBMITTED,
|
||||||
|
this.GaLabels.VINLOOKUP,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
this.pushEventToGA(this.$route.query[this.queryStrings.FMG_PAGE], this.GaActions.SUBMITTED, this.GaLabels.VINLOOKUP , true);
|
|
||||||
|
|
||||||
const zipValidation = await this.validateZip(this.zip);
|
const zipValidation = await this.validateZip(this.zip);
|
||||||
if (!zipValidation.data.isServiceable) {
|
if (!zipValidation.data.isServiceable) {
|
||||||
this.customAlertData.zip = this.zip;
|
this.customAlertData.zip = this.zip;
|
||||||
|
|
@ -257,10 +304,9 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
validateZip(zip) {
|
validateZip(zip) {
|
||||||
return baseMixin.methods.dispatchStoreAction(
|
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||||
storeActions.VALIDATE_ZIP,
|
zip,
|
||||||
{ zip }
|
});
|
||||||
);
|
|
||||||
},
|
},
|
||||||
lookupVehicle(vin) {
|
lookupVehicle(vin) {
|
||||||
return baseMixin.methods.dispatchStoreAction(
|
return baseMixin.methods.dispatchStoreAction(
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,15 @@ export default {
|
||||||
// Push to the data layer with the Google Custom Dimension Index.
|
// Push to the data layer with the Google Custom Dimension Index.
|
||||||
pushToDataLayerIfDefined(experimentWithDimension);
|
pushToDataLayerIfDefined(experimentWithDimension);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
|
prependActionToMethod(object, method, actionToPrepend) {
|
||||||
|
const baseMethod = object[method.name];
|
||||||
|
object[method.name] = function () {
|
||||||
|
actionToPrepend.apply(this, arguments);
|
||||||
|
return baseMethod.apply(object, arguments);
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
analyticsPageEvents() {
|
analyticsPageEvents() {
|
||||||
|
|
@ -96,7 +104,7 @@ export default {
|
||||||
GaLabels() {
|
GaLabels() {
|
||||||
return GaLabels;
|
return GaLabels;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function pushToDataLayerIfDefined(data) {
|
function pushToDataLayerIfDefined(data) {
|
||||||
|
|
|
||||||
|
|
@ -79,5 +79,4 @@ describe("analyticsMixin.js", () => {
|
||||||
expect(window.dataLayer).toEqual([ { settings_5: {"Google Custom Dimension Index": "5"}, variationName_5: 'test', universeName_5: 'testUniverse' } ]);
|
expect(window.dataLayer).toEqual([ { settings_5: {"Google Custom Dimension Index": "5"}, variationName_5: 'test', universeName_5: 'testUniverse' } ]);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -126,6 +126,7 @@ const router = createRouter({
|
||||||
router.afterEach(async (to, from) => {
|
router.afterEach(async (to, from) => {
|
||||||
// Push page view to GA
|
// Push page view to GA
|
||||||
analyticsMixin.methods.pushPageViewToGA(to.query[queryStrings.FMG_PAGE]);
|
analyticsMixin.methods.pushPageViewToGA(to.query[queryStrings.FMG_PAGE]);
|
||||||
|
|
||||||
const assignedExperiments = await baseMixin.methods.dispatchStoreAction(storeActions.GET_EXPERIMENTS_BY_USER_FOR_GA, { userId: getDeviceIdValue() });
|
const assignedExperiments = await baseMixin.methods.dispatchStoreAction(storeActions.GET_EXPERIMENTS_BY_USER_FOR_GA, { userId: getDeviceIdValue() });
|
||||||
analyticsMixin.methods.pushExperimentsToDataLayer(assignedExperiments);
|
analyticsMixin.methods.pushExperimentsToDataLayer(assignedExperiments);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,21 @@ describe("alert.vue", () => {
|
||||||
expect(wrapperDiv.classes()).toContain('warning')
|
expect(wrapperDiv.classes()).toContain('warning')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should update alert Headline to manualHeadline datam entered and alert copy to manualCopy datam entered when no cmsWidgetName entered", async () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(alert, {
|
||||||
|
propsData: {
|
||||||
|
manualHeadline: 'testHeader',
|
||||||
|
manualCopy: 'testCopy'
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.alertHeadline).toBe("testHeader");
|
||||||
|
expect(wrapper.vm.alertCopy).toBe("testCopy");
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockMixin = {
|
const mockMixin = {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue