Merge remote-tracking branch 'origin/feature/CASH-532v2' into feature/CASH-532v2

This commit is contained in:
Johnny shultz 2025-05-13 16:50:07 -04:00
commit 477492ff35
101 changed files with 2326 additions and 1848 deletions

View file

@ -36,9 +36,6 @@ export default {
loadingModal,
funnelFooter,
},
mounted() {
showFmgLoadingModal(true);
},
};
// Add a global Javascript exception handler for logging exceptions, this handler will log when there is an uncaught exception

View file

@ -6,7 +6,6 @@ const applicationConfig = {
COOKIE_PATH: "/",
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
APPLICATION_NAME: "FixMyGlass",
ANALYTICS_APPLICATION_NAME: "FixMyGlassNextGen",
APPLICATION_ABBREVIATION: "fmg",
@ -16,12 +15,21 @@ const applicationConfig = {
CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER: "87291",
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
PIA_RESPONSE_URL:
location.protocol + "//" + location.host + "/fmg/payment-pia-return?src=concept-funnel",
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-pia-return&src=concept-funnel",
PIA_CANCEL_URL:
location.protocol + "//" + location.host + "/fmg/payment-method?src=concept-funnel",
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-method&src=concept-funnel",
PIA_ERROR_URL:
location.protocol + "//" + location.host + "/fmg/payment-pia-return?src=concept-funnel",
CONFIRMATION_URL: location.protocol + "//" + location.host + "/fmg/confirmation",
location.protocol +
"//" +
location.host +
"/fmg/?fmgPage=payment-pia-return&src=concept-funnel",
CONFIRMATION_URL: location.protocol + "//" + location.host + "/fmg/?fmgPage=confirmation",
GOOGLE_CALENDAR: "https://www.google.com/calendar/render?action=TEMPLATE",
YAHOO_CALENDAR: "https://calendar.yahoo.com/?v=60",
OUTLOOK_CALENDAR:
@ -30,7 +38,7 @@ const applicationConfig = {
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
SESSION_TIMEOUT_MINUTES: process.env.VUE_APP_SESSION_TIMEOUT_MINUTES,
RETURN_USER_PAGE: "/fmg/return-user",
RETURN_USER_PAGE: "/fmg/?fmgPage=return-user",
};
export { applicationConfig };

View file

@ -117,7 +117,6 @@ const storeActions = {
UPDATE_EXTERNAL_PARAMETER_MMS: "updateExternalParameterMMS",
SAVE_LOGGING_OPTION: "saveLoggingOption",
UPDATE_HAS_TRIGGERED_ERROR: "updateHasTriggeredError",
};
export { storeActions };

View file

@ -94,7 +94,6 @@ const storeMutations = {
UPDATE_SAVE_SESSION_PROMISE: "updateSaveSessionPromise",
UPDATE_LAST_PAGE_VISITED: "updateLastPageVisited",
UPDATE_LOGGING_OPTION: "updateLoggingOption",
UPDATE_HAS_TRIGGERED_ERROR: "updateHasTriggeredError",
// EXPERIMENT MUTATIONS
UPDATE_EXPERIMENTS: "updateExperiments",

View file

@ -1143,7 +1143,7 @@ describe("buttonQuestion.vue", () => {
});
function setupMocks(mountOptionsMockData = {}) {
const defaultMountOptions = { route: { name: "page-name" } };
const defaultMountOptions = { route: { query: { fmgPage: "page-name" } } };
const baseMountOptions = getMountOptions(
Object.assign(defaultMountOptions, mountOptionsMockData)
);

View file

@ -1042,6 +1042,9 @@ export default {
min-width: 3rem;
width: 3rem;
}
&:hover {
border: 2px solid $blue;
}
}
}
&.unavailable-day {
@ -1083,7 +1086,6 @@ export default {
}
input[type="radio"]:checked + label:after {
background-color: $black;
top: 2rem;
}
}
}

View file

@ -46,7 +46,9 @@
</template>
<script>
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import analyticsMixin from "@/mixins/analytics-mixin";
import router from "@/router/index.js";
import modalButtonMain from "@/digital-components/modal/ux-components/modal-button-main/modal-button-main";
import { Modal } from "bootstrap";
import { useForm } from "vee-validate";
@ -89,7 +91,11 @@ export default {
const validationResult = await this.validate();
if (validationResult.valid) {
if (analyticsMixin.methods.sessionExpired()) {
this.$router.sendToReturnUser();
analyticsMixin.methods.initSession();
router.push({
path: "/",
query: { fmgPage: fmgPageValues.RETURN_USER },
});
} else {
this.$emit("footer-button-event");
}

View file

@ -58,7 +58,7 @@ export default {
getRouterLinkDisplayTextFromCopy,
getExternalLink,
navigateWithScenario(scenarioName) {
this.$router.navigateWithoutSaving(scenarioName, this.pageName);
this.$router.navigateWithoutSaving(scenarioName, this.$route);
},
},
computed: {

View file

@ -5,9 +5,6 @@ import store from "@/store";
describe("progressBar", () => {
test("progress should be 0", () => {
// Arrange
mockMixin.computed = {
pageName: () => undefined,
};
// Act
const wrapper = shallowMount(progressBar, {
@ -23,8 +20,10 @@ describe("progressBar", () => {
describe("progressBar", () => {
test("progress should be 4%", () => {
// Arrange
mockMixin.computed = {
pageName: () => "vehicle",
store.getters = {
applicationUser: {
lastPageVisited: "vehicle",
},
};
// Act
@ -41,8 +40,10 @@ describe("progressBar", () => {
describe("progressBar", () => {
test("progress should be 48%", () => {
// Arrange
mockMixin.computed = {
pageName: () => "quote",
store.getters = {
applicationUser: {
lastPageVisited: "quote",
},
};
// Act
@ -59,8 +60,10 @@ describe("progressBar", () => {
describe("progressBar", () => {
test("progress should be 100%", () => {
// Arrange
mockMixin.computed = {
pageName: () => "confirmation",
store.getters = {
applicationUser: {
lastPageVisited: "confirmation",
},
};
// Act

View file

@ -10,10 +10,15 @@ import { getProgressBarPercentage } from "@/constants/progress-bar-mapper";
export default {
name: "progressBar",
data() {},
computed: {
progress() {
return getProgressBarPercentage(this.pageName);
data() {
return {
progress: this.getProgress(),
};
},
methods: {
getProgress() {
var pageName = store.getters.applicationUser.lastPageVisited;
return getProgressBarPercentage(pageName);
},
},
};

View file

@ -245,7 +245,6 @@ function setupMocks() {
};
const mountOptions = getMountOptions({
mixins: [baseMixin, vehicleQuestionsMixin],
route: { name: "questions" },
});
mountOptions["attachTo"] = document.body;
const wrapper = shallowMount(questionsPageLayout, mountOptions);

View file

@ -45,7 +45,9 @@
<script>
import textLink from "@/ux-components/text-link/text-link";
import buttonMain from "@/ux-components/button-main/button-main";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import analyticsMixin from "@/mixins/analytics-mixin";
import router from "@/router/index.js";
export default {
name: "navbar",
@ -111,7 +113,12 @@ export default {
}
},
routeReturnUser() {
this.$router.sendToReturnUser();
analyticsMixin.methods.initSession();
router.push({
path: "/",
query: { fmgPage: fmgPageValues.RETURN_USER },
});
},
},
};

View file

@ -117,7 +117,7 @@ export default {
endpoint: endpoint,
};
router.bailout(errorPayload);
router.navigateError(errorPayload);
// do not log 404 errors from services because we return NotFound
// when a service doesn't return an object

View file

@ -38,7 +38,7 @@ it("Global Methods - Call Http Client - Should Reject Promise", () => {
isError: true,
});
analyticsMixIn.methods.pushEventToGA = jest.fn();
router.bailout = jest.fn();
router.navigateError = jest.fn();
//Act
globalMethods.callHttpClient(httpArgs).catch((err) => {

View file

@ -1,23 +0,0 @@
import store from "@/store";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { queryStrings } from "@/constants/query-strings";
import { storeActions } from "@/constants/store-actions";
export function debugLog(message, data, forceLog = false) {
checkLogParam();
if (store?.getters?.applicationUser?.loggingOption || forceLog) {
data = data ?? "";
const outData = typeof data === "object" ? JSON.stringify(data) : data;
console.log(`${new Date()} ${message} ${outData}`);
}
}
export function checkLogParam() {
const logQueryString = getQuerystringParameter(queryStrings.LOG);
if (logQueryString) {
store?.dispatch(storeActions?.SAVE_LOGGING_OPTION, logQueryString);
}
}

View file

@ -1,23 +1,123 @@
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { externalUrls } from "@/router/router-constants/externalUrl-values";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeActions } from "@/constants/store-actions.js";
import { settleAllPromises } from "@/helpers/layout-helper";
import experimentMixin from "@/mixins/experiment-mixin";
import { experimentSettings } from "@/constants/experiments";
import { includesWindshieldReplacement } from "@/helpers/damage-helper";
import { applicationConfig } from "@/constants/application-config.js";
import store from "@/store";
import router from "@/router";
import { debugLog } from "@/helpers/debug-log-helper";
export async function getPageToRouteExistingOrderTo(toRoute = {}) {
const fmgQueryPage = toRoute.query[queryStrings.FMG_PAGE];
const hasFmgQueryPage = !!fmgQueryPage;
if (hasFmgQueryPage) {
return await getDirectNavigation(toRoute);
} else {
return await getImplicitNavigation(toRoute);
}
}
/*
* Send the user to the specified page, except in specific scenarios.
*/
export async function getDirectNavigation(toRoute) {
const fmgPageValue = toRoute.query[queryStrings.FMG_PAGE];
// Verified insurance users need to be routed around some pages. Same goes for C&C unverified 6 digit referrals
// vehicle -> vehicle-damage
// quote -> vin-lookup/estimate
// insurance-company -> vin-lookup/estimate
if (
store.getters.payment?.insuranceCoverage?.isVerified ||
store.getters.order?.referralNumber?.length === 6
) {
if (fmgPageValue === fmgPageValues.VEHICLE) {
return fmgPageValues.VEHICLE_DAMAGE;
}
if (fmgPageValue === fmgPageValues.QUOTE) {
const skipVin = await skipVinLookup();
if (skipVin || !store.getters.vehicle?.vin) {
return fmgPageValues.ESTIMATE;
} else {
return fmgPageValues.VIN_LOOKUP;
}
}
}
// Otherwise, respect navigation from query string.
return fmgPageValue;
}
/*
* Determine which page in the flow the user should be sent to, based on their current order.
* General strategy: run through pages in reverse order, and select first where prerequisites are valid.
* QUOTE is the latest page to send to.
*/
export async function getImplicitNavigation(toRoute) {
const vehicleDamageComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_DAMAGE);
const estimateComponent = await getLazyLoadedComponent(fmgPageValues.ESTIMATE);
const vinLookupComponent = await getLazyLoadedComponent(fmgPageValues.VIN_LOOKUP);
const partQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.PART_QUESTIONS);
const vehiclePartsComponent = await getLazyLoadedComponent(fmgPageValues.VEHICLE_PARTS);
const moldingQuestionsComponent = await getLazyLoadedComponent(fmgPageValues.MOLDING_QUESTIONS);
const capabilityQuestionsComponent = await getLazyLoadedComponent(
fmgPageValues.CAPABILITY_QUESTIONS
);
const quoteComponent = await getLazyLoadedComponent(fmgPageValues.QUOTE);
const skipVin = await skipVinLookup();
if (store.getters.order.payment.insuranceCoverage?.isVerified) {
return fmgPageValues.HERITAGE;
}
if (quoteComponent.methods.arePagePrerequisitesValid()) {
// Do not send to quote if verified insurance user.
if (store.getters.requiresVerifiedRedirecting) {
return fmgPageValues.HERITAGE;
} else {
return fmgPageValues.QUOTE;
}
} else if (capabilityQuestionsComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.CAPABILITY_QUESTIONS;
} else if (moldingQuestionsComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.MOLDING_QUESTIONS;
} else if (vehiclePartsComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_PARTS;
} else if (partQuestionsComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.PART_QUESTIONS;
} else if (vinLookupComponent.methods.arePagePrerequisitesValid() && !skipVin) {
return fmgPageValues.VIN_LOOKUP;
} else if (estimateComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.ESTIMATE;
} else if (vehicleDamageComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_DAMAGE;
} else {
return fmgPageValues.VEHICLE;
}
}
/*
Used to navigate to the heritage funnel with the correct query string and url.
*/
export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLog, navType }) {
debugLog("--- Navigate to heritage start ---");
debugLog("applicationConfig:", applicationConfig);
debugLog("navigateToHeritageFunnel:", applicationConfig.HERITAGE_FUNNEL);
debugLog("--- Navigate to heritage end ---");
const log = getQuerystringParameter(queryStrings.LOG);
if (log === "true") {
console.log("------------- Navigate to heritage start -----------------");
console.log(new Date() + " applicationConfig: " + JSON.stringify(applicationConfig));
console.log(new Date() + " navigateToHeritageFunnel: " + applicationConfig.HERITAGE_FUNNEL);
console.log("------------- Navigate to heritage end -----------------");
}
// Create the order (or save existing order) when navigating to Heritage Funnel.
if (shouldSaveSession) {
@ -91,3 +191,7 @@ export async function skipVinLookupNotRepair() {
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
);
}
async function getLazyLoadedComponent(pageName) {
return (await lazyLoadComponent(pageName)()).default;
}

View file

@ -1,11 +1,12 @@
import * as navigationHelper from "@/helpers/heritage-integration/navigation-helper";
import * as orderHelper from "@/helpers/heritage-integration/order-helper";
import { lazyLoadComponent } from "@/router/methods/helpers/lazy-load-component";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { setupMocksForJsFiles, getMockOrderInfo } from "@/helpers/unit-test-helper.js";
import { externalUrls } from "@/router/constants/externalUrl-values";
import { externalUrls } from "@/router/router-constants/externalUrl-values";
import { queryStrings } from "@/constants/query-strings";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
@ -16,10 +17,476 @@ const getPageToRouteExistingOrderTo = navigationHelper.getPageToRouteExistingOrd
const navigateToHeritageFunnel = navigationHelper.navigateToHeritageFunnel;
// Mock Lazy Load
jest.mock("@/router/methods/helpers/lazy-load-component", () => ({
jest.mock("@/router/dynamic-routing/component-loader.js", () => ({
lazyLoadComponent: jest.fn(),
}));
describe("getPageToRouteExistingOrderTo", () => {
describe("Explicit vs. Implicit Routing", () => {
test("Should call explicit routing if `fmgPage` parameter is present in query", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: "schedule",
},
};
mockLazyLoadComponentReturnValues();
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
// If direct, should be "schedule".
// Otherwise, not.
expect(result).toBe("schedule");
});
test("Should call implicit routing if `fmgPage` parameter is NOT present in query", async () => {
// Arrange
const toRoute = {
query: {},
};
mockLazyLoadComponentReturnValues();
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
// If direct, should be "schedule".
// Otherwise, not.
expect(result).not.toBe("schedule");
});
});
describe("Implicit Routing", () => {
test("should return vehicle", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE);
});
test("should return vehicle-damage", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
});
test("user has YMMS and no vehicle questions > should return estimate", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
const mockExperimentsList = [
{
universeName: "ConceptFunnel",
settings: {
SuppressVinCapture: false,
},
},
];
store.commit(storeMutations.UPDATE_EXPERIMENTS, mockExperimentsList);
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: false,
[fmgPageValues.VIN_LOOKUP]: true,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.ESTIMATE);
});
test("user has YMMS but no questions or carId > should return estimate", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: false,
[fmgPageValues.VIN_LOOKUP]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.ESTIMATE);
});
test("user has capability questions and molding questions > should return capability questions", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: true,
[fmgPageValues.MOLDING_QUESTIONS]: true,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: false,
[fmgPageValues.VIN_LOOKUP]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.CAPABILITY_QUESTIONS);
});
test("user has molding questions and part questions > should return molding questions", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: true,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: true,
[fmgPageValues.VIN_LOOKUP]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.MOLDING_QUESTIONS);
});
test("user has vehicle parts questions > should return vehicle-parts", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: true,
[fmgPageValues.PART_QUESTIONS]: true,
[fmgPageValues.VIN_LOOKUP]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.VEHICLE_PARTS);
});
test("user has part questions > should return part-questions", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: true,
[fmgPageValues.VIN_LOOKUP]: false,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.PART_QUESTIONS);
});
test("should return quote, if not verified insurance", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: true,
[fmgPageValues.VIN_LOOKUP]: false,
[fmgPageValues.QUOTE]: true,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.QUOTE);
});
test("should not return pages beyond quote even if prerequisites are met", async () => {
// Arrange
const toRoute = {
query: {},
};
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Mock out the lazy load calls for all components.
mockLazyLoadComponentReturnValues({
[fmgPageValues.VEHICLE]: true,
[fmgPageValues.VEHICLE_DAMAGE]: true,
[fmgPageValues.ESTIMATE]: true,
[fmgPageValues.CAPABILITY_QUESTIONS]: false,
[fmgPageValues.MOLDING_QUESTIONS]: false,
[fmgPageValues.VEHICLE_PARTS]: false,
[fmgPageValues.PART_QUESTIONS]: true,
[fmgPageValues.VIN_LOOKUP]: false,
[fmgPageValues.QUOTE]: true,
[fmgPageValues.SERVICE_LOCATION]: true,
[fmgPageValues.SCHEDULE]: true,
});
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
//Assert
expect(result).toBe(fmgPageValues.QUOTE);
});
});
describe("Explicit Routing", () => {
test("Returns the value passed in in nominal case", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: "testValue",
},
};
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe("testValue");
});
describe("Verified users", () => {
test("Replace navigation to `vehicle` with `vehicle-damage`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.VEHICLE,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.VEHICLE_DAMAGE);
});
describe("Vin-Exempt", () => {
test("Replace navigation to `quote` with `estimate`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.QUOTE,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, true);
store.commit(storeMutations.UPDATE_MAKE, "acura");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.ESTIMATE);
});
});
describe("Vin-Required", () => {
test("Replace navigation to `quote` with `vin-lookup`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.QUOTE,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, true);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "666666");
store.commit(storeMutations.UPDATE_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_MAKE, "acura");
store.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, [
{ glassLocation: glassLocations.WINDSHIELD },
]);
store.commit(storeMutations.UPDATE_VEHICLE_VIN, "abcd1234");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.VIN_LOOKUP);
});
});
});
describe("Non-verified users", () => {
test("Don't replace navigation to `vehicle` with `vehicle-damage`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.VEHICLE,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.VEHICLE);
});
test("Don't replace navigation to `quote` with `estimate` or `vin-lookup`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.QUOTE,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.QUOTE);
});
test("Don't replace navigation to `insurance-company` with `estimate` or `vin-lookup`", async () => {
// Arrange
const toRoute = {
query: {
fmgPage: fmgPageValues.INSURANCE_COMPANY,
},
};
store.commit(storeMutations.UPDATE_IS_VERIFIED_INSURANCE, false);
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, "55555");
// Act
const result = await getPageToRouteExistingOrderTo(toRoute);
// Assert
expect(result).toBe(fmgPageValues.INSURANCE_COMPANY);
});
});
});
});
describe("navigateToHeritageFunnel", () => {
test("should save session", async () => {
// Arrange

View file

@ -59,15 +59,25 @@ export async function saveSession({
submitAfterSave = false,
createUnscheduledStatusWorkOrderForPIA = false,
}) {
// Add next save session to end of queue
const saveSessionPromise = flushSaveSessionQueue().then(() => {
return saveSessionHelper(
var saveSessionPromise;
if (store.getters.applicationUser.saveSessionPromise) {
// queue newest request after current saveSessionPromise resolves
saveSessionPromise = store.getters.applicationUser.saveSessionPromise.then(() => {
// get a new saveSessionPromise
return saveSessionHelper(
pageNameToLog,
submitAfterSave,
createUnscheduledStatusWorkOrderForPIA
);
});
} else {
// create an initial saveSessionPromise
saveSessionPromise = saveSessionHelper(
pageNameToLog,
submitAfterSave,
createUnscheduledStatusWorkOrderForPIA
);
});
}
store.commit(storeMutations.UPDATE_SAVE_SESSION_PROMISE, saveSessionPromise);
// await here to allow for a caller to await and make the function synchronous
if (!store.getters.applicationUser.savedSessionId || shouldAwaitSaveSessionQueue) {
@ -123,7 +133,7 @@ async function loadSession(
pageNameToLog
) {
// await the saveSessionPromise in the store to make sure we're loading up to date information
await flushSaveSessionQueue();
await store.getters.applicationUser.saveSessionPromise;
const response = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.LOAD_SESSION,
@ -183,7 +193,3 @@ async function saveSessionHelper(
// Update the cookie with the referral information when saved.
updateOrCreateFunnelCookie();
}
export async function flushSaveSessionQueue() {
return Promise.resolve(store.getters.applicationUser.saveSessionPromise);
}

View file

@ -1,7 +1,8 @@
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { cookieNames } from "@/constants/cookie-names";
import { Form } from "vee-validate";
import baseMixin from "@/mixins/base-mixin";
@ -18,6 +19,7 @@ import {
ValueToLogTypes,
} from "@/constants/analytics";
import { queryStrings } from "@/constants/query-strings";
import { routerParams } from "@/router/router-constants/router-params";
// Common methods
export function getMountOptions(mockData) {
@ -58,6 +60,7 @@ export function getMountOptions(mockData) {
mocks.storeMutations = storeMutations;
mocks.navigationScenarios = navigationScenarios;
mocks.vehicleCategories = vehicleCategories;
mocks.fmgPageValues = fmgPageValues;
mocks.analyticsPageEvents = analyticsPageEvents;
mocks.GaCategories = GaCategories;
mocks.GaActions = GaActions;
@ -65,6 +68,7 @@ export function getMountOptions(mockData) {
mocks.GaEvents = GaEvents;
mocks.ValueToLogTypes = ValueToLogTypes;
mocks.queryStrings = queryStrings;
mocks.routerParams = routerParams;
// Mock $store and $router when accessing this.$store/$router
mocks.$store = mockData.store;
@ -76,11 +80,6 @@ export function getMountOptions(mockData) {
mocks: mocks,
mixins: mockData.mixins,
stubs: { Form },
computed: {
pageName() {
return mockData?.route?.name;
},
},
};
const props = mockData.propsData || {};

View file

@ -7,7 +7,7 @@ import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import store from "@/store";
import { experimentSettings } from "@/constants/experiments";
@ -308,9 +308,11 @@ describe("address-lookup.vue", () => {
await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
undefined,
{},
{},
carsFound
);
});
@ -397,7 +399,9 @@ describe("address-lookup.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
undefined
undefined,
{},
{ displayVehicleChangeAlert: true }
);
});
@ -713,7 +717,6 @@ function setupMocks({
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
store: {
getters: {

View file

@ -118,11 +118,12 @@ import { errorMessages } from "@/constants/error-messages";
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 baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES - Note: Additional rules are defined in Customer Questions and Address Questions components
defineRule("service-zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -136,7 +137,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -192,10 +193,7 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
@ -411,7 +409,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.SERVICE_ZIP.name,
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.customerQuestions.emailOrSms },
},
false
@ -444,14 +442,18 @@ export default {
) {
this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else if (matchingCars.length === 1) {
await this.navigateForwardWithSingleCarMatch();
} else {
this.$router.navigateWithPageData(
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
this.pageName,
this.$route,
{},
{},
carsFound
);
}

View file

@ -60,7 +60,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { errorMessages } from "@/constants/error-messages";
import { required } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
@ -71,6 +71,7 @@ import {
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
@ -81,7 +82,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -143,7 +144,7 @@ export default {
return mappedData;
},
VehiclesFromApi() {
return store.getters.pageData(routeData.ADDRESS_VEHICLES.name);
return store.getters.pageData(fmgPageValues.ADDRESS_VEHICLES);
},
selectedVehicle() {
return this.VehiclesForQuestions.find(({ vin }) => vin === this.selectedVehicleVin);
@ -158,17 +159,14 @@ export default {
if (
store.getters.order.vehicle.carId &&
store.getters.order.serviceLocation.zipCode &&
store.getters.pageData(routeData.ADDRESS_VEHICLES.name)
store.getters.pageData(fmgPageValues.ADDRESS_VEHICLES)
) {
return true;
}
return false;
},
backButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
const vinLookup = await this.dispatchStoreActionWithLogging(
@ -207,7 +205,9 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -37,7 +37,7 @@ export default {
name: "bailout",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [

View file

@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -97,7 +97,7 @@ export default {
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
},
partsOrQuestionsData() {
return this.$store.getters.pageData(routeData.CAPABILITY_QUESTIONS.name)
return this.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)
.partsOrQuestions;
},
},
@ -107,7 +107,7 @@ export default {
methods: {
arePagePrerequisitesValid() {
const capabilityQuestionsPageData = store.getters.pageData(
routeData.CAPABILITY_QUESTIONS.name
fmgPageValues.CAPABILITY_QUESTIONS
);
return (
// has capabilityQuestions array and has glassName not null

View file

@ -123,7 +123,6 @@ import experimentMixin from "@/mixins/experiment-mixin.js";
import { containsRecalParts } from "@/helpers/recal-helper.js";
import donationBlock from "@/experiment-components/donation-block.vue";
import { partNumberStrings } from "@/constants/part-number-strings";
import analyticsMixin from "@/mixins/analytics-mixin";
export default {
name: "confirmation",
@ -180,7 +179,7 @@ export default {
// Call APIs
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_WIPERS,
@ -245,8 +244,6 @@ export default {
vm.showDonationSuccess = lineItemsFromSubmittedOrder.supportingItems?.some(
(item) => item.partType === partNumberStrings.DONATION
);
vm.pushAnalytics();
});
},
data() {
@ -559,16 +556,6 @@ export default {
this.$refs.donationBlock.removeLoader();
}
},
pushAnalytics() {
//Push Ecommerce Cart to Data Layer
analyticsMixin.methods.pushECommerceCartToDataLayer();
//Push Product Array to Data Layer
analyticsMixin.methods.pushProductArrayToDataLayer();
//Push Commission Junction Gtm Data To Data Layer
analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer();
},
},
components: {
funnelHeader,

View file

@ -84,7 +84,6 @@ import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
import store from "@/store";
import { paymentMethods } from "@/constants/payment-method-constants";
import { flushSaveSessionQueue } from "@/helpers/heritage-integration/order-helper";
// DEFINE VALIDATION RULES
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
@ -103,7 +102,7 @@ export default {
name: "customer-details",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -158,10 +157,7 @@ export default {
return store.getters.order.serviceLocation.techNotes;
},
backButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
this.dispatchStoreAction(
@ -190,13 +186,10 @@ export default {
paymentMethods.NONE,
false
);
await flushSaveSessionQueue();
await store.getters.applicationUser.saveSessionPromise;
}
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
},
components: {

View file

@ -215,7 +215,7 @@ describe("estimate.vue", () => {
});
describe("estimate.vue", () => {
test.skip("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
test("should call forwardButtonAction if isExternalParameter is true and form is valid", async () => {
store.getters = {
externalParameterState: { isExternalParameter: true },
externalParameterEstimate: { vinSelection: "decline" },
@ -263,7 +263,7 @@ function setupMocks({
navigateWithoutSaving: jest.fn(),
},
route: {
name: "estimate",
query: {},
},
},
}) {
@ -271,9 +271,7 @@ function setupMocks({
const cmsContent = {
groupName: groupName,
QuestionText: cmsQuestionText,
VinLookupMethod: {
Answers: cmsAnswers,
},
Answers: cmsAnswers,
FunnelFooterWidget: FunnelFooterWidget,
};
const mockMixin = {

View file

@ -62,7 +62,6 @@ import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { nextTick } from "vue";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -90,7 +89,7 @@ export default {
async beforeRouteEnter(to, from, next) {
//Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const queryString = window.location.search;
const urlParams = new URLSearchParams(queryString);
@ -99,9 +98,9 @@ export default {
lowerCaseParams.append(name.toLowerCase(), value);
}
const zip =
consumeQueryFromStash(queryStrings.ZIP_CODE) ??
store.getters.order.serviceLocation.zipCode;
const zip = lowerCaseParams.get(queryStrings.ZIP_CODE)
? lowerCaseParams.get(queryStrings.ZIP_CODE)
: store.getters.order.serviceLocation.zipCode;
var vinByAddressPromise;
if (zip) {
@ -185,35 +184,32 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
if (this.selectedVinLookupMethod === vinLookupMethodSelections.MANUALVIN) {
await this.dispatchStoreAction(storeActions.CLEAR_VIN);
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_MANUAL_VIN,
this.pageName
this.$route
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.LICENSEPLATE) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_LICENSE_PLATE,
this.pageName
this.$route
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.HOMEADDRESS) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_HOME_ADDRESS,
this.pageName
this.$route
);
}
if (this.selectedVinLookupMethod === vinLookupMethodSelections.DECLINE) {
return this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_NO_VIN,
this.pageName
this.$route
);
}
},

View file

@ -26,7 +26,6 @@ jest.mock("@/mixins/base-mixin.js", () => ({
return {
navigationScenarios: {
CLICKED_BACK: "clicked_back",
CLICKED_PAY_ON_MY_OWN: "clicked_pay_on_my_own",
},
};
},
@ -65,7 +64,7 @@ describe("insurance-company.vue", () => {
expect(wrapper.vm.isCashParentAccountNumber()).toBe(false);
});
test("should call navigateWithoutSaving with CLICKED_PAY_ON_MY_OWN when forceCashSelection is true", () => {
test("should call navigateWithoutSaving with { isCashSelected: true } when forceCashSelection is true", () => {
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
@ -78,8 +77,9 @@ describe("insurance-company.vue", () => {
wrapper.vm.backButtonAction(true);
expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith(
wrapper.vm.navigationScenarios.CLICKED_PAY_ON_MY_OWN,
wrapper.vm.$route
wrapper.vm.navigationScenarios.CLICKED_BACK,
wrapper.vm.$route,
{ isCashSelected: true }
);
});

View file

@ -58,7 +58,6 @@ import { experimentSettings } from "@/constants/experiments";
import { partNumberStrings } from "@/constants/part-number-strings";
import { deepClone } from "@/helpers/object-helper";
import store from "@/store";
import { flushSaveSessionQueue } from "@/helpers/heritage-integration/order-helper";
export default {
name: "insurance-company",
@ -82,7 +81,7 @@ export default {
}
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const insuranceCompanyListPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_INSURANCE_COMPANY_LIST,
{},
@ -147,20 +146,18 @@ export default {
// Go back to Quote page
if (forceCashSelectionOnQuote) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_PAY_ON_MY_OWN,
this.pageName
this.navigationScenarios.CLICKED_BACK,
this.$route,
{ isCashSelected: true }
);
return;
}
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
// await any pending save-sessions. if you don't, we will save the new parent account into vuex and then a pending async save-session response overwrites it
await flushSaveSessionQueue();
await store.getters.applicationUser.saveSessionPromise;
await this.dispatchStoreAction(
this.storeActions.SAVE_PARENT_ACCOUNT_NUMBER,

View file

@ -112,14 +112,13 @@ import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions";
import { errorMessages } from "@/constants/error-messages";
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
import { routerParams } from "@/router/router-constants/router-params";
import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { routeData } from "@/router/constants/routes";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { queryStrings } from "@/constants/query-strings";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES
defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIRED));
@ -139,7 +138,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -164,8 +163,7 @@ export default {
data() {
return {
licensePlate: this.getLicensePlateFromStore(),
registrationZipCode:
this.getRegistrationZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
registrationZipCode: this.getRegistrationZipFromStore() ?? this.$route.query.zipcode,
emailOrSms: this.getEmailOrSmsFromStore(),
serviceZipCode: this.getServiceZipFromStore(),
carId: this.getCarIdfromStore(),
@ -189,10 +187,7 @@ export default {
},
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => {
@ -366,7 +361,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.SERVICE_ZIP.name,
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.emailOrSms },
},
false
@ -397,7 +392,9 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -336,7 +336,6 @@ function setupMocks({
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
store: {
getters: store.getters,

View file

@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -112,7 +112,7 @@ export default {
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
},
partsOrQuestionsData() {
return this.$store.getters.pageData(routeData.MOLDING_QUESTIONS.name).partsOrQuestions;
return this.$store.getters.pageData(fmgPageValues.MOLDING_QUESTIONS).partsOrQuestions;
},
},
mounted() {
@ -121,7 +121,7 @@ export default {
methods: {
arePagePrerequisitesValid() {
const moldingQuestionsFromPageData = store.getters.pageData(
routeData.MOLDING_QUESTIONS.name
fmgPageValues.MOLDING_QUESTIONS
);
return (
// has childPartQuestions array and has glassName not null

View file

@ -32,7 +32,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
@ -47,7 +47,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -114,7 +114,7 @@ export default {
return this.getCmsContent("AlertPartsQuestions", "BodyText");
},
partsOrQuestionsData() {
return this.$store.getters.pageData(routeData.PART_QUESTIONS.name).partsOrQuestions;
return this.$store.getters.pageData(fmgPageValues.PART_QUESTIONS).partsOrQuestions;
},
},
mounted() {
@ -122,7 +122,7 @@ export default {
},
methods: {
arePagePrerequisitesValid() {
const partQuestionsFromPageData = store.getters.pageData(routeData.PART_QUESTIONS.name);
const partQuestionsFromPageData = store.getters.pageData(fmgPageValues.PART_QUESTIONS);
return (
// has .partQuestions array and has glassName not null
partQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName) &&

View file

@ -147,6 +147,7 @@ import {
getNewlyInactivatedPromos,
} from "@/helpers/promotions-helper";
import { queryStrings } from "@/constants/query-strings";
import { routerParams } from "@/router/router-constants/router-params";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { deepClone } from "@/helpers/object-helper";
@ -167,8 +168,6 @@ import {
getSubTotal,
getSalesTax,
} from "@/helpers/pricing-helper.js";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { debugLog } from "@/helpers/debug-log-helper";
defineRule("payment-method-required", required(errorMessages.OPTION_REQUIRED));
defineRule("recal-ack-required", required(errorMessages.RECAL_ACK_REQUIRED));
@ -180,7 +179,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const lineItemsFromStore = deepClone(store.getters.order.lineItems);
@ -282,7 +281,7 @@ export default {
const oldActivePromos = store.getters.lineItems.promos?.slice(0);
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
const promoCodeFromQueryString = consumeQueryFromStash(queryStrings.PROMO);
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateQueryStringPromo(
promoCodeFromQueryString,
@ -375,7 +374,7 @@ export default {
doesCopyContainRouterLink,
getRouterLinkRouteFromCopy,
navigateWithScenario(scenarioName) {
this.$router.navigateWithoutSaving(scenarioName, this.pageName);
this.$router.navigateWithoutSaving(scenarioName, this.$route);
},
arePagePrerequisitesValid() {
// Service Location
@ -441,25 +440,26 @@ export default {
// prettier-ignore
{
debugLog("--- payment-method.vue pagePrereqs start ---", null, !preReqResult);
debugLog("serviceLocationRequs::isMobile:", isMobile, !preReqResult);
debugLog("serviceLocationReqs::mobileReqs:", mobileReqs, !preReqResult);
debugLog("serviceLocationReqs::dropOffInshopReqs:", dropOffInshopReqs, !preReqResult);
debugLog("serviceLocationReqs:: result", serviceLocationReqs, !preReqResult);
debugLog("isInsuranceSet::", isInsuranceSet(), !preReqResult);
debugLog("scheduleReqs::schedule.date:", schedule.date, !preReqResult);
debugLog("scheduleReqs::schedule.startTime:", schedule.startTime, !preReqResult);
debugLog("scheduleReqs::schedule.endTime:", schedule.endTime, !preReqResult);
debugLog("scheduleReqs::schedule.jobMaxMinutes:", schedule.jobMaxMinutes, !preReqResult);
debugLog("scheduleReqs::schedule.jobMinMinutes:", schedule.jobMinMinutes, !preReqResult);
debugLog("customerReqs::customer.firstName:", customer.firstName, !preReqResult);
debugLog("customerReqs::customer.lastName:", customer.lastName, !preReqResult);
debugLog("customerReqs::customer.phoneNumber:", customer.phoneNumber, !preReqResult);
debugLog("customerReqs::customer.emailAddress:", customer.emailAddress, !preReqResult);
debugLog("--- payment-method.vue pagePrereqs end ---", null, !preReqResult);
const log = getQuerystringParameter(queryStrings.LOG);
const logAsBool = getBoolFromString(log);
if (logAsBool || !preReqResult) {
console.log("------------- payment-method.vue pagePrereqs start -----------------");
console.log(new Date() + " serviceLocationReqs::isMobile: " + isMobile);
console.log(new Date() + " serviceLocationReqs::mobileReqs: " + mobileReqs);
console.log(new Date() + " serviceLocationReqs::dropOffInshopReqs: " + dropOffInshopReqs);
console.log(new Date() + " serviceLocationReqs:: result " + serviceLocationReqs);
console.log(new Date() + " isInsuranceSet:: " + isInsuranceSet());
console.log(new Date() + " scheduleReqs::schedule.date:" + schedule.date);
console.log(new Date() + " scheduleReqs::schedule.startTime:" + schedule.startTime);
console.log(new Date() + " scheduleReqs::schedule.endTime:" + schedule.endTime);
console.log(new Date() + " scheduleReqs::schedule.jobMaxMinutes:" + schedule.jobMaxMinutes);
console.log(new Date() + " scheduleReqs::schedule.jobMinMinutes:" + schedule.jobMinMinutes);
console.log(new Date() + " customerReqs::customer.firstName:" + customer.firstName);
console.log(new Date() + " customerReqs::customer.lastName:" + customer.lastName);
console.log(new Date() + " customerReqs::customer.phoneNumber:" + customer.phoneNumber);
console.log(new Date() + " customerReqs::customer.emailAddress:" + customer.emailAddress);
console.log("------------- payment-method.vue pagePrereqs end -----------------");
}
}
return preReqResult;
@ -537,10 +537,7 @@ export default {
return this.$store.getters.order.isRecalAckOptIn;
},
backButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {
this.forwardClicked = true;
@ -578,14 +575,16 @@ export default {
await submitWorkOrder({ pageNameToLog: "payment-method", submitAfterSave: true });
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: false }
);
} else {
if (this.paymentMethod == paymentMethods.INSURANCE) {
this.dispatchStoreAction(this.storeActions.SAVE_PAYMENT_TYPE, true, false);
return this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_INSURANCE,
this.pageName
this.$route
);
} else {
this.setupPia();
@ -604,14 +603,16 @@ export default {
} catch (error) {
console.log("error: response from pia submit work order:" + error.message);
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$route.query.piaError = true;
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] = true;
return;
}
this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_PAY_NOW,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: false }
);
},
hasSubmittedOrder() {
@ -796,7 +797,10 @@ export default {
return this.paymentMethodInternalModel;
},
shouldDisplayPiaAlert() {
return getBoolFromString(this.$route?.query?.piaError);
return (
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] ||
getBoolFromString(window.history.state.displayPiaAlert)
);
},
// Necessary to make the watcher of lineItems work
// JavaScript does not keep a record of the old value, only a reference to it's location in the memory.

View file

@ -13,6 +13,7 @@ import store from "@/store";
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import { Form } from "vee-validate";
import { paymentMethods } from "@/constants/payment-method-constants";
import { routerParams } from "@/router/router-constants/router-params";
import baseMixin from "@/mixins/base-mixin.js";
import {
getDisplayAmountDue,
@ -38,22 +39,20 @@ export default {
store.getters.order.payment.piaType === paymentMethods.APPLE_PAY ||
store.getters.order.payment.piaType === paymentMethods.AFTERPAY;
if (paymentPageNavScenario) {
const scenarios = {
[paymentMethods.CREDIT_CARD]: this.navigationScenarios.PIA_CC_ERROR,
[paymentMethods.APPLE_PAY]: this.navigationScenarios.PIA_APPLE_ERROR,
[paymentMethods.AFTERPAY]: this.navigationScenarios.PIA_AFTERPAY_ERROR,
};
const relevantScenario = scenarios[store.getters.order.payment.piaType];
await this.$router.navigateAndForceTopLevelNavigation(
relevantScenario,
this.pageName
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_CC_ERROR,
this.$route,
{
[queryStrings.DISPLAY_PIA_ALERT]: store.getters.order.payment.piaType,
}
);
} else {
await this.$router.navigateAndForceTopLevelNavigation(
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
this.$route,
{
[queryStrings.DISPLAY_PIA_ALERT]: true,
}
);
}
} else {
@ -85,9 +84,11 @@ export default {
} else {
var msg = "Unknown Pia type: " + store.getters.order.payment.piaType;
console.log(msg);
await this.$router.navigateAndForceTopLevelNavigation(
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
);
}
}
@ -122,9 +123,11 @@ export default {
" " +
store.getters.order.referralSequenceNumber
);
this.$router.navigateAndForceTopLevelNavigation(
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
);
} else {
const expMonth = getQuerystringParameter(queryStrings.CARD_EXPIRATION_MONTH);
@ -178,9 +181,11 @@ export default {
});
} catch (error) {
console.log("error: response from submit work order:" + error.message);
this.$router.navigateAndForceTopLevelNavigation(
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
);
this.$refs.loadingModal.isModalVisible = false;
return;
@ -188,10 +193,7 @@ export default {
this.$refs.loadingModal.isModalVisible = false;
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.PIA_SUCCESS,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route);
},
},
components: {

View file

@ -599,13 +599,7 @@ describe("payment.vue", () => {
function setupMocks({ customMountOptions }) {
const mountOptions = getMountOptions({
...customMountOptions,
route: { name: "payment-method" },
router: {
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
navigateAndForceTopLevelNavigation: jest.fn(),
},
route: { query: { fmgPage: "page-name" }, params: {} },
});
// set all mock stuff

View file

@ -213,6 +213,7 @@ import alert from "@/ux-components/alert/alert";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { externalUrls } from "@/router/router-constants/externalUrl-values";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { applicationConfig } from "@/constants/application-config";
@ -230,6 +231,7 @@ import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { deepClone } from "@/helpers/object-helper";
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
import iframeResize from "../../../node_modules/iframe-resizer/js/iframeResizer.js";
import { routerParams } from "@/router/router-constants/router-params";
import { coverageStatus } from "@/constants/insurance";
import { getBoolFromString } from "@/helpers/boolean-helper.js";
import {
@ -238,13 +240,12 @@ import {
getSubTotal,
getSalesTax,
} from "@/helpers/pricing-helper.js";
import { debugLog } from "@/helpers/debug-log-helper.js";
export default {
name: "payment",
data() {
return {
checkoutUrl: applicationConfig.SAFELITE_HOP,
checkoutUrl: externalUrls.SAFELITE_HOP,
piaResponseUrl: applicationConfig.PIA_RESPONSE_URL,
piaCancelUrl: applicationConfig.PIA_CANCEL_URL,
piaErrorUrl: applicationConfig.PIA_ERROR_URL,
@ -288,7 +289,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const signaturePromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_SIGNATURE,
@ -546,50 +547,41 @@ export default {
// prettier-ignore
{
debugLog("--- payment.vue pagePrereqs start ---", null, !preReqResult);
debugLog("mobileReqs:", mobileReqs, !preReqResult);
debugLog("serviceLocation.address:", serviceLocation.address, !preReqResult);
debugLog("serviceLocation.city:", serviceLocation.city, !preReqResult);
debugLog("serviceLocation.state:", serviceLocation.state, !preReqResult);
debugLog("serviceLocation.zipCode:", serviceLocation.zipCode, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("dropOffInshopReqs:", dropOffInshopReqs, !preReqResult);
debugLog("serviceLocationReqs:", serviceLocationReqs, !preReqResult);
debugLog("providerLocation.streetAddress:", providerLocation.streetAddress, !preReqResult);
debugLog("providerLocation.city:", providerLocation.city, !preReqResult);
debugLog("providerLocation.state:", providerLocation.state, !preReqResult);
debugLog("providerLocation.zipCode:", providerLocation.zipCode, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("isInsuranceSet:", isInsuranceSet, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("scheduleReqs:", scheduleReqs, !preReqResult);
debugLog("schedule.date:", schedule.date, !preReqResult);
debugLog("schedule.startTime:", schedule.startTime, !preReqResult);
debugLog("schedule.endTime:", schedule.endTime, !preReqResult);
debugLog("schedule.jobMaxMinutes:", schedule.jobMaxMinutes, !preReqResult);
debugLog("schedule.jobMinMinutes:", schedule.jobMinMinutes, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("customerReqs:", customerReqs, !preReqResult);
debugLog("customer.firstName:", customer.firstName, !preReqResult);
debugLog("customer.lastName:", customer.lastName, !preReqResult);
debugLog("customer.phoneNumber:", customer.phoneNumber, !preReqResult);
debugLog("customer.emailAddress:", customer.emailAddress, !preReqResult);
debugLog("", null, !preReqResult);
debugLog("paymentMethodReqs:", paymentMethodReqs, !preReqResult);
debugLog("store.getters.order.payment.isPia:", store.getters.order?.payment?.isPia, !preReqResult);
debugLog("store.getters.order.payment.piaType:", store.getters.order?.payment?.piaType, !preReqResult);
debugLog("--- payment.vue pagePrereqs end ---", null, !preReqResult);
if (store.getters.applicationUser.loggingOption || !preReqResult) {
console.log("------------- payment.vue pagePrereqs start -----------------");
console.log(new Date() + "mobileReqs:" + mobileReqs);
console.log(new Date() + "serviceLocation.address:" + serviceLocation.address);
console.log(new Date() + "serviceLocation.city:" + serviceLocation.city);
console.log(new Date() + "serviceLocation.state:" + serviceLocation.state);
console.log(new Date() + "serviceLocation.zipCode:" + serviceLocation.zipCode);
console.log("");
console.log(new Date() + "dropOffInshopReqs:" + dropOffInshopReqs);
console.log(new Date() + "serviceLocationReqs:" + serviceLocationReqs);
console.log(new Date() + "providerLocation.streetAddress:" + providerLocation.streetAddress);
console.log(new Date() + "providerLocation.city:" + providerLocation.city);
console.log(new Date() + "providerLocation.state:" + providerLocation.state);
console.log(new Date() + "providerLocation.zipCode:" + providerLocation.zipCode);
console.log("");
console.log(new Date() + "isInsuranceSet:" + isInsuranceSet);
console.log("");
console.log(new Date() + "scheduleReqs:" + scheduleReqs);
console.log(new Date() + "schedule.date:" + schedule.date);
console.log(new Date() + "schedule.startTime:" + schedule.startTime);
console.log(new Date() + "schedule.endTime:" + schedule.endTime);
console.log(new Date() + "schedule.jobMaxMinutes:" + schedule.jobMaxMinutes);
console.log(new Date() + "schedule.jobMinMinutes:" + schedule.jobMinMinutes);
console.log("");
console.log(new Date() + "customerReqs:" + customerReqs);
console.log(new Date() + "customer.firstName:" + customer.firstName);
console.log(new Date() + "customer.lastName:" + customer.lastName);
console.log(new Date() + "customer.phoneNumber:" + customer.phoneNumber);
console.log(new Date() + "customer.emailAddress:" + customer.emailAddress);
console.log("");
console.log(new Date() + "paymentMethodReqs:" + paymentMethodReqs);
console.log(new Date() + "store.getters.order.payment.isPia:" + store.getters.order.payment.isPia);
console.log(new Date() + "store.getters.order.payment.piaType:" + store.getters.order.payment.piaType);
console.log("------------- payment.vue pagePrereqs end -------------------");
}
}
return preReqResult;
@ -692,29 +684,30 @@ export default {
});
await baseMixin.methods.dispatchStoreAction(storeActions.CREATE_SUBMITTED_STATE);
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.CLICKED_PAY_LATER,
this.pageName
);
//window.location = applicationConfig.CONFIRMATION_URL;
window.location = applicationConfig.CONFIRMATION_URL;
} catch (error) {
console.log("error: response from submit work order(payment pg):" + error.message);
this.$router.navigateWithoutSaving(
this.navigationScenarios.PIA_ERROR,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_PIA_ALERT]: true }
);
this.$refs.loadingModal.isModalVisible = false;
return;
}
},
backButtonAction() {
// Used to set the url directly here.
// Now hooks into a shared set of logic for doing this, also used with `payment-pia-return`.
// And uses nav scenarios properly.
this.$router.navigateAndForceTopLevelNavigation(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
// The only way I could figure out how to get navigation to work on a page with the iframe.
// This is also how a cancel from Paypal would work. Just a redirect to the payment-method page.
// The normal navigation sort of works but the page does not render. The "next" callback function does not get
// invoked in payment-method's beforeroute enter. I also spotted an error in vue-router.esm-bundler.js when this
// happens but was unable to ignore it with a try catch. The navigation guard error is:
// Error: Redirected from "/?fmgPage=payment-method" to "{ params: {isSavingNation: "false"}, query: "fmgPage: "payment-method"}"
// I don't know if the navigation guard thinks the to and from are the same page.
// Also tried overriding with a $router.push
window.location = applicationConfig.PIA_CANCEL_URL;
//this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
submitHopForm() {
this.$nextTick(() => {
@ -811,7 +804,10 @@ export default {
}
},
shouldDisplayPiaAlert(payMethod) {
return this.$route?.query?.piaErrorType === payMethod;
return (
this.$route.query[queryStrings.DISPLAY_PIA_ALERT] === payMethod ||
getBoolFromString(window.history.state.displayPiaAlert)
);
},
},
components: {

View file

@ -651,7 +651,7 @@ describe("quote.vue", () => {
//Assert
expect(wrapper.vm.isInsuranceSelected).toBe(false);
});
test("should default to cash if offer = cash, despite all other checks pointing to insurance selection", async () => {
test("should default to cash if isCashSelected is true, despite all other checks pointing to insurance selection", async () => {
// Also needs no query parameter or previous selection in store to be present
//Arrange
@ -695,7 +695,7 @@ describe("quote.vue", () => {
//Act
await quote.beforeRouteEnter.call(
wrapper.vm,
{ name: "quote", query: { isInsuranceSelected: true, offer: "cash" } },
{ query: { fmgPage: "quote", isInsuranceSelected: true, isCashSelected: true } },
undefined,
(c) => c(wrapper.vm)
);

View file

@ -168,25 +168,18 @@ import {
getDeviceIdValue,
} from "@/helpers/heritage-integration/cookie-helper";
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { routeData } from "@/router/constants/routes";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeMutations } from "@/constants/store-mutations";
import { debugLog } from "@/helpers/debug-log-helper";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
const INSURANCE_TAB_TO_DISPLAY_THRESHOLD_DEFAULT = 300;
const ACCEPTED_QUOTE_TYPES = {
CASH: "cash",
INSURANCE: "insurance",
};
export default {
name: "quote",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const wipersPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_WIPERS,
{
@ -223,7 +216,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.name,
pageName: to.query.fmgPage,
experiment: skipQuoteExperiment,
},
"quote",
@ -253,7 +246,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.name,
pageName: to.query.fmgPage,
experiment: afterpayBreakoutDisplayExperiment,
},
"quote",
@ -284,7 +277,7 @@ export default {
const emailFromStore = store.getters.order.customer.emailAddress;
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
const isPopupSkipped =
store.getters.pageData(routeData.QUOTE.name)?.saveProgressPopupSkipped === true;
store.getters.pageData(fmgPageValues.QUOTE)?.saveProgressPopupSkipped === true;
const showSaveProgressPopup = !(isEmailInStoreOnPageLoad || isPopupSkipped);
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
const shouldSkipToInsurance =
@ -360,7 +353,7 @@ export default {
const oldActivePromos = store.getters.lineItems.promos?.slice(0);
const oldInactivePromos = store.getters.order.payment.inactivePromos?.slice(0);
const promoCodeFromQueryString = consumeQueryFromStash(queryStrings.PROMO);
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateQueryStringPromo(
promoCodeFromQueryString,
@ -410,15 +403,10 @@ export default {
}
const getIsInsuranceSelectedValue = (availableLineItems, insuranceThreshold) => {
// Override auto-select if specified
const quoteTypeParam = to.query?.offer?.toLowerCase();
if (quoteTypeParam === ACCEPTED_QUOTE_TYPES.CASH) {
// query param checked here is set on insurance-selection "Pay on my own" link click
if (to.query?.isCashSelected || to.query?.iscashselected) {
return false;
} else if (quoteTypeParam === ACCEPTED_QUOTE_TYPES.INSURANCE) {
return true;
}
const serviceLocationState = store.getters.order.serviceLocation.state;
// usually true when returning from heritage but can be false when returning from heritage on a save quote
@ -463,7 +451,9 @@ export default {
baseMixin.methods.getTierOnePackagePrice(lineItemsNoDiscount);
// prettier-ignore
{
debugLog("quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + " quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
}
}
// compare base price vs arbitrary threshold (representing insurance price)
@ -484,17 +474,21 @@ export default {
// prettier-ignore
{
debugLog("--- quote.vue thresholds start ---");
debugLog(" isExternalParameter: ", isExternalParameter);
debugLog(" internalThreshold: ", internalThreshold);
debugLog(" externalThreshold: ", externalThreshold);
debugLog("--- quote.vue thresholds end ---");
if (store.getters.applicationUser.loggingOption) {
console.log("------------- quote.vue thresholds start -----------------");
console.log(new Date() + " isExternalParameter: " + isExternalParameter);
console.log(new Date() + " internalThreshold: " + internalThreshold);
console.log(new Date() + " externalThreshold: " + externalThreshold);
console.log("------------- quote.vue thresholds end -----------------");
}
}
if (isExternalParameter === externalParameterStatus.NOT_SET) {
// prettier-ignore
{
debugLog("quote.vue tab select EXTERNAL not set");
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select EXTERNAL not set");
}
}
// there are no active or inactive external parameters; use internal threshold
if (internalThreshold) thresholdToUse = internalThreshold;
@ -509,7 +503,9 @@ export default {
if (getBoolFromString(store.getters.externalParameterQuote?.isInsurance)) {
// prettier-ignore
{
debugLog("quote.vue tab select EXTERNAL ISINSURANCE");
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select EXTERNAL ISINSURANCE");
}
}
const insuranceSelection = true;
@ -528,7 +524,9 @@ export default {
// prettier-ignore
{
debugLog("quote.vue tab select NOT EXTERNAL");
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select NOT EXTERNAL");
}
}
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
@ -644,13 +642,16 @@ export default {
// prettier-ignore
{
debugLog("--- quote.vue pagePrereqs start ---", null, !preReqResult);
debugLog("store.getters.order.serviceLocation.zipCode:", store.getters.order.serviceLocation?.zipCode, !preReqResult);
debugLog("store.getters.order.serviceLocation.zipCodeCtu:", store.getters.order.serviceLocation?.zipCodeCtu, !preReqResult);
debugLog("store.getters.order.damage.isRepair:", store.getters.order.damage?.isRepair, !preReqResult);
debugLog("store.getters.order.lineItems?.glassParts:", store.getters.order.lineItems?.glassParts, !preReqResult);
debugLog("store.getters.order.payemt.insuranceCoverage?.isVerified:", store.getters.order.payment?.insuranceCoverage?.isVerified, !preReqResult);
debugLog("--- quote.vue pagePrereqs end ---", null, !preReqResult);
const log = getQuerystringParameter(queryStrings.LOG);
if (log === "true" || !preReqResult) {
console.log("------------- quote.vue pagePrereqs start -----------------");
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + store.getters.order.serviceLocation?.zipCode);
console.log(new Date() +" store.getters.order.serviceLocation.zipCodeCtu: " + store.getters.order.serviceLocation?.zipCodeCtu);
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage?.isRepair);
console.log(new Date() + " store.getters.order.lineItems?.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
console.log(new Date() + " store.getters.order.payment.insuranceCoverage?.isVerified: " + payment?.insuranceCoverage?.isVerified);
console.log("------------- quote.vue pagePrereqs end -----------------");
}
}
return preReqResult;
@ -673,7 +674,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.QUOTE.name,
page: fmgPageValues.QUOTE,
data: { saveProgressPopupSkipped: true },
},
false
@ -759,12 +760,12 @@ export default {
if (payment.isInsurance) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
this.pageName
this.$route
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_CASH,
this.pageName
this.$route
);
}

View file

@ -13,7 +13,7 @@ import router from "@/router";
import navbar from "@/fmg-components/nav-bar/nav-bar";
import { Form } from "vee-validate";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { settleAllPromises } from "@/helpers/layout-helper";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
@ -257,7 +257,7 @@ describe("return-user.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
navigationScenarios.CLICKED_FORWARD,
wrapper.vm.$route.name
wrapper.vm.$route
);
});
test("expect functions in startOver to be called", async () => {
@ -272,15 +272,18 @@ describe("return-user.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
navigationScenarios.CLICKED_RESTART,
wrapper.vm.$route.name
navigationScenarios.CLICKED_FORWARD,
wrapper.vm.$route
);
expect(dispatchStoreActionSpy).toHaveBeenCalledWith(storeActions.RESET_STATE);
expect(deleteFunnelCookie).toHaveBeenCalled();
});
});
});
function setupMocks({ customMountOptions }) {
const route = { name: "return-user" };
const route = { query: { fmgPage: "return-user" }, params: {} };
baseMixin.methods.ResetExternalParamsAndHideModal = jest.fn();
@ -291,7 +294,6 @@ function setupMocks({ customMountOptions }) {
mountOptions.global.mocks["$store"] = store;
mountOptions.global.mocks["$router"] = router;
mountOptions.global.mocks.pageName = route.name;
baseMixin.methods.isFormValid = jest.fn().mockReturnValue(true);
mountOptions["attachTo"] = document.body;

View file

@ -55,7 +55,7 @@ export default {
name: "return-user",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
{
@ -85,15 +85,22 @@ export default {
async forwardButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
this.$route
);
},
async startOver() {
this.pushEventToGA(this.pageName, this.GaActions.CLICKED, "Start over", true);
this.pushEventToGA(
this.$route.query[this.queryStrings.FMG_PAGE],
this.GaActions.CLICKED,
"Start over",
true
);
deleteFunnelCookie();
await this.dispatchStoreAction(storeActions.RESET_STATE);
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_RESTART,
this.pageName
this.navigationScenarios.CLICKED_FORWARD,
this.$route
);
},
},

View file

@ -463,13 +463,14 @@ describe("schedule.vue...", () => {
expect(testOutput4).toBe("3:30 PM");
});
test("Clicking back should fire correct navigation", () => {
test("getDisplayTextForMilitaryTime should return the correctly formatted string", () => {
// Arrange
const { wrapper } = setupMocks({});
wrapper.vm.selectableDatesData = {
days: [],
};
wrapper.vm.$router.navigateWithoutSaving = jest.fn();
wrapper.vm.$route = "testRoute";
// Act
wrapper.vm.backButtonAction();
@ -477,7 +478,7 @@ describe("schedule.vue...", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
"CLICKED_BACK",
"schedule"
"testRoute"
);
});
});
@ -597,7 +598,6 @@ const mockCmsContent = {};
function setupMocks({ customMountOptions }) {
const mountOptions = getMountOptions({
...customMountOptions,
route: { name: "schedule" },
});
mountOptions.global.mocks["$store"] = store;
@ -613,7 +613,6 @@ function setupMocks({ customMountOptions }) {
},
},
];
mountOptions.global.mocks.pageName = "schedule";
const wrapper = shallowMount(schedule, mountOptions);

View file

@ -94,7 +94,6 @@ import { getAmountDue, getPricingByDayPartWithPrice } from "@/helpers/pricing-he
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
import { partNumberStrings } from "@/constants/part-number-strings";
import { deepClone } from "@/helpers/object-helper";
import { debugLog } from "@/helpers/debug-log-helper";
// DEFINE VALIDATION RULES
defineRule("date-required", required(errorMessages.DATE_REQUIRED));
@ -268,7 +267,7 @@ export default {
}
// Set up promises
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
store.getters.order.serviceLocation.zipCodeCtu,
@ -429,15 +428,18 @@ export default {
// prettier-ignore
{
debugLog("--- schedule.vue pagePrereqs start ---", null, !preReqResult);
debugLog("store.getters.order.serviceLocation.zipCode:", serviceLocation.zipCode, !preReqResult);
debugLog("store.getters.order.serviceLocation.zipCodeCtu:", serviceLocation.zipCodeCtu, !preReqResult);
debugLog("store.getters.order.serviceLocation.appointmentType:", serviceLocation.appointmentType, !preReqResult);
debugLog("store.getters.order.serviceLocation.provider.providerNumber:", serviceLocation.provider?.providerNumber, !preReqResult);
debugLog("store.getters.payment.isInsurance:", store.getters.payment?.isInsurance, !preReqResult);
debugLog("store.getters.order.damage.isRepair:", store.getters.order.damage?.isRepair, !preReqResult);
debugLog("store.getters.order.lineItems.glassParts:", store.getters.order.lineItems?.glassParts, !preReqResult);
debugLog("--- schedule.vue pagePrereqs end ---", null, !preReqResult);
const log = getQuerystringParameter(queryStrings.LOG);
if (log === "true" || !preReqResult) {
console.log("------------- schedule.vue pagePrereqs start -----------------");
console.log(new Date() + " store.getters.order.serviceLocation.zipCode: " + serviceLocation.zipCode);
console.log(new Date() + " store.getters.order.serviceLocation.zipCodeCtu: " + serviceLocation.zipCodeCtu);
console.log(new Date() + " store.getters.order.serviceLocation.appointmentType: " + serviceLocation.appointmentType);
console.log(new Date() + " store.getters.order.serviceLocation.provider.providerNumber: " + serviceLocation.provider.providerNumber);
console.log(new Date() + " store.getters.payment.isInsurance: " + store.getters.payment?.isInsurance);
console.log(new Date() + " store.getters.order.damage.isRepair: " + store.getters.order.damage.isRepair);
console.log(new Date() + " store.getters.order.lineItems.glassParts: " + JSON.stringify(store.getters.order.lineItems?.glassParts));
console.log("------------- schedule.vue pagePrereqs end -------------------");
}
}
return preReqResult;
},
@ -534,10 +536,7 @@ export default {
}
},
backButtonAction() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
forwardButtonAction() {
this.updateSupportingItems();
@ -586,10 +585,7 @@ export default {
);
}
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
setDisplayWaitList() {
if (

View file

@ -219,7 +219,7 @@ export default {
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const zipCodeDataPromise = getZipCodeData(serviceZipCode);
@ -611,7 +611,7 @@ export default {
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
this.$route
);
}
},
@ -746,10 +746,7 @@ export default {
this.updateAndSaveSupportingItems();
this.updateAndSaveIsMSRFeeApplicable();
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
setMobileLocationInValid(isMobileLocationInValid) {
this.isMobileAddressValid = !isMobileLocationInValid;

View file

@ -2,12 +2,12 @@
import serviceZip from "@/layouts/service-zip/service-zip";
// Supporting Files
import { mount, shallowMount } from "@vue/test-utils";
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper";
import baseMixin from "@/mixins/base-mixin";
import store from "@/store";
import router from "@/router";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { experimentSettings } from "../../constants/experiments";
@ -251,6 +251,20 @@ describe("service-zip.vue", () => {
expect(wrapper.vm.serviceZipCode).toEqual("11111");
expect(wrapper.vm.emailOrSms).toEqual("builddigitaltest@safelite.com");
});
test("Zip in querystring -> pushed to data", () => {
// Arrange
// no changes to store
applyMockStoreDataToGetters();
// Act
const wrapper = setupMocks({
customZipQuery: "11111",
});
// Assert
expect(wrapper.vm.serviceZipCode).toEqual("11111");
});
});
describe("Navigation", () => {
@ -271,7 +285,7 @@ describe("service-zip.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
wrapper.vm.$route.name
wrapper.vm.$route
);
});
@ -287,7 +301,7 @@ describe("service-zip.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toBeCalledWith(
navigationScenarios.CLICKED_BACK,
wrapper.vm.$route.name
wrapper.vm.$route
);
});
});
@ -312,7 +326,7 @@ describe("service-zip.vue", () => {
// Assert
expect(wrapper.vm.$router.navigateWithSaving).toBeCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
wrapper.vm.$route.name
wrapper.vm.$route
);
expect(wrapper.vm.navigateForwardWithSingleCarMatch).not.toBeCalled();
});
@ -472,7 +486,7 @@ describe("service-zip.vue", () => {
});
function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse }) {
const route = { name: "service-zip" };
const route = { query: { fmgPage: "service-zip" }, params: {} };
if (customZipQuery) {
route.query.zipcode = customZipQuery;
}
@ -485,7 +499,6 @@ function setupMocks({ customMountOptions, customZipQuery, customZipDataResponse
mountOptions.global.mocks["$store"] = store;
mountOptions.global.mocks["$router"] = router;
mountOptions.global.mocks.pageName = route.name;
mountOptions.mixins = [
{
methods: {

View file

@ -95,8 +95,7 @@ import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
import baseMixin from "@/mixins/base-mixin.js";
import { queryStrings } from "@/constants/query-strings";
import { routeData } from "@/router/constants/routes";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -116,7 +115,7 @@ export default {
mixins: [vinPagesMixin],
data() {
return {
serviceZipCode: this.getZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
emailOrSms: this.getEmailOrSmsFromStore(),
carId: this.getCarIdfromStore(),
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
@ -128,7 +127,7 @@ export default {
async beforeRouteEnter(to, from, next) {
//Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
//Settle promises and get results
const promiseResultMap = [
@ -215,12 +214,12 @@ export default {
if (skipVin) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
this.pageName
this.$route
);
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
this.$route
);
}
},
@ -243,7 +242,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.SERVICE_ZIP.name,
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.emailOrSms },
},
false
@ -318,7 +317,7 @@ export default {
await saveSession({ pageNameToLog: "service-zip" });
return this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
this.pageName
this.$route
);
} else {
// if we're skipping the vin-lookup but it's not a repair, we still need to get the parts

View file

@ -16,6 +16,7 @@ import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { validate } from "vee-validate";
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
import { routerParams } from "@/router/router-constants/router-params";
import * as cookieHelper from "@/helpers/heritage-integration/cookie-helper";
// Mock our module for promises.
@ -309,11 +310,11 @@ describe("vehicle-damage.vue", () => {
describe("alert", () => {
test("when displayVehicleChangeAlert router params is true, the alert: 'vehicleChangeAlert' should be rendered", () => {
// Arrange & Act
window.history.pushState({ displayVehicleChangeAlert: "true" }, "", "");
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
name: "vehicle-damage",
query: { displayVehicleChangeAlert: true },
state: { displayVehicleChangeAlert: true },
},
},
});
@ -327,9 +328,8 @@ describe("vehicle-damage.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
name: "vehicle-damage",
query: {
displayVehicleChangeAlert: false,
state: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false,
},
},
},
@ -345,9 +345,8 @@ describe("vehicle-damage.vue", () => {
const { wrapper } = setupMocks({
mountOptionsMockData: {
route: {
name: "vehicle-damage",
query: {
displayVehicleChangeAlert: undefined,
params: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: undefined,
},
},
},
@ -856,8 +855,9 @@ function setupMocks({ pageHeaderWidgetHeaderText, mountOptionsMockData, funnelCo
navigateWithSaving: jest.fn(),
},
route: {
name: "vehicle-damage",
query: {},
state: {
[routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false,
},
},
store: {
getters: {

View file

@ -97,6 +97,7 @@ import { errorMessages } from "@/constants/error-messages";
import { damageLocationsCms } from "@/constants/damage-locations-cms.js";
import { damageLocationsSelected } from "@/constants/damage-locations-selected.js";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { routerParams } from "@/router/router-constants/router-params";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
@ -109,7 +110,7 @@ export default {
name: "vehicle-damage",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const damageOptionsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_DAMAGE_OPTIONS,
@ -275,10 +276,7 @@ export default {
backButtonAction() {
// route to move backwards
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
);
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
},
getDamageLocationsFromStore() {
@ -486,26 +484,34 @@ export default {
if (skipVin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
} else {
if (store.getters.damage.isRepair) {
this.$router.navigateWithSaving(
this.navigationScenarios
.CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
} else {
if (store.getters.vehicle.vin) {
this.$router.navigateWithSaving(
this.navigationScenarios
.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
}
}
@ -515,17 +521,23 @@ export default {
else if (store.getters.vehicle.vin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_VIN,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
} else if (skipVin) {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
} else {
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: false }
);
}
},
@ -654,7 +666,7 @@ export default {
);
},
shouldDisplayVehicleChangeAlert() {
return getBoolFromString(this.$route?.query?.displayVehicleChangeAlert);
return getBoolFromString(window.history.state.displayVehicleChangeAlert);
},
shouldHideBackButton() {
return this.$store.getters.requiresVerifiedRedirecting;

View file

@ -154,7 +154,7 @@ export default {
},
PartDataFromApi() {
return this.$store.getters.pageData(this.pageName) ?? {};
return this.$store.getters.pageData(this.$route.query.fmgPage) ?? {};
},
},
methods: {

View file

@ -12,7 +12,7 @@ import baseMixin from "@/mixins/base-mixin.js";
import { storeActions } from "@/constants/store-actions";
import store from "@/store";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
// Mock our module for promises.
jest.mock("@/helpers/layout-helper.js", () => ({
@ -84,10 +84,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -122,10 +123,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -159,10 +161,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -202,10 +205,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: {
@ -251,7 +255,7 @@ describe("vehicle-parts.vue", () => {
//Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
wrapper.vm.$route.name
wrapper.vm.$route
);
});
@ -264,10 +268,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: {
@ -297,7 +302,7 @@ describe("vehicle-parts.vue", () => {
//Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
wrapper.vm.$route.name
wrapper.vm.$route
);
});
@ -351,10 +356,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -378,7 +384,7 @@ describe("vehicle-parts.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalled();
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
});
test("ForwardButtonAction triggers a router.navigateWithSaving change if there are capability questions", async () => {
@ -411,10 +417,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -444,7 +451,7 @@ describe("vehicle-parts.vue", () => {
await wrapper.vm.forwardButtonAction();
//Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalled();
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalled();
});
test("ForwardButtonAction saves selected parts to store if no molding or capability questions", async () => {
@ -461,10 +468,11 @@ describe("vehicle-parts.vue", () => {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
route: {
name: "vehicle-parts",
query: {
fmgPage: "vehicle-parts",
},
},
store: {
getters: store.getters,
@ -536,7 +544,6 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
wrapper.vm.$refs.navbar.removeLoader = jest.fn();
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
wrapper.vm.pageName = "vehicle-parts";
// wrapper.vm.$refs.onSubmit = jest.fn();
// wrapper.vm.$refs.onInvalidSubmit = jest.fn();

View file

@ -69,7 +69,7 @@ import saveProgressModalQuestion from "@/fmg-components/save-progress-modal-ques
// Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { Form } from "vee-validate";
import store from "@/store";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
@ -81,7 +81,7 @@ export default {
mixins: [vehicleQuestionsMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
{
@ -162,7 +162,7 @@ export default {
},
PartsFromApi() {
return this.$store.getters.pageData(routeData.VEHICLE_PARTS.name);
return this.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
},
RefPrefix() {
@ -172,7 +172,7 @@ export default {
methods: {
arePagePrerequisitesValid() {
// Check if isRepair is populated and if the pageData we need is here (Parts data)
const vehiclePartsFromPageData = store.getters.pageData(routeData.VEHICLE_PARTS.name);
const vehiclePartsFromPageData = store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
return (
store.getters.damage.isRepair != null &&
vehiclePartsFromPageData?.partsOrQuestions?.some((part) => part?.glassName)

View file

@ -110,11 +110,6 @@ import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { applicationConfig } from "../../constants/application-config";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import {
consumeQueryFromStash,
peekQueryFromStash,
} from "@/router/methods/helpers/querystring-stash";
import { debugLog } from "@/helpers/debug-log-helper";
//define validation rules
defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
@ -138,7 +133,7 @@ export default {
imageUrl: this.getImagefromStore(),
imageVifNumber: this.getImageVifNumberfromStore(),
imageVifColor: this.getImageVifColorfromStore(),
serviceZipCode: this.getZipFromStore() ?? peekQueryFromStash(queryStrings.ZIP_CODE),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
yearOptions: [],
makeOptions: [],
modelOptions: [],
@ -149,12 +144,17 @@ export default {
},
async beforeRouteEnter(to, from, next) {
debugLog("------------- vehicle.vue applicationConfig start -------------");
debugLog("", applicationConfig);
debugLog("------------- vehicle.vue applicationConfig end -------------");
if (store.getters.applicationUser.loggingOption) {
console.log(
new Date() + "------------- vehicle.vue applicationConfig start -------------"
);
console.log(new Date() + JSON.stringify(applicationConfig));
console.log(
new Date() + "------------- vehicle.vue applicationConfig end -------------"
);
}
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
);
@ -213,7 +213,7 @@ export default {
userId: getUserIdValue(),
deviceId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
pageName: to.name,
pageName: to.query.fmgPage,
experiment: experimentForLogging,
},
"vehicle",
@ -539,10 +539,7 @@ export default {
}
}
this.$router.navigateWithSaving(
this.navigationScenarios.CLICKED_FORWARD,
this.pageName
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
initializeYearComponent(initialData) {
this.yearOptions = initialData;

View file

@ -1,7 +1,7 @@
import { shallowMount } from "@vue/test-utils";
import vinLookup from "./vin-lookup.vue";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios.js";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
import { settleAllPromises } from "@/helpers/layout-helper.js";
import { experimentSettings } from "@/constants/experiments";

View file

@ -155,12 +155,11 @@ import {
import { required, regex } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { routerParams } from "@/router/router-constants/router-params";
import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store";
import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { routeData } from "@/router/constants/routes";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { queryStrings } from "@/constants/query-strings";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
// DEFINE VALIDATION RULES
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -181,7 +180,7 @@ export default {
mixins: [vinPagesMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.name);
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Settle promises and get results
const promiseResultMap = [
@ -204,7 +203,7 @@ export default {
data() {
return {
vin: this.getVinFromStore(),
serviceZipCode: this.getZipFromStore() ?? consumeQueryFromStash(queryStrings.ZIP_CODE),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
emailOrSms: this.getEmailOrSmsFromStore(),
carId: this.getCarIdfromStore(),
isHeavyTruck: this.getIsVehicleHeavyTruckServiceableFromStore(),
@ -248,12 +247,12 @@ export default {
if (this.$store.getters.vehicle.vin) {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK_WITH_VIN,
this.pageName
this.$route
);
} else {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_BACK,
this.pageName
this.$route
);
}
},
@ -390,7 +389,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.SERVICE_ZIP.name,
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.emailOrSms },
},
false
@ -453,7 +452,7 @@ export default {
await this.dispatchStoreAction(
storeActions.SAVE_PAGE_DATA,
{
page: routeData.SERVICE_ZIP.name,
page: fmgPageValues.EMAIL_SMS_PAGES,
data: { emailOrSmsValue: this.emailOrSms },
},
false
@ -475,7 +474,9 @@ export default {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigateWithSaving(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.pageName
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else {
await this.navigateForwardWithSingleCarMatch();

View file

@ -2,7 +2,7 @@ import { createApp } from "vue";
import LoadScript from "vue-plugin-load-script";
import Maska from "maska";
import App from "./App.vue";
import router from "@/router";
import router from "./router";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
import analyticsMixin from "@/mixins/analytics-mixin.js";

View file

@ -27,7 +27,8 @@ import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { applicationConfig } from "../constants/application-config";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import router from "@/router/index.js";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { Variables } from "../constants/analytics";
@ -44,7 +45,7 @@ export default {
const submittedOrder = baseMixin.methods.getSubmittedOrder();
const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
const hasSubmittedOrderAtConfirmationPage =
hasSubmittedOrder && currentPageName?.toLowerCase() == routeData.CONFIRMATION.name;
hasSubmittedOrder && currentPageName?.toLowerCase() == fmgPageValues.CONFIRMATION;
const refSequenceNum = hasSubmittedOrderAtConfirmationPage
? submittedOrder.referralSequenceNumber

View file

@ -2,20 +2,19 @@ import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
import { sessionStorageKeyConstants } from "@/constants/session-storage.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { routerParams } from "@/router/router-constants/router-params";
import { queryStrings } from "@/constants/query-strings";
import { dynamicStrings } from "@/constants/dynamic-strings";
import { partTypeStrings } from "../constants/part-type-strings";
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { getItemsWithoutRecalParts } from "@/helpers/recal-helper";
import { debugLog } from "@/helpers/debug-log-helper";
export default {
data() {
return {
cmsContentByWidget: {},
_componentPageName: null,
};
},
methods: {
@ -96,8 +95,10 @@ export default {
let totalPrice = this.getTotalPriceOfAllLineItemsAndChildParts(lineItemsToPrice, false);
// prettier-ignore
{
debugLog("base-mixin getTierOnePackagePrice lineItemsToPrice:", lineItemsToPrice);
debugLog("base-mixin getTierOnePackagePrice totalPrice:", totalPrice);
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + " base-mixin getTierOnePackagePrice lineItemsToPrice: " + JSON.stringify(lineItemsToPrice));
console.log(new Date() + " base-mixin getTierOnePackagePrice totalPrice: " + totalPrice);
}
}
return totalPrice;
},
@ -233,6 +234,9 @@ export default {
vehicleCategories() {
return vehicleCategories;
},
routerParams() {
return routerParams;
},
queryStrings() {
return queryStrings;
},
@ -242,15 +246,9 @@ export default {
cssClassNameForCmsWidget() {
return "widget-name-" + this.cmsWidgetName;
},
pageName() {
return this._componentPageName ?? this.$route.name;
},
},
mounted() {
// Store route immutably so that components know their originating page even during page transition.
this._componentPageName = this.$route.name;
if (!store.getters.externalParameterState?.isExternalParameter) {
showFmgLoadingModal(false);
}

View file

@ -1,7 +1,7 @@
import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions.js";
import { storeMutations } from "@/constants/store-mutations.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { queryStrings } from "@/constants/query-strings";
import { dynamicStrings } from "@/constants/dynamic-strings";

View file

@ -1,6 +1,6 @@
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeMutations } from "@/constants/store-mutations.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "../router/router-constants/navigation-scenarios";
import { storeActions } from "@/constants/store-actions";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import baseMixin from "@/mixins/base-mixin.js";
@ -53,11 +53,11 @@ export default {
},
comparePageIndices(currentPage, fmgPage) {
const orderedVehicleQuestionPages = [
routeData.PART_QUESTIONS.name,
routeData.VEHICLE_PARTS.name,
routeData.MOLDING_QUESTIONS.name,
routeData.CAPABILITY_QUESTIONS.name,
routeData.QUOTE.name,
fmgPageValues.PART_QUESTIONS,
fmgPageValues.VEHICLE_PARTS,
fmgPageValues.MOLDING_QUESTIONS,
fmgPageValues.CAPABILITY_QUESTIONS,
fmgPageValues.QUOTE,
];
return (
@ -65,10 +65,10 @@ export default {
orderedVehicleQuestionPages.indexOf(fmgPage)
);
},
currentPageComesBeforePage(currentPage = this.pageName, fmgPage) {
currentPageComesBeforePage(currentPage = this.$route.query.fmgPage, fmgPage) {
return this.comparePageIndices(currentPage, fmgPage) < 0;
},
currentPageComesAfterPage(currentPage = this.pageName, fmgPage) {
currentPageComesAfterPage(currentPage = this.$route.query.fmgPage, fmgPage) {
return this.comparePageIndices(currentPage, fmgPage) > 0;
},
setupInitialData(glass, index, alreadyAnsweredQuestions, vm) {
@ -359,7 +359,7 @@ export default {
// Can't use `this` because navigateForward is also called from vin-pages-mixin
async navigateForward(partsOrQuestions, vm) {
const self = vm ?? this;
const currentPage = self.pageName;
const currentPage = self.$route.query.fmgPage;
const hasPartQuestions = this.hasPartQuestions(partsOrQuestions);
const hasGlassLocationWithMultipleParts =
@ -369,38 +369,44 @@ export default {
if (
hasPartQuestions &&
this.currentPageComesBeforePage(currentPage, routeData.PART_QUESTIONS.name)
this.currentPageComesBeforePage(currentPage, fmgPageValues.PART_QUESTIONS)
) {
self.$router.navigateWithPageData(
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
self.pageName,
self.$route,
{},
{},
{ partsOrQuestions: partsOrQuestions }
);
} else if (
hasGlassLocationWithMultipleParts &&
this.currentPageComesBeforePage(currentPage, routeData.VEHICLE_PARTS.name)
this.currentPageComesBeforePage(currentPage, fmgPageValues.VEHICLE_PARTS)
) {
// if multiple parts on any glass
// go to vehicle-parts page and pass the partsData
self.$router.navigateWithPageData(
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
self.pageName,
self.$route,
{},
{},
{ partsOrQuestions: partsOrQuestions }
);
} else if (
hasChildPartQuestions &&
this.currentPageComesBeforePage(currentPage, routeData.MOLDING_QUESTIONS.name)
this.currentPageComesBeforePage(currentPage, fmgPageValues.MOLDING_QUESTIONS)
) {
// if any childpart questions
// go to molding-questions page and pass the partsData
self.$router.navigateWithPageData(
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
self.pageName,
self.$route,
{},
{},
{ partsOrQuestions: partsOrQuestions }
);
} else if (
hasCapabilityQuestions &&
this.currentPageComesBeforePage(currentPage, routeData.CAPABILITY_QUESTIONS.name)
this.currentPageComesBeforePage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS)
) {
// if has capability questions
// go to capability-questions page and pass the partsData
@ -432,9 +438,11 @@ export default {
}
}
self.$router.navigateWithPageData(
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
self.pageName,
self.$route,
{},
{},
{ partsOrQuestions }
);
} else {
@ -469,7 +477,7 @@ export default {
} else {
self.$router.navigateWithSaving(
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
self.pageName
self.$route
);
}
}
@ -477,16 +485,16 @@ export default {
// Can't use `this` because navigateForward is also called from quote
async navigateBack(vm) {
const self = vm ?? this;
const currentPage = self.pageName;
const currentPage = self.$route.query.fmgPage;
const pageDataCapabilityQuestions = self.$store.getters.pageData(
routeData.CAPABILITY_QUESTIONS.name
fmgPageValues.CAPABILITY_QUESTIONS
);
const pageDataMoldingQuestions = self.$store.getters.pageData(
routeData.MOLDING_QUESTIONS.name
fmgPageValues.MOLDING_QUESTIONS
);
const pageDataVehicleParts = self.$store.getters.pageData(routeData.VEHICLE_PARTS.name);
const pageDataVehicleParts = self.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
const pageDataPartQuestions = self.$store.getters.pageData(
routeData.PART_QUESTIONS.name
fmgPageValues.PART_QUESTIONS
);
const allPartsOrQuestions = [
@ -510,28 +518,28 @@ export default {
if (
hasCapabilityQuestions &&
this.currentPageComesAfterPage(currentPage, routeData.CAPABILITY_QUESTIONS.name)
this.currentPageComesAfterPage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS)
) {
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS;
} else if (
hasChildPartQuestions &&
this.currentPageComesAfterPage(currentPage, routeData.MOLDING_QUESTIONS.name)
this.currentPageComesAfterPage(currentPage, fmgPageValues.MOLDING_QUESTIONS)
) {
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS;
} else if (
hasGlassLocationWithMultipleParts &&
this.currentPageComesAfterPage(currentPage, routeData.VEHICLE_PARTS.name)
this.currentPageComesAfterPage(currentPage, fmgPageValues.VEHICLE_PARTS)
) {
backNavigationScenario =
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE;
} else if (
hasPartQuestions &&
this.currentPageComesAfterPage(currentPage, routeData.PART_QUESTIONS.name)
this.currentPageComesAfterPage(currentPage, fmgPageValues.PART_QUESTIONS)
) {
backNavigationScenario = navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS;
}
self.$router.navigateWithoutSaving(backNavigationScenario, self.pageName);
self.$router.navigateWithoutSaving(backNavigationScenario, self.$route);
},
},
};

View file

@ -1,11 +1,11 @@
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
import { shallowMount } from "@vue/test-utils";
import { setupMocksForJsFiles, getMountOptions } from "@/helpers/unit-test-helper.js";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { storeMutations } from "@/constants/store-mutations";
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { navigationScenarios } from "../router/router-constants/navigation-scenarios";
import { getters } from "@/store";
jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
@ -290,13 +290,13 @@ describe("vehicle-questions-mixin", () => {
describe("currentPageComesBeforePage", () => {
const testCases = [
[routeData.PART_QUESTIONS, routeData.VEHICLE_PARTS, true],
[routeData.VEHICLE_PARTS, routeData.VEHICLE_PARTS, false],
[routeData.QUOTE, routeData.VEHICLE_PARTS, false],
[routeData.QUOTE, routeData.QUOTE, false],
[routeData.VEHICLE_PARTS, routeData.PART_QUESTIONS, false],
[routeData.PART_QUESTIONS, routeData.CAPABILITY_QUESTIONS, true],
[routeData.MOLDING_QUESTIONS, routeData.CAPABILITY_QUESTIONS, true],
[fmgPageValues.PART_QUESTIONS, fmgPageValues.VEHICLE_PARTS, true],
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.VEHICLE_PARTS, false],
[fmgPageValues.QUOTE, fmgPageValues.VEHICLE_PARTS, false],
[fmgPageValues.QUOTE, fmgPageValues.QUOTE, false],
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.PART_QUESTIONS, false],
[fmgPageValues.PART_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, true],
[fmgPageValues.MOLDING_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, true],
];
test.each(testCases)(
"%s comes before %s is %s",
@ -305,10 +305,7 @@ describe("vehicle-questions-mixin", () => {
const { wrapper } = setupMocks({});
// Act
const result = wrapper.vm.currentPageComesBeforePage(
currentPage.name,
nextPage.name
);
const result = wrapper.vm.currentPageComesBeforePage(currentPage, nextPage);
// Assert
expect(result).toEqual(expectedResult);
@ -318,20 +315,20 @@ describe("vehicle-questions-mixin", () => {
describe("currentPageComesAfterPage", () => {
const testCases = [
[routeData.PART_QUESTIONS, routeData.VEHICLE_PARTS, false],
[routeData.VEHICLE_PARTS, routeData.VEHICLE_PARTS, false],
[routeData.QUOTE, routeData.VEHICLE_PARTS, true],
[routeData.QUOTE, routeData.QUOTE, false],
[routeData.VEHICLE_PARTS, routeData.PART_QUESTIONS, true],
[routeData.PART_QUESTIONS, routeData.CAPABILITY_QUESTIONS, false],
[routeData.MOLDING_QUESTIONS, routeData.CAPABILITY_QUESTIONS, false],
[fmgPageValues.PART_QUESTIONS, fmgPageValues.VEHICLE_PARTS, false],
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.VEHICLE_PARTS, false],
[fmgPageValues.QUOTE, fmgPageValues.VEHICLE_PARTS, true],
[fmgPageValues.QUOTE, fmgPageValues.QUOTE, false],
[fmgPageValues.VEHICLE_PARTS, fmgPageValues.PART_QUESTIONS, true],
[fmgPageValues.PART_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, false],
[fmgPageValues.MOLDING_QUESTIONS, fmgPageValues.CAPABILITY_QUESTIONS, false],
];
test.each(testCases)("%s comes after %s is %s", (currentPage, nextPage, expectedResult) => {
// Arrange
const { wrapper } = setupMocks({});
// Act
const result = wrapper.vm.currentPageComesAfterPage(currentPage.name, nextPage.name);
const result = wrapper.vm.currentPageComesAfterPage(currentPage, nextPage);
// Assert
expect(result).toEqual(expectedResult);
@ -1324,10 +1321,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -1437,10 +1436,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -1542,10 +1543,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -1695,10 +1698,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -1741,10 +1746,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -1851,10 +1858,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -2027,10 +2036,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -2084,10 +2095,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -2124,10 +2137,12 @@ describe("vehicle-questions-mixin", () => {
await wrapper.vm.navigateForward(partsOrQuestions);
// Assert
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithPageData).toHaveBeenCalledWith(
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledTimes(1);
expect(wrapper.vm.$router.navigateWithSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
wrapper.vm.$route.name,
wrapper.vm.$route,
{},
{},
{ partsOrQuestions }
);
});
@ -2300,7 +2315,7 @@ describe("vehicle-questions-mixin", () => {
test("current page is quote, there are no questions, and we have their vin => go to vin-lookup", async () => {
// Arrange
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name, hasVin: true });
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE, hasVin: true });
// Act
store.dispatch = jest.fn(() => {});
@ -2309,13 +2324,13 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
routeData.QUOTE.name
{ query: { fmgPage: fmgPageValues.QUOTE } }
);
});
test("current page is quote and there are capability questions => go to capability questions", async () => {
// Arrange
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name });
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE });
wrapper.vm.hasCapabilityQuestions = jest.fn().mockReturnValue(true);
// Act
@ -2325,13 +2340,13 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
routeData.QUOTE.name
{ query: { fmgPage: fmgPageValues.QUOTE } }
);
});
test("current page is quote and there are part questions and molding questions => go to molding questions", async () => {
// Arrange
const { wrapper } = setupMocks({ fmgPage: routeData.QUOTE.name });
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.QUOTE });
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
@ -2341,13 +2356,13 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
routeData.QUOTE.name
{ query: { fmgPage: fmgPageValues.QUOTE } }
);
});
test("current page is molding questions and there are part questions, multiple parts to choose, and capability questions => go to vehicle-parts", async () => {
// Arrange
const { wrapper } = setupMocks({ fmgPage: routeData.MOLDING_QUESTIONS.name });
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.MOLDING_QUESTIONS });
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
wrapper.vm.hasGlassLocationWithMultipleParts = jest.fn().mockReturnValue(true);
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
@ -2360,13 +2375,13 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
routeData.MOLDING_QUESTIONS.name
{ query: { fmgPage: fmgPageValues.MOLDING_QUESTIONS } }
);
});
test("current page is molding questions and there are part questions and capability questions => go to part-questions", async () => {
// Arrange
const { wrapper } = setupMocks({ fmgPage: routeData.MOLDING_QUESTIONS.name });
const { wrapper } = setupMocks({ fmgPage: fmgPageValues.MOLDING_QUESTIONS });
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
wrapper.vm.hasGlassLocationWithMultipleParts = jest.fn().mockReturnValue(false);
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
@ -2379,13 +2394,13 @@ describe("vehicle-questions-mixin", () => {
// Assert
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
routeData.MOLDING_QUESTIONS.name
{ query: { fmgPage: fmgPageValues.MOLDING_QUESTIONS } }
);
});
});
});
function setupMocks({ fmgPage = routeData.VIN_LOOKUP.name, hasVin, carId }) {
function setupMocks({ fmgPage = fmgPageValues.VIN_LOOKUP, hasVin, carId }) {
const baseMixin = setupMocksForJsFiles({
actionList: [
{
@ -2408,7 +2423,6 @@ function setupMocks({ fmgPage = routeData.VIN_LOOKUP.name, hasVin, carId }) {
navigate: jest.fn(),
navigateWithSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
navigateWithPageData: jest.fn(),
},
store: {
commit: jest.fn(),
@ -2422,7 +2436,9 @@ function setupMocks({ fmgPage = routeData.VIN_LOOKUP.name, hasVin, carId }) {
},
},
route: {
name: fmgPage,
query: {
fmgPage,
},
},
});

View file

@ -58,9 +58,6 @@ function setupMocks({ partsOrQuestions = [] }) {
},
},
},
route: {
name: "vin-lookup",
},
});
const mockVinComponent = {

View file

@ -1,13 +0,0 @@
import { routeData } from "./routes";
export const autoRouteTable = [
routeData.QUOTE,
routeData.CAPABILITY_QUESTIONS,
routeData.MOLDING_QUESTIONS,
routeData.VEHICLE_PARTS,
routeData.PART_QUESTIONS,
routeData.VIN_LOOKUP,
routeData.ESTIMATE,
routeData.VEHICLE_DAMAGE,
routeData.VEHICLE,
];

View file

@ -1,3 +0,0 @@
export const ROUTE_PREFIX_TRIMMED = "fmg";
export const ROUTE_PREFIX_FULL = `/${ROUTE_PREFIX_TRIMMED}/`;

View file

@ -1,123 +0,0 @@
export const routeData = {
VEHICLE: {
name: "vehicle",
path: "/vehicle",
},
VEHICLE_DAMAGE: {
name: "vehicle-damage",
path: "/vehicle-damage",
},
ESTIMATE: {
name: "estimate",
path: "/estimate",
},
ADDRESS_LOOKUP: {
name: "address-lookup",
path: "/address-lookup",
},
VIN_LOOKUP: {
name: "vin-lookup",
path: "/vin-lookup",
},
LICENSE_PLATE_LOOKUP: {
name: "license-plate-lookup",
path: "/license-plate-lookup",
},
SERVICE_ZIP: {
name: "service-zip",
path: "/service-zip",
},
ADDRESS_VEHICLES: {
name: "address-vehicles",
path: "/address-vehicles",
},
VEHICLE_PARTS: {
name: "vehicle-parts",
path: "/vehicle-parts",
},
PART_QUESTIONS: {
name: "part-questions",
path: "/part-questions",
},
MOLDING_QUESTIONS: {
name: "molding-questions",
path: "/molding-questions",
},
CAPABILITY_QUESTIONS: {
name: "capability-questions",
path: "/capability-questions",
},
QUOTE: {
name: "quote",
path: "/quote",
},
INSURANCE_COMPANY: {
name: "insurance-company",
path: "/insurance-company",
},
SERVICE_LOCATION: {
name: "service-location",
path: "/service-location",
},
HERITAGE: {
name: "heritage",
path: "/virtual/heritage",
virtual: true,
},
SCHEDULE: {
name: "schedule",
path: "/schedule",
},
CUSTOMER_DETAILS: {
name: "customer-details",
path: "/customer-details",
},
PAYMENT_METHOD: {
name: "payment-method",
path: "/payment-method",
},
PAYMENT: {
name: "payment",
path: "/payment",
},
PAYMENT_PIA_RETURN: {
name: "payment-pia-return",
path: "/payment-pia-return",
},
CONFIRMATION: {
name: "confirmation",
path: "/confirmation",
},
RETURN_USER: {
name: "return-user",
path: "/return-user",
},
LOAD_SESSION: {
name: "load-session",
path: "/virtual/load-session",
virtual: true,
},
LANDING: {
name: "landing",
path: "/",
virtual: true,
},
AUTO_ROUTE: {
name: "auto-route",
path: "/virtual/auto-route",
virtual: true,
},
// TODO: RENAME FROM BAILOUT
ERROR: {
name: "error",
path: "/virtual/error",
virtual: true,
},
RESTART: {
name: "restart",
path: "/virtual/restart",
virtual: true,
},
};
export const FUNNEL_START_PAGE = routeData.VEHICLE;

View file

@ -1,3 +1,3 @@
export function lazyLoadComponent(componentName) {
return () => import(`@/layouts/${componentName}/${componentName}.vue`);
return () => import(`@/layouts/${componentName}/${componentName}.vue`); // /src/layouts/folder/component.vue
}

View file

@ -1,41 +1,936 @@
import { routes } from "@/router/methods/routes";
import { afterEach } from "@/router/methods/after-each";
import { beforeEach } from "@/router/methods/before-each";
import { bailout } from "@/router/methods/error";
import {
navigateWithoutSaving,
navigateWithSaving,
navigateWithPageData,
navigateAndForceTopLevelNavigation,
} from "@/router/methods/navigate";
import { navigateToExternalUrl } from "@/router/methods/navigate-external";
import { sendToReturnUser } from "@/router/methods/send-to-return-user";
// Supporting files
import { createWebHistory, createRouter } from "vue-router";
import { ROUTE_PREFIX_FULL } from "@/router/constants/route-prefix";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "../constants/store-mutations";
import { sessionStorageKeyConstants } from "@/constants/session-storage.js";
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
import { routingTable } from "@/router/router-constants/routing-table.js";
import { globalEvents, globalEventTypes } from "@/constants/events";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter, buildQuerystringObject } from "@/helpers/querystring-helper";
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
import { showFmgLoadingModal } from "@/helpers/loading-modal-helper";
import { fmgPageValues, funnelStartPageName } from "@/router/router-constants/fmgPage-values";
import { externalParameterStatus } from "@/constants/external-parameters";
// Heritage integration
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
import {
updateOrCreateFunnelCookie,
getFunnelCookie,
updateSessionIdCookie,
deleteFunnelCookie,
getAffiliateCookies,
setupAdvertiserTracking,
} from "@/helpers/heritage-integration/cookie-helper";
import { loadSessionIfPresent, saveSession } from "@/helpers/heritage-integration/order-helper";
import {
getPageToRouteExistingOrderTo,
navigateToHeritageFunnel,
getImplicitNavigation,
} from "@/helpers/heritage-integration/navigation-helper";
import baseMixin from "@/mixins/base-mixin";
import eventBus from "@/helpers/event-bus/event-bus";
import store from "@/store";
import analyticsMixin from "@/mixins/analytics-mixin";
import { experimentTriggers } from "../constants/experiments";
import { applicationConfig } from "../constants/application-config";
import { shouldStripPromoQueryString } from "@/helpers/promotions-helper";
import bailout from "@/layouts/bailout/bailout";
import { nextTick } from "vue";
import { getBoolFromString } from "@/helpers/boolean-helper";
const routes = [
{
path: "/bailout",
name: "bailout",
component: bailout,
},
{
path: "/",
name: "root",
async beforeEnter(to, from, next) {
// If we have no query string, or we don't have the FmgPage query string.
try {
log("------------- router index.js beforeEnter start -----------------");
log(" --to: ", to);
log(" --cookie: ", getFunnelCookie());
log(` --from.redirectedFrom:>${JSON.stringify(from.redirectedFrom)}<`, "");
await analyticsMixin.methods.validateSession();
var fromHeritage = getQuerystringParameter(queryStrings.FROM_HERITAGE);
var offerQuote = getQuerystringParameter(queryStrings.OFFER_QUOTE);
log(" --offerQuote: ", offerQuote);
// after session is validated, remove the fromHeritage querystring if it exists so session expiration works
if (to.query) {
delete to.query[queryStrings.FROM_HERITAGE];
}
//remove offerquote querystring if it exists
if (offerQuote) {
delete to.query[queryStrings.OFFER_QUOTE];
}
if (getFunnelCookie()?.SuppressConceptFunnel) {
log(" --go to heritage suppressConceptFunnel: ");
await navigateToHeritageFunnel({ shouldSaveSession: false });
return next(false);
}
// If the saved session has timed out, clear the session, execute 404 logic.
if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
log(" --save session timeout go to start");
const errorPayload = {
cause: "expired session",
currentPage: from?.query?.fmgPage,
nextPage: to?.query?.fmgPage,
};
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
deleteFunnelCookie();
GoToFunnelStartOn404(next, errorPayload);
return;
}
const fromReturnUser = from?.name === fmgPageValues.RETURN_USER;
const fromContentSite = getQuerystringParameter(queryStrings.START_TYPE) === "fmg";
const toReturnUserPage = to.query?.fmgPage === fmgPageValues.RETURN_USER;
log(" --fromReturnUser ", fromReturnUser);
log(" --to.query.fmgPage ", to.query?.fmgPage);
// Intercept all navigation if a submitted order exists in storage
if (
window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !==
null
) {
if (to.query.fmgPage !== funnelStartPageName) {
to.query.fmgPage = fmgPageValues.CONFIRMATION;
log(
` --has ${sessionStorageKeyConstants.SUBMITTED_STATE} go to confirmation`
);
}
}
// On entering the funnel "fresh", read cookie information, decide what to do next.
else if (from.redirectedFrom === undefined || fromReturnUser) {
// if entering the funnel from the content site, check and see if there is already a vehicle year in vuex.
// if so, send them to return-user page.
if (
fromContentSite &&
!toReturnUserPage &&
store.getters.order.vehicle?.year > 0
) {
log(" --from content site navigate to return user");
var qso = {
fmgPage: fmgPageValues.RETURN_USER,
};
const newQueryString = buildQuerystringObject(qso, true);
log(" -- returnUser add querystring: " + JSON.stringify(newQueryString));
router.push({
path: "/",
query: Object.assign({}, newQueryString),
});
return;
}
// clear the saveSessionPromise - if it exists in the vuex store but a new instance was created
// the saveSessionPromise will no longer point to a valid promise
log(" --clear promise");
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
if (!to.query.fmgPage?.startsWith("payment")) {
//payment pages used to return from safelitehop so exclude here
// Remove the parameter after quote release
// for testing end to end locally, see if there is a referralNumber on the querystring
// that could have changed in heritage and then stick it in the store and then update the cookie
// so load-session runs properly. this can be removed when heritage goes away
const referralNumber = getQuerystringParameter(
queryStrings.REFERRAL_NUMBER
);
const parentAccount = getQuerystringParameter(queryStrings.PARENT_ACCOUNT);
const correlationId = getQuerystringParameter(queryStrings.CORRELATION_ID);
if (referralNumber) {
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
store.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccount);
store.commit(
storeMutations.UPDATE_REFERRAL_CORRELATION_ID,
correlationId
);
log(" --update cookie");
updateOrCreateFunnelCookie();
}
//Affiliate Cookies
const affiliateCookies = getAffiliateCookies();
if (affiliateCookies != null && affiliateCookies.length > 0) {
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
}
setupAdvertiserTracking();
log(" --load session start");
const loadSessionResponse = await loadSessionIfPresent(
to.query.isInsurance != null
? to.query.isInsurance == "true"
? true
: false
: null,
to.query.fmgPage
);
log(" --load session end");
//Update external parameter state but not when returning from heritage
if (!to.query.fmgPage?.startsWith("service-location") && !fromReturnUser) {
updateExternalParameterState();
}
//Update CASH tab when return from heritage and have offerQuote param
if (offerQuote === "true" && fromHeritage === "true") {
store.commit(storeMutations.UPDATE_IS_INSURANCE, false);
}
// clear part related state because heritage selected a new vehicle
if (
to.query.fmgPage === fmgPageValues.VEHICLE &&
getBoolFromString(getFunnelCookie()?.HasDelayedClaimRegistration) &&
!fromReturnUser
) {
store.commit(storeMutations.RESET_GLASS_PARTS_STATE);
}
// if coming from the return user page, clear the destination page so implicit navigation runs
log(" --to.query ", JSON.stringify(to.query));
if (fromReturnUser && to.query) {
log(" --clear to.query");
delete to.query[queryStrings.FMG_PAGE];
//to.query[queryStrings.FMG_PAGE] = "";
log(" --to.query cleared ", JSON.stringify(to.query));
}
const pageToRedirectTo = await getPageToRouteExistingOrderTo(to);
log(" --pageToRedirectTo ", JSON.stringify(pageToRedirectTo));
// This logic may determine that the user should be sent to heritage -- if so, do that here.
if (pageToRedirectTo === fmgPageValues.HERITAGE) {
// prettier-ignore
log(" --go to heritage pageToRedirectTo ", JSON.stringify(pageToRedirectTo));
await navigateToHeritageFunnel({ shouldSaveSession: false });
return next(false);
}
// Assign our fmgPage so it will load normally like the other pages.
to.query.fmgPage = pageToRedirectTo;
log(" --assign to: ", JSON.stringify(pageToRedirectTo));
}
}
// Reroute around pages that should not be available.
// Exception 1: Integrated Users should not see vehicle or quote pages.
if (
store.getters.payment?.insuranceCoverage?.isVerified ||
store.getters.order?.referralNumber?.length === 6
) {
if (to.query.fmgPage === fmgPageValues.VEHICLE) {
to.query.fmgPage = fmgPageValues.VEHICLE_DAMAGE;
} else if (
to.query.fmgPage === fmgPageValues.QUOTE ||
to.query.fmgPage === fmgPageValues.INSURANCE_COMPANY
) {
log(" --block quote page for integrated clients - go to heritage");
// Push to heritage if going to quote & integrated.
await navigateToHeritageFunnel({ shouldSaveSession: false });
return next(false);
}
}
await runExperiments(to.query.fmgPage);
//Affiliate Cookies
const affiliateCookies = getAffiliateCookies();
if (affiliateCookies != null && affiliateCookies.length > 0) {
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
}
setupAdvertiserTracking();
// Process funnel cookie.
updateOrCreateFunnelCookie();
// If we already have our route, go to it.
if (router.hasRoute(to.query.fmgPage)) {
// Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
let component = router
.getRoutes()
.filter((x) => x.name === to.query.fmgPage)[0].components;
// If the component hasn't been loaded fully, load it before we check prerequisites.
if (component.default.methods === undefined) {
component = await component.default();
}
if (!arePagePrerequisitesValid(component)) {
console.log("Page prereq error: " + component.default.name);
if (to.query.fmgPage === fmgPageValues.PAYMENT) {
await store.getters.applicationUser.saveSessionPromise;
window.location = applicationConfig.PIA_CANCEL_URL;
return;
}
const errorPayload = {
cause: "invalid page prerequisites for page",
currentPage: from?.query?.fmgPage,
nextPage: to?.query?.fmgPage,
};
GoToFunnelStartOn404(next, errorPayload);
return;
}
log(" --has route:", to.query.fmgPage);
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
}
if (!isExistingFmgPageName(to.query.fmgPage)) {
const errorPayload = {
cause: "invalid page name",
currentPage: from?.query?.fmgPage,
nextPage: to?.query?.fmgPage,
};
GoToFunnelStartOn404(next, errorPayload);
return;
}
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
const routeData = GetRouteInfoFromPageName(to.query.fmgPage);
log("--routeData:", routeData);
// Add our dynamic route.
router.addRoute({
path: routeData[0].path, // Always the same path, because we control it with query strings.
name: routeData[0].name,
component: routeData[0].component,
});
// Call the next components arePagePrerequisitesValid method before load.
// If it returns false, use the 404 logic.
const nextComponent = await router
.getRoutes()
.filter((x) => x.name === routeData[0].name)[0]
.components.default();
if (!arePagePrerequisitesValid(nextComponent)) {
// prettier-ignore
console.log("Page Prereqs not valid for next component: " + nextComponent.default.name);
const errorPayload = {
cause: "invalid page prerequisites for page",
currentPage: from?.query?.fmgPage,
nextPage: to?.query?.fmgPage,
};
GoToFunnelStartOn404(next, errorPayload);
return;
}
log("------------- router index.js beforeEnter end -----------------");
// Assign current query string parameters, as well as our fmgPage one.
next({
name: routeData[0].name,
query: Object.assign(to.query, { fmgPage: routeData[0].name }),
params: to.params,
});
} catch (error) {
global.$logger.logError(`Routing ${error.stack}`);
if (to.query?.fmgPage === funnelStartPageName) {
deleteFunnelCookie();
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
}
console.log(new Date() + " Exception in beforeEnter:" + JSON.stringify(error));
// If we don't have a route, go to our 404 page.
const errorPayload = {
cause: "uncaught error in beforeEnter",
currentPage: from?.query?.fmgPage,
nextPage: to?.query?.fmgPage,
fullError: error,
errorStack: error?.stack,
};
GoToFunnelStartOn404(next, errorPayload);
return;
}
},
},
];
const router = createRouter({
history: createWebHistory(ROUTE_PREFIX_FULL),
history: createWebHistory("/fmg/"),
routes,
// Scroll to top on navigation.
//Cause "page" to begin at the top when route chanages.
scrollBehavior(to, from, savedPosition) {
// always scroll to top
return { top: 0 };
},
});
// Set guards
router.afterEach(async (to, from) => afterEach(to, from));
router.beforeEach(async (to, from) => beforeEach(to, from));
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
// Bind methods for external use
router.navigateWithSaving = navigateWithSaving;
router.navigateWithoutSaving = navigateWithoutSaving;
router.navigateWithPageData = navigateWithPageData;
router.navigateAndForceTopLevelNavigation = navigateAndForceTopLevelNavigation;
router.beforeEach(async (to, from, next) => {
log("------------- router index.js beforeEach start -----------------");
// set lastNavigationPage here to capture state before API calls for analytics.
// use current page url query string name when to.name is "root" (due to unresolved navigation in beforeEach)
router.lastNavigationPage = to.name == "root" ? analyticsMixin.methods.getPageName() : to.name;
router.bailout = bailout;
const fromQueryPage = from.query?.fmgPage;
if (fromQueryPage === undefined) {
showFmgLoadingModal(true);
}
router.navigateToExternalUrl = navigateToExternalUrl;
const toQueryPage = to.query?.fmgPage;
const notToPIAReturn = toQueryPage != fmgPageValues.PAYMENT_PIA_RETURN;
const isInIframe = window !== window.top;
router.sendToReturnUser = sendToReturnUser;
if (store.getters.externalParameterState?.isExternalParameter) {
// Check if alert event is on the bus
const alertEvent = eventBus.readEventFromBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.PAGE_NOT_FOUND
);
//Uknown alerts most likely were added by a failed api call in global-methods
const unknownAlertEvent = eventBus.readEventFromBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.UNKNOWN_ERROR
);
// If alert event is on the bus, then display the alert
if (alertEvent !== undefined || unknownAlertEvent !== undefined) {
store.commit(
storeMutations.UPDATE_IS_EXTERNAL_PARAMETER,
externalParameterStatus.INACTIVE
);
}
}
// fromPaymentToConfirmation workaround for navigating from an iframe but
// isInIframe evaluates to false for some reason when navigating from payment to confirmation
const fromPaymentToConfirmation =
fromQueryPage === fmgPageValues.PAYMENT && toQueryPage === fmgPageValues.CONFIRMATION;
if ((isInIframe && notToPIAReturn) || fromPaymentToConfirmation) {
const newUrl = `${window.top.location.origin}${to.href}`;
window.top.location.href = newUrl;
next(false);
// Refresh page if navigating to self to prevent locking.
// For now only carved out for vehicle; all modals are opened through anchor tags at the moment,
// which also self navigate, but relied on the page remaining the same on self-navigation.
} else if (toQueryPage === fromQueryPage && toQueryPage === getRedirectedStartPage()) {
router.go(0);
next(false);
} else {
next();
}
log("------------- router index.js beforeEach end -----------------");
});
router.afterEach(async (to, from) => {
// Update lastPageVisited in the store
store.commit(storeMutations.UPDATE_LAST_PAGE_VISITED, to.name);
// If saving on navigation is requested, check for saved SessionId or EmailAddress to determine if saving is appropriate
if (getBoolFromString(window.history.state.isSavingNavigation)) {
if (
store.getters.applicationUser.savedSessionId ||
store.getters.order.customer?.emailAddress
) {
await saveSession({ pageNameToLog: to.query.fmgPage });
}
}
// Push page view to GA
analyticsMixin.methods.pushPageViewToGA();
// Push experiments to Data Layer
analyticsMixin.methods.pushExperimentsToDataLayer();
// Push current order status to Data Layer
analyticsMixin.methods.pushOrderToDataLayer();
if (to.query.fmgPage == fmgPageValues.CONFIRMATION) {
//Push Ecommerce Cart to Data Layer
analyticsMixin.methods.pushECommerceCartToDataLayer();
//Push Product Array to Data Layer
analyticsMixin.methods.pushProductArrayToDataLayer();
//Push Commission Junction Gtm Data To Data Layer
analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer();
}
});
router.navigateWithoutSaving = (
scenario,
currentRoute,
optionalQuery = {},
optionalParams = {},
optionalPageData = {}
) => {
navigate(scenario, currentRoute, false, optionalQuery, optionalParams, optionalPageData);
};
router.navigateWithSaving = (
scenario,
currentRoute,
optionalQuery = {},
optionalParams = {},
optionalPageData = {}
) => {
navigate(scenario, currentRoute, true, optionalQuery, optionalParams, optionalPageData);
};
router.navigateToExternalUrl = (url, optionalQuery = {}) => {
log("------------- router navigateToExternalUrl -----------------");
log("url:", url);
navigateToUrl(url, optionalQuery);
};
router.navigateError = (errorPayload = null) => {
DisplayPageError(errorPayload);
};
//Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example.
router.overrideNavigation = (
scenario,
currentRoute,
next,
isSavingNavigation,
optionalQuery = {},
optionalParams = {},
optionalPageData
) => {
log("------------- router overrideNavigation -----------------");
log("scenario:", scenario);
log("currentRoute:", currentRoute);
log("isSavingNavigation:", isSavingNavigation);
log("optionalQuery:", optionalQuery);
log("optionalParams:", optionalParams);
log("optionalPageData:", optionalPageData);
navigate(
scenario,
currentRoute,
isSavingNavigation,
optionalQuery,
optionalParams,
optionalPageData
);
next();
};
router.getNextPage = () => nextPageName;
// PRIVATE VARIABLES
var nextPageName;
// PRIVATE FUNCTIONS
// Navigate to the next route, depending on the scenario.
async function navigate(
scenario,
currentRoute,
isSavingNavigation,
optionalQuery = {},
optionalParams = {},
optionalPageData = {}
) {
if (!scenario) {
console.error("No scenario provided. Please review the routing table.");
return;
}
// Match our maps up and navigate if we have a destination.
const matchingScenarioMap = getNavigationMap(scenario, currentRoute);
const destinationFmgPageValue = matchingScenarioMap.destinationFmgPageValue;
if (destinationFmgPageValue !== undefined) {
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one.
nextPageName = destinationFmgPageValue;
// Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object
const existingPageDataForPage = store.getters.pageData(destinationFmgPageValue);
baseMixin.methods.savePageDataToStore(
destinationFmgPageValue,
Object.keys(optionalPageData).length > 0
? optionalPageData
: (existingPageDataForPage ?? {})
);
optionalParams.isSavingNavigation = isSavingNavigation;
// add querystring params to the route. if they are already in the store then no need to add them
var queryStringsObject = {
fmgPage: destinationFmgPageValue,
};
const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE);
const zip = getQuerystringParameter(queryStrings.ZIP_CODE);
const promo = getQuerystringParameter(queryStrings.PROMO);
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
const logQs = getQuerystringParameter(queryStrings.LOG);
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, logQs, false);
log("------------- router index.js navigate start -----------------");
log(" --scenario: ", scenario);
log(" --isSavingNavigation: ", isSavingNavigation);
log(" --optionalQuery: ", optionalQuery);
log(" --optionalParams: ", optionalParams);
log(" --optionalPageData: ", optionalPageData);
log(" --nextPageName: ", nextPageName);
if (
hasZip &&
(store.getters.order.serviceLocation.zipCode === undefined ||
store.getters.order.serviceLocation.zipCode == null) &&
(store.getters.order.vehicle.registration.zipCode === undefined ||
store.getters.order.vehicle.registration.zipCode == null)
) {
queryStringsObject[queryStrings.ZIP_CODE] = zip;
}
if (promo && !shouldStripPromoQueryString(currentRoute.query.fmgPage)) {
queryStringsObject[queryStrings.PROMO] = promo;
}
if (pageError) {
queryStringsObject[queryStrings.PAGE_ERROR] = pageError;
}
if (logQs) {
queryStringsObject[queryStrings.LOG] = logQs;
}
log(" querystrings: ", queryStringsObject);
log("------------- router index.js navigate end -----------------");
router.push({
name: "root",
query: Object.assign(optionalQuery, queryStringsObject),
state: optionalParams,
});
} else if (matchingScenarioMap.destinationUrl !== undefined) {
navigateToUrl(matchingScenarioMap.destinationUrl, optionalQuery);
}
}
// Get navigation map depending on the scenario and the current 'page' you're on.
function getNavigationMap(scenario, currentRoute) {
const fmgPageValue = currentRoute.query.fmgPage;
log("------------- router index.js getNavigationMap start -----------------");
log("fmgPage: " + fmgPageValue + " scenario: " + scenario, "");
log("------------- router index.js getNavigationMap end -----------------");
const matchedQueryValue = routingTable(store)
.filter(
(item) =>
item.fmgPageValue === fmgPageValue &&
item.maps.filter((map) => map.scenario === scenario).length > 0
)
.map((m) => m.maps.filter((map) => map.scenario === scenario))[0]
.filter((x) => x.filter === true || x.filter === undefined);
return matchedQueryValue[0];
}
function log(message, data) {
const log = getQuerystringParameter(queryStrings.LOG);
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, log, false);
data = data ?? "";
const outData = typeof data === "object" ? JSON.stringify(data) : data;
if (log === "true" || store.getters.applicationUser.loggingOption) {
console.log(new Date() + message + outData);
}
}
//---------------------------------------------------------- Private Functions ----------------------------------------------------------
// Navigate to an external url.
function navigateToUrl(url, optionalQuery = {}) {
// possibly show some loading screen in the future here.
var externalUrl = new URL(url);
for (const queryKey in optionalQuery) {
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
}
window.location.assign(externalUrl);
}
// Get route information by page name.
// This will no longer reach out to the Cms. There is a 1:1 relationship between page names and route names and layouts.
function GetRouteInfoFromPageName(pageName) {
// check if pagename is a valid route/component
if (!isExistingFmgPageName(pageName)) {
return [];
}
const routeData = [
{
path: "/",
name: pageName,
component: lazyLoadComponent(pageName),
},
];
return routeData;
}
// Go to our start page on a 404.
function GoToFunnelStartOn404(next, errorPayload = null) {
if (errorPayload !== null) {
errorPayload.type = "GoToFunnelStartOn404";
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
console.log(
"%cGoToFunnelStartOn404()... errorPayload",
"color: white; background-color: blue; padding: 5px;",
errorPayload
);
}
// Put item on the bus
eventBus.addEventToBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.PAGE_NOT_FOUND,
{
isDismissible: true,
messageCopy: "You can get a quote by starting on this page.",
messageHeadline: "We're sorry, something went wrong.",
type: globalEventTypes.Danger,
}
);
next({
path: "/",
query: { fmgPage: funnelStartPageName },
});
}
async function DisplayPageError(errorPayload = null) {
console.log("%c running DisplayPageError()... ", "font-size: 20px; color: purple;");
if (errorPayload !== null) {
errorPayload.type = "DisplayPageError";
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
} else {
// very cautiously to avoid additional errors:
var currentPage = "";
try {
currentPage = getQuerystringParameter(queryStrings.FMG_PAGE);
} catch (e) {
// pass
}
errorPayload = {
type: "DisplayPageError",
cause: "Unknown page error",
currentPage: currentPage,
};
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
}
// Put item on the bus
eventBus.addEventToBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.UNKNOWN_ERROR,
{
isDismissible: true,
messageCopy: "",
messageHeadline: "We're sorry, something went wrong.",
type: globalEventTypes.Danger,
}
);
if (
store.getters.externalParameterState?.isExternalParameter == externalParameterStatus.ACTIVE
) {
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.INACTIVE);
}
baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR);
// we use the pageError querystring as a counter to how many times a user has experienced an error and been routed here.
// once they receive more than 1 pageerrors, we'll reset their state to hopefully correct any issues they may be having.
var navPage = fmgPageValues.VEHICLE;
if (store.getters.payment?.insuranceCoverage?.isVerified) {
navPage = fmgPageValues.VEHICLE_DAMAGE;
}
if (pageError) {
var errorCount = Number(pageError);
if (errorCount > 1) {
deleteFunnelCookie();
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
router.push({
path: "/",
query: { fmgPage: navPage },
});
} else {
errorCount++;
router.push({
path: "/",
query: { fmgPage: navPage, pageError: errorCount },
});
}
} else {
router.push({
path: "/",
query: { fmgPage: navPage, pageError: "1" },
});
}
}
function isExistingFmgPageName(pageName) {
const names = Object.values(fmgPageValues);
return names.some((name) => name === pageName);
}
// Checks arePagePrerequisitesValid on the component passed in.
function arePagePrerequisitesValid(component) {
return component.default.methods.arePagePrerequisitesValid();
}
// Run SiteEntry and PageEntry triggers for experiments
async function runExperiments(nextPage) {
if (!store.getters.applicationUser.triggeredSiteEntry) {
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.SITE_ENTRY,
triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE,
},
nextPage
);
}
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.PAGE_ENTRY,
triggerValue: nextPage,
},
nextPage
);
}
function getRedirectedStartPage() {
if (store.getters.payment?.insuranceCoverage?.isVerified) {
return fmgPageValues.VEHICLE_DAMAGE;
} else {
return funnelStartPageName;
}
}
function updateExternalParameterState() {
const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR);
const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE);
const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL);
const externalParameterStyle = getQuerystringParameter(queryStrings.VEHICLE_STYLE);
const externalParameterDamage = getQuerystringParameter(queryStrings.VEHICLE_DAMAGE);
const externalParameterZipCode = getQuerystringParameter(queryStrings.SERVICE_ZIP);
const externalParameterEmail = getQuerystringParameter(queryStrings.EMAIL);
const externalParameterIsInsurance = getQuerystringParameter(queryStrings.IS_INSURANCE);
const externalParameterVinSelection = getQuerystringParameter(queryStrings.VIN_SELECTION);
const externalParameterServicePackage = getQuerystringParameter(queryStrings.SERVICE_PACKAGE);
const externalParameterNumberOfChips = getQuerystringParameter(queryStrings.NUMBER_OF_CHIPS);
const externalParameterSource = getQuerystringParameter(queryStrings.EXPERIMENTS);
const externalParameterPhoneNumber = getQuerystringParameter(queryStrings.PHONE_NUMBER);
if (
externalParameterYear &&
externalParameterMake &&
externalParameterModel &&
externalParameterStyle
) {
resetStoreForExternalParameter();
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_STYLE, externalParameterStyle);
}
if (
externalParameterDamage &&
(externalParameterDamage.toUpperCase() != "WINDSHIELDREPAIR" ||
externalParameterNumberOfChips?.length > 0)
) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_DAMAGE_TYPE, externalParameterDamage);
if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPLACE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS, null);
} else if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPAIR") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS,
externalParameterNumberOfChips
);
}
}
if (externalParameterZipCode) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
}
if (externalParameterEmail) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS,
externalParameterEmail
);
}
if (externalParameterIsInsurance?.toUpperCase() == "TRUE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_INSURANCE, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_SERVICE_PACKAGE,
externalParameterServicePackage?.toLowerCase()
);
}
if (externalParameterDamage?.toUpperCase() != "WINDSHIELDREPAIR") {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION,
externalParameterVinSelection
);
}
if (externalParameterSource) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource);
}
if (externalParameterPhoneNumber) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
externalParameterPhoneNumber
);
}
}
// if there is an existing external parameter state then they have already been through from an external source(LeadGen) and
// are returning. clear out prior related things that need to be selected again like parts and damage type.
function resetStoreForExternalParameter() {
if (
store.getters.externalParameterState?.isExternalParameter ==
externalParameterStatus.INACTIVE
) {
store.dispatch(storeActions.RESET_VEHICLE_STATE_AND_DEPENDENCIES);
store.dispatch(storeActions.SAVE_SERVICE_ZIP_CODE_INFO, {
state: null,
zipCode: null,
zipCodeCtu: null,
});
store.dispatch(storeActions.SAVE_EMAIL, null);
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
}
export default router;

View file

@ -1,12 +0,0 @@
import analyticsMixin from "@/mixins/analytics-mixin";
export async function afterEach(to, from) {
// Push page view to GA
analyticsMixin.methods.pushPageViewToGA();
// Push experiments to Data Layer
analyticsMixin.methods.pushExperimentsToDataLayer();
// Push current order status to Data Layer
analyticsMixin.methods.pushOrderToDataLayer();
}

View file

@ -1,105 +0,0 @@
import { queryStrings } from "@/constants/query-strings";
import { sessionStorageKeyConstants } from "@/constants/session-storage";
import {
getFunnelCookie,
updateOrCreateFunnelCookie,
} from "@/helpers/heritage-integration/cookie-helper";
import { loadSessionIfPresent } from "@/helpers/heritage-integration/order-helper";
import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper";
import analyticsMixin from "@/mixins/analytics-mixin";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
import { runExperiments } from "@/router/methods/helpers/run-experiments";
import { bailout } from "@/router/methods/error";
import { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
import { checkLogParam } from "@/helpers/debug-log-helper";
import { debugLog } from "@/helpers/debug-log-helper";
export async function beforeEach(to, from) {
try {
await analyticsMixin.methods.validateSession();
// prettier-ignore
{
debugLog(`--- before-each.js ${from?.name} start ---`);
debugLog(" funnel cookie init: ", getFunnelCookie());
}
if (getFunnelCookie()?.SuppressConceptFunnel) {
// Redirect to heritage.
return {
name: routeData.HERITAGE.name,
};
}
// Ensure session has not expired
if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
const errorPayload = {
cause: "expired session",
currentPage: from?.name,
nextPage: to?.name,
};
bailout(errorPayload, true);
return false;
}
// Block navigation if an order has been submitted.
if (window.sessionStorage.getItem(sessionStorageKeyConstants.SUBMITTED_STATE) !== null) {
if (to.name !== FUNNEL_START_PAGE.name && to.name !== routeData.CONFIRMATION.name) {
return false;
}
}
// If sent from heritage, need to load session.
const fromHeritageFlag = consumeQueryFromStash(queryStrings.FROM_HERITAGE);
if (fromHeritageFlag) {
await loadSessionIfPresent(true, routeData.SERVICE_LOCATION.name);
}
// Process funnel cookie.
updateOrCreateFunnelCookie();
// prettier-ignore
{
debugLog(`--- before-each.js ${from?.name} start ---`);
debugLog(" funnel cookie after: ", getFunnelCookie());
}
// Update if logging is enabled.
checkLogParam();
// Ensure page-prerequisites are fulfilled
const arePagePrerequisitesValid = await checkPagePrerequisites(to.name);
if (!arePagePrerequisitesValid) {
const errorPayload = {
cause: "invalid page prerequisites for page",
currentPage: from?.name,
nextPage: to?.name,
};
bailout(errorPayload);
return;
}
await runExperiments(to.name);
// prettier-ignore
{
debugLog("--- before-each.js end ---");
}
} catch (error) {
const errorPayload = {
cause: "Uncaught exception in `beforeEach`.",
currentPage: from?.name,
nextPage: to?.name,
};
console.log(error);
bailout(errorPayload);
return;
}
}

View file

@ -1,17 +0,0 @@
import analyticsMixin from "@/mixins/analytics-mixin";
import { routeData } from "@/router/constants/routes";
import router from "@/router";
export async function bailout(errorPayload, forceRestart = false) {
analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload);
if (forceRestart) {
router.push({
name: routeData.RESTART.name,
});
} else {
router.push({
name: routeData.ERROR.name,
});
}
}

View file

@ -1,5 +0,0 @@
import router from "@/router";
export function getRoute(pageName) {
return router.getRoutes().find((r) => r.name === pageName);
}

View file

@ -1,27 +0,0 @@
import { ROUTE_PREFIX_TRIMMED } from "@/router/constants/route-prefix";
export function buildManualUrl(nextPage) {
const queries = nextPage.params;
const querystring = buildSearchParams(queries);
const url = `${window.top.location.origin}/${ROUTE_PREFIX_TRIMMED}${nextPage.path}${querystring}`;
return url;
}
export function buildSearchParams(paramList) {
if (!paramList) {
return "";
}
const keys = Object.keys(paramList);
if (keys?.length > 0) {
const queryFormattedParams = keys.map((k) => `${k}=${paramList[k]}`);
const querystring = queryFormattedParams.reduce((a, b) => `${a}&${b}`);
return `?${querystring}`;
}
return "";
}

View file

@ -1,18 +0,0 @@
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { queryStrings } from "@/constants/query-strings";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { updateOrCreateFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
export async function consumeReferralQuerystrings() {
const referralNumber = getQuerystringParameter(queryStrings.REFERRAL_NUMBER);
const parentAccount = getQuerystringParameter(queryStrings.PARENT_ACCOUNT);
const correlationId = getQuerystringParameter(queryStrings.CORRELATION_ID);
if (referralNumber) {
store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
store.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccount);
store.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, correlationId);
// log(" --update cookie");
updateOrCreateFunnelCookie();
}
}

View file

@ -1,39 +0,0 @@
import { lazyLoadComponent } from "@/router/methods/helpers/lazy-load-component";
import { routeData } from "@/router/constants/routes";
export function createRoute(routeDatum, beforeEnter = async (to, from) => undefined) {
return {
name: routeDatum.name,
path: routeDatum.path,
component: lazyLoadComponent(routeDatum.name),
beforeEnter: async (to, from) => {
try {
return await beforeEnter(to, from);
} catch {
return {
name: routeData.BAILOUT.name,
replace: true,
};
}
},
};
}
export function createVirtualRoute(routeDatum, beforeEnter = async (to, from) => undefined) {
return {
name: routeDatum.name,
path: routeDatum.path,
beforeEnter: async (to, from) => {
try {
return await beforeEnter(to, from);
} catch (error) {
console.log(error);
return {
name: routeData.BAILOUT.name,
replace: true,
};
}
},
virtual: true,
};
}

View file

@ -1,18 +0,0 @@
import { routingTable } from "@/router/constants/routing-table";
export function getDestination(sourcePageName, navigationScenario) {
const table = routingTable();
const pageEntry = table.find((entry) => entry.pageName === sourcePageName);
const map = pageEntry?.maps?.find((map) => map.scenario === navigationScenario);
if (!map || map?.filter === false) {
return null;
}
return {
...map.destinationPageData,
params: map.params,
};
}

View file

@ -1,121 +0,0 @@
import {
setupAdvertiserTracking,
getAffiliateCookies,
} from "@/helpers/heritage-integration/cookie-helper";
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
import { storeActions } from "@/constants/store-actions";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { queryStrings } from "@/constants/query-strings";
import { externalParameterStatus } from "@/constants/external-parameters";
export async function initializeFromQueryStrings() {
// Get advertiser info
setupAdvertisersAndAffiliates();
// Read all external paramter queries and write to store.
updateExternalParameterState();
}
function setupAdvertisersAndAffiliates() {
const affiliateCookies = getAffiliateCookies();
if (affiliateCookies != null && affiliateCookies.length > 0) {
store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
}
setupAdvertiserTracking();
}
function updateExternalParameterState() {
const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR);
const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE);
const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL);
const externalParameterStyle = getQuerystringParameter(queryStrings.VEHICLE_STYLE);
const externalParameterDamage = getQuerystringParameter(queryStrings.VEHICLE_DAMAGE);
const externalParameterZipCode = getQuerystringParameter(queryStrings.SERVICE_ZIP);
const externalParameterEmail = getQuerystringParameter(queryStrings.EMAIL);
const externalParameterIsInsurance = getQuerystringParameter(queryStrings.IS_INSURANCE);
const externalParameterVinSelection = getQuerystringParameter(queryStrings.VIN_SELECTION);
const externalParameterServicePackage = getQuerystringParameter(queryStrings.SERVICE_PACKAGE);
const externalParameterNumberOfChips = getQuerystringParameter(queryStrings.NUMBER_OF_CHIPS);
const externalParameterSource = getQuerystringParameter(queryStrings.EXPERIMENTS);
const externalParameterPhoneNumber = getQuerystringParameter(queryStrings.PHONE_NUMBER);
if (
externalParameterYear &&
externalParameterMake &&
externalParameterModel &&
externalParameterStyle
) {
resetStoreForExternalParameter();
store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_STYLE, externalParameterStyle);
}
if (
externalParameterDamage &&
(externalParameterDamage.toUpperCase() != "WINDSHIELDREPAIR" ||
externalParameterNumberOfChips?.length > 0)
) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_DAMAGE_TYPE, externalParameterDamage);
if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPLACE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, false);
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS, null);
} else if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPAIR") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS,
externalParameterNumberOfChips
);
}
}
if (externalParameterZipCode) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode);
}
if (externalParameterEmail) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS,
externalParameterEmail
);
}
if (externalParameterIsInsurance?.toUpperCase() == "TRUE") {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_INSURANCE, true);
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_SERVICE_PACKAGE,
externalParameterServicePackage?.toLowerCase()
);
}
if (externalParameterDamage?.toUpperCase() != "WINDSHIELDREPAIR") {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION,
externalParameterVinSelection
);
}
if (externalParameterSource) {
store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource);
}
if (externalParameterPhoneNumber) {
store.commit(
storeMutations.UPDATE_EXTERNAL_PARAMETER_PHONE_NUMBER,
externalParameterPhoneNumber
);
}
}
// if there is an existing external parameter state then they have already been through from an external source(LeadGen) and
// are returning. clear out prior related things that need to be selected again like parts and damage type.
function resetStoreForExternalParameter() {
if (
store.getters.externalParameterState?.isExternalParameter ==
externalParameterStatus.INACTIVE
) {
store.dispatch(storeActions.RESET_VEHICLE_STATE_AND_DEPENDENCIES);
store.dispatch(storeActions.SAVE_SERVICE_ZIP_CODE_INFO, {
state: null,
zipCode: null,
zipCodeCtu: null,
});
store.dispatch(storeActions.SAVE_EMAIL, null);
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
}
}

View file

@ -1,58 +0,0 @@
import { reactive } from "vue";
const queryStash = reactive({
queries: [],
});
function stash(key, value) {
const existingValue = getStashedQuery(key);
if (existingValue) {
existingValue.value = value;
existingValue.used = false;
return;
}
queryStash.queries.push({
key: key,
value: value,
used: false,
});
}
export function stashAllQueries(toRoute) {
const keys = Object.keys(toRoute.query);
keys.forEach((k) => stash(k, toRoute.query[k]));
}
function getStashedQuery(key) {
const match = queryStash.queries.find(
(entry) => entry?.key?.toLowerCase() === key?.toLowerCase()
);
return match;
}
export function peekQueryFromStash(key) {
return getStashedQuery(key)?.value;
}
export function consumeQueryFromStash(key) {
const match = getStashedQuery(key);
if (match) {
if (!match.used) {
match.used = true;
return match.value;
}
return null;
}
return null;
}
export function clearStash() {
queryStash.queries = [];
}

View file

@ -1,8 +0,0 @@
import store from "@/store";
export function isVerifiedInsurance() {
return (
store.getters.payment?.insuranceCoverage?.isVerified ||
store.getters.order?.referralNumber?.length === 6
);
}

View file

@ -1,30 +0,0 @@
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { storeActions } from "@/constants/store-actions";
import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper";
import { experimentTriggers } from "@/constants/experiments";
import { applicationConfig } from "@/constants/application-config";
export async function runExperiments(nextPageName) {
if (!store.getters.applicationUser.triggeredSiteEntry) {
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.SITE_ENTRY,
triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE,
},
nextPageName
);
}
await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.RUN_EXPERIMENTS_FOR_TRIGGER,
{
deviceId: getDeviceIdValue(),
triggerEvent: experimentTriggers.PAGE_ENTRY,
triggerValue: nextPageName,
},
nextPageName
);
}

View file

@ -1,11 +0,0 @@
import store from "@/store";
import { storeMutations } from "@/constants/store-mutations";
export async function savePageData(page, data) {
const existingPageData = store.getters.pageData(page);
const dataToSave = Object.keys(data).length > 0 ? data : (existingPageData ?? {});
// Save data if non-null
store.commit(storeMutations.UPDATE_PAGE_DATA, { page: page, data: dataToSave });
}

View file

@ -1,10 +0,0 @@
export function navigateToExternalUrl(url, optionalQuery = {}) {
// possibly show some loading screen in the future here.
var externalUrl = new URL(url);
for (const queryKey in optionalQuery) {
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
}
window.location.assign(externalUrl);
}

View file

@ -1,84 +0,0 @@
import { saveSession } from "@/helpers/heritage-integration/order-helper";
import { buildManualUrl } from "@/router/methods/helpers/build-manual-url";
import { getDestination } from "@/router/methods/helpers/get-destination";
import { savePageData } from "@/router/methods/helpers/save-page-data";
import router from "@/router";
import store from "@/store";
import { bailout } from "@/router/methods/error";
async function navigate(scenario, currentPageName, withSaving = false, forceTopLevelNav = false) {
// Check to see if calling page is same as current page.
// If not, cancel navigation before it begins.
const callingRoute = currentPageName;
const actualRoute = router.currentRoute.value.name;
if (callingRoute !== actualRoute) {
return false;
}
const nextPage = getDestination(currentPageName, scenario);
if (!nextPage) {
console.error(
`Could not navigate from ${currentPageName} via scenario ${scenario}. Ensure routing table is configured correctly.`
);
const errorPayload = {
cause: "invalid page name",
currentPage: currentPageName,
nextPage: nextPage?.name,
};
bailout(errorPayload);
return;
}
if (withSaving) {
if (
store.getters?.applicationUser?.savedSessionId ||
store.getters?.order?.customer?.emailAddress
) {
await saveSession({ pageNameToLog: nextPage.name });
}
}
// Some pages require manually setting the next url
// to work with iframes.
if (forceTopLevelNav) {
const newUrl = buildManualUrl(nextPage);
window.top.location.href = newUrl;
return;
}
// All other pages use router.push
router.push({
name: nextPage.name,
query: nextPage.params ?? {},
});
}
//// -- Aliases: what's actually called
export async function navigateWithoutSaving(scenario, currentPageName) {
return await navigate(scenario, currentPageName, false);
}
export async function navigateWithSaving(scenario, currentPageName) {
return await navigate(scenario, currentPageName, true);
}
export async function navigateWithPageData(scenario, currentPageName, pageData = {}) {
const nextPage = getDestination(currentPageName, scenario);
await savePageData(nextPage.name, pageData);
return await navigate(scenario, currentPageName, true);
}
export async function navigateAndForceTopLevelNavigation(
scenario,
currentPageName,
saving = false
) {
return await navigate(scenario, currentPageName, saving, true);
}

View file

@ -1,22 +0,0 @@
import { getRoute } from "@/router/methods/get-route";
export async function checkPagePrerequisites(pageName) {
const route = getRoute(pageName);
if (!route) {
return false;
}
let component = route.components;
// Virtual routes have no component, so skip check.
if (!component) {
return true;
}
if (component?.default?.methods === undefined) {
component = await component?.default();
}
return component?.default?.methods?.arePagePrerequisitesValid();
}

View file

@ -1,23 +0,0 @@
import { autoRouteTable } from "@/router/constants/auto-route-table";
import { FUNNEL_START_PAGE } from "@/router/constants/routes";
import { checkPagePrerequisites } from "@/router/methods/page-prerequisites";
export async function autoRouteBeforeEnter(to, from) {
for (let i = 0; i < autoRouteTable.length; i++) {
const testRouteData = autoRouteTable[i];
const isReady = await checkPagePrerequisites(testRouteData.name);
if (isReady) {
return {
name: testRouteData.name,
replace: true,
};
}
}
return {
name: FUNNEL_START_PAGE,
replace: true,
};
}

View file

@ -1,52 +0,0 @@
import { globalEvents, globalEventTypes } from "@/constants/events";
import { storeActions } from "@/constants/store-actions";
import eventBus from "@/helpers/event-bus/event-bus";
import baseMixin from "@/mixins/base-mixin";
import router from "@/router";
import { routeData, FUNNEL_START_PAGE } from "@/router/constants/routes";
import store from "@/store";
export async function errorBeforeEnter(to, from) {
// If we've already encountered one error, clear session to avoid more.
// Otherwise mark that we encoutnered an error here.
if (store.getters.applicationUser.hasAlreadyTriggeredError) {
return {
name: routeData.RESTART.name,
replace: true,
};
} else {
await store.dispatch(storeActions.UPDATE_HAS_TRIGGERED_ERROR, true);
}
// Add error event to bus
eventBus.addEventToBus(
globalEvents.Categories.GLOBAL_ALERT,
globalEvents.SubCategories.UNKNOWN_ERROR,
{
isDismissable: true,
messageCopy: "",
messageHeadline: "We're sorry, something went wrong.",
type: globalEventTypes.Danger,
}
);
let nextPage = FUNNEL_START_PAGE.name;
baseMixin.methods?.ResetExternalParamsAndHideModal();
if (store.getters.payment?.insuranceCoverage?.isVerified) {
nextPage = routeData.VEHICLE_DAMAGE.name;
}
if (from.name === nextPage) {
// Router won't load the page if we redirect to the already existing page
// Force refresh in this scenario.
router.go(0);
return false;
}
return {
name: nextPage,
replace: false,
};
}

View file

@ -1,5 +0,0 @@
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
export async function heritageBeforeEnter(to, from) {
await navigateToHeritageFunnel({ shouldSaveSession: false, pageNameToLog: to.name });
}

View file

@ -1,11 +0,0 @@
import { routeData } from "@/router/constants/routes";
import { isVerifiedInsurance } from "@/router/methods/helpers/requires-verified-redirect";
export async function insuranceCompanyBeforeEnter(to, from) {
if (isVerifiedInsurance()) {
return {
name: routeData.HERITAGE.name,
replace: true,
};
}
}

View file

@ -1,38 +0,0 @@
import router from "@/router";
import { routeData } from "@/router/constants/routes";
import { consumeReferralQuerystrings } from "@/router/methods/helpers/consume-referral-info";
import { initializeFromQueryStrings } from "@/router/methods/helpers/initialize-from-querystrings";
import { stashAllQueries } from "@/router/methods/helpers/querystring-stash";
import store from "@/store";
export async function landingBeforeEnter(to, from) {
await initializeFromQueryStrings();
// Save querystrings to temporary stash so they can be referred to later.
stashAllQueries(to);
// Change referral info. For use in local testing for insurance crossover.
await consumeReferralQuerystrings();
// Check for fmgpage parameter
const fmgPage = to?.query?.fmgPage;
if (fmgPage && router.hasRoute(fmgPage)) {
return {
name: fmgPage,
replace: true,
};
}
// If a session is still in memory, go to return-user.
if (store.getters.vehicle?.year > 0) {
console.log(`trying to redirect!`);
return {
name: routeData.RETURN_USER.name,
replace: true,
};
}
// Otherwise, load session and auto-route
return {
name: routeData.LOAD_SESSION.name,
replace: true,
};
}

View file

@ -1,11 +0,0 @@
import { loadSessionIfPresent } from "@/helpers/heritage-integration/order-helper";
import { routeData } from "@/router/constants/routes";
export async function loadSessionBeforeEnter(to, from) {
const loadSessionResponse = await loadSessionIfPresent(false, to.name);
return {
name: routeData.AUTO_ROUTE.name,
replace: true,
};
}

View file

@ -1,20 +0,0 @@
import { queryStrings } from "@/constants/query-strings";
import { storeMutations } from "@/constants/store-mutations";
import { routeData } from "@/router/constants/routes";
import { isVerifiedInsurance } from "@/router/methods/helpers/requires-verified-redirect";
import store from "@/store";
export async function quoteBeforeEnter(to, from) {
if (isVerifiedInsurance()) {
return {
name: routeData.HERITAGE.name,
replace: true,
};
}
const offerQuote = to.query?.[queryStrings.OFFER_QUOTE];
if (offerQuote === "true") {
store.commit(storeMutations.UPDATE_IS_INSURANCE, false);
}
}

View file

@ -1,22 +0,0 @@
import { storeActions } from "@/constants/store-actions";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import router from "@/router";
import { FUNNEL_START_PAGE } from "@/router/constants/routes";
import store from "@/store";
export async function restartBeforeEnter(to, from) {
await store.dispatch(storeActions.RESET_STATE);
deleteFunnelCookie();
if (from.name === FUNNEL_START_PAGE.name) {
// Router won't load the page if we redirect to the already existing page
// Force refresh in this scenario.
router.go(0);
return false;
}
return {
name: FUNNEL_START_PAGE.name,
replace: true,
};
}

View file

@ -1,21 +0,0 @@
import { storeMutations } from "@/constants/store-mutations";
import { getBoolFromString } from "@/helpers/boolean-helper";
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
import { routeData } from "@/router/constants/routes";
import { isVerifiedInsurance } from "@/router/methods/helpers/requires-verified-redirect";
import store from "@/store";
export async function vehicleBeforeEnter(to, from) {
// If cookie indicates that vehicle has changed during insurance flow, reset parts info.
const hasVehicleChanged = getBoolFromString(getFunnelCookie()?.HasDelayedClaimRegistration);
if (hasVehicleChanged) {
store.commit(storeMutations.RESET_GLASS_PARTS_STATE);
}
if (isVerifiedInsurance()) {
return {
name: routeData.VEHICLE_DAMAGE.name,
replace: true,
};
}
}

View file

@ -1,46 +0,0 @@
import { createRoute, createVirtualRoute } from "@/router/methods/helpers/create-route";
import { routeData } from "@/router/constants/routes";
import { vehicleBeforeEnter } from "@/router/methods/route-logic/vehicle";
import { quoteBeforeEnter } from "@/router/methods/route-logic/quote";
import { insuranceCompanyBeforeEnter } from "@/router/methods/route-logic/insurance-company";
import { landingBeforeEnter } from "@/router/methods/route-logic/landing";
import { heritageBeforeEnter } from "@/router/methods/route-logic/heritage";
import { loadSessionBeforeEnter } from "@/router/methods/route-logic/load-session";
import { autoRouteBeforeEnter } from "@/router/methods/route-logic/auto-route";
import { errorBeforeEnter } from "@/router/methods/route-logic/error";
import { restartBeforeEnter } from "@/router/methods/route-logic/restart";
export const routes = [
// Non-virtual pages.
createRoute(routeData.VEHICLE, vehicleBeforeEnter),
createRoute(routeData.VEHICLE_DAMAGE),
createRoute(routeData.ESTIMATE),
createRoute(routeData.ADDRESS_LOOKUP),
createRoute(routeData.VIN_LOOKUP),
createRoute(routeData.LICENSE_PLATE_LOOKUP),
createRoute(routeData.SERVICE_ZIP),
createRoute(routeData.ADDRESS_VEHICLES),
createRoute(routeData.VEHICLE_PARTS),
createRoute(routeData.PART_QUESTIONS),
createRoute(routeData.MOLDING_QUESTIONS),
createRoute(routeData.CAPABILITY_QUESTIONS),
createRoute(routeData.QUOTE, quoteBeforeEnter),
createRoute(routeData.INSURANCE_COMPANY, insuranceCompanyBeforeEnter),
createRoute(routeData.SERVICE_LOCATION),
createRoute(routeData.SCHEDULE),
createRoute(routeData.CUSTOMER_DETAILS),
createRoute(routeData.PAYMENT_METHOD),
createRoute(routeData.PAYMENT),
createRoute(routeData.PAYMENT_PIA_RETURN),
createRoute(routeData.CONFIRMATION),
createRoute(routeData.RETURN_USER),
// Virtual pages (resolve to a non-virtual page.)
createVirtualRoute(routeData.LANDING, landingBeforeEnter),
createVirtualRoute(routeData.HERITAGE, heritageBeforeEnter),
createVirtualRoute(routeData.LOAD_SESSION, loadSessionBeforeEnter),
createVirtualRoute(routeData.AUTO_ROUTE, autoRouteBeforeEnter),
createVirtualRoute(routeData.ERROR, errorBeforeEnter),
createVirtualRoute(routeData.RESTART, restartBeforeEnter),
];

View file

@ -1,11 +0,0 @@
import analyticsMixin from "@/mixins/analytics-mixin";
import router from "@/router";
import { routeData } from "@/router/constants/routes";
export function sendToReturnUser() {
analyticsMixin.methods.initSession();
router.push({
name: routeData.RETURN_USER.name,
});
}

View file

@ -0,0 +1,32 @@
const fmgPageValues = {
VEHICLE: "vehicle",
VEHICLE_DAMAGE: "vehicle-damage",
ADDRESS_LOOKUP: "address-lookup",
VIN_LOOKUP: "vin-lookup",
VEHICLE_PARTS: "vehicle-parts",
PART_QUESTIONS: "part-questions",
MOLDING_QUESTIONS: "molding-questions",
CAPABILITY_QUESTIONS: "capability-questions",
LICENSE_PLATE_LOOKUP: "license-plate-lookup",
ESTIMATE: "estimate",
SERVICE_ZIP: "service-zip",
ADDRESS_VEHICLES: "address-vehicles",
QUOTE: "quote",
INSURANCE_COMPANY: "insurance-company",
INSURANCE_DETAILS: "insurance-details",
SERVICE_LOCATION: "service-location",
HERITAGE: "heritage",
SCHEDULE: "schedule",
CUSTOMER_DETAILS: "customer-details",
PAYMENT_METHOD: "payment-method",
PAYMENT: "payment",
PAYMENT_PIA_RETURN: "payment-pia-return",
CONFIRMATION: "confirmation",
RETURN_USER: "return-user",
EMAIL_SMS_PAGES: "email-or-sms-related-pages",
};
const funnelStartPageName = fmgPageValues.VEHICLE;
const returnUserPageName = fmgPageValues.RETURN_USER;
export { fmgPageValues, funnelStartPageName, returnUserPageName };

View file

@ -13,7 +13,6 @@ const navigationScenarios = {
CLICKED_FORWARD_WITH_CASH: "CLICKED_FORWARD_WITH_CASH",
CLICKED_FORWARD_WITH_INSURANCE: "CLICKED_FORWARD_WITH_INSURANCE",
// TODO: use virtual page?
// Vin selection
CLICKED_BACK_WITH_VIN: "CLICKED_BACK_WITH_VIN",
CLICKED_BACK_WITH_SKIP_VIN: "CLICKED_BACK_WITH_SKIP_VIN",
@ -46,24 +45,15 @@ const navigationScenarios = {
CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS: "CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS",
CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS: "CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS",
// Insurance-Company
CLICKED_PAY_ON_MY_OWN: "CLICKED_PAY_ON_MY_OWN",
// Schedule
CLICKED_CHANGE_LOCATION: "CLICKED_CHANGE_LOCATION",
// Payment
CLICKED_INSURANCE: "CLICKED_INSURANCE",
CLICKED_PAY_NOW: "CLICKED_PAY_NOW",
CLICKED_PAY_LATER: "CLICKED_PAY_LATER",
PIA_ERROR: "PIA_ERROR",
PIA_CC_ERROR: "PIA_CC_ERROR",
PIA_APPLE_ERROR: "PIA_APPLE_ERROR",
PIA_AFTERPAY_ERROR: "PIA_AFTERPAY_ERROR",
PIA_SUCCESS: "PIA_SUCCESS",
// Return User
CLICKED_RESTART: "CLICKED_RESTART",
};
export { navigationScenarios };

View file

@ -0,0 +1,6 @@
const routerParams = {
DISPLAY_VEHICLE_CHANGE_ALERT: "displayVehicleChangeAlert",
DISPLAY_PIA_ALERT: "displayPiaAlert",
};
export { routerParams };

View file

@ -1,592 +1,542 @@
import { routeData } from "@/router/constants/routes";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import store from "@/store";
import { paymentMethods } from "@/constants/payment-method-constants";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
// Get as function to live-evaluate filters
const routingTable = function () {
// Get store from router/index.js instead of importing it here to get updated values
const routingTable = function (store) {
return [
{
pageName: routeData.VEHICLE.name,
fmgPageValue: fmgPageValues.VEHICLE,
maps: [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
],
},
{
pageName: routeData.VEHICLE_DAMAGE.name,
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.VEHICLE,
destinationFmgPageValue: fmgPageValues.VEHICLE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_VIN,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SKIP_VIN,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario:
navigationScenarios.CLICKED_FORWARD_WITH_REPAIR_AND_VERIFIED_INSURANCE,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario:
navigationScenarios.CLICKED_FORWARD_WITH_REPLACE_AND_VERIFIED_INSURANCE,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
],
},
{
pageName: routeData.VIN_LOOKUP.name,
fmgPageValue: fmgPageValues.VIN_LOOKUP,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,
destinationPageData: routeData.VEHICLE_DAMAGE,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
],
},
{
pageName: routeData.LICENSE_PLATE_LOOKUP.name,
fmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
],
},
{
pageName: routeData.ADDRESS_LOOKUP.name,
fmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
destinationPageData: routeData.ADDRESS_VEHICLES,
destinationFmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
},
{
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
],
},
{
pageName: routeData.ADDRESS_VEHICLES.name,
fmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ADDRESS_LOOKUP,
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.VEHICLE_DAMAGE,
params: {
displayVehicleChangeAlert: true,
},
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_VIN_RETRY,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
],
},
{
pageName: routeData.ESTIMATE.name,
fmgPageValue: fmgPageValues.ESTIMATE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.VEHICLE_DAMAGE,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.SELECTED_MANUAL_VIN,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_LICENSE_PLATE,
destinationPageData: routeData.LICENSE_PLATE_LOOKUP,
destinationFmgPageValue: fmgPageValues.LICENSE_PLATE_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_HOME_ADDRESS,
destinationPageData: routeData.ADDRESS_LOOKUP,
destinationFmgPageValue: fmgPageValues.ADDRESS_LOOKUP,
},
{
scenario: navigationScenarios.SELECTED_NO_VIN,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
],
},
{
pageName: routeData.SERVICE_ZIP.name,
fmgPageValue: fmgPageValues.SERVICE_ZIP,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.ESTIMATE,
destinationFmgPageValue: fmgPageValues.ESTIMATE,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_SKIP_VIN,
destinationPageData: routeData.VEHICLE_DAMAGE,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
],
},
{
pageName: routeData.PART_QUESTIONS.name,
fmgPageValue: fmgPageValues.PART_QUESTIONS,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
],
},
{
pageName: routeData.VEHICLE_PARTS.name,
fmgPageValue: fmgPageValues.VEHICLE_PARTS,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
],
},
{
pageName: routeData.MOLDING_QUESTIONS.name,
fmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
],
},
{
pageName: routeData.CAPABILITY_QUESTIONS.name,
fmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
],
},
{
pageName: routeData.QUOTE.name,
fmgPageValue: fmgPageValues.QUOTE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
destinationPageData: routeData.VIN_LOOKUP,
destinationFmgPageValue: fmgPageValues.VIN_LOOKUP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
destinationPageData: routeData.SERVICE_ZIP,
destinationFmgPageValue: fmgPageValues.SERVICE_ZIP,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
destinationPageData: routeData.PART_QUESTIONS,
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
destinationPageData: routeData.VEHICLE_PARTS,
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
destinationPageData: routeData.MOLDING_QUESTIONS,
destinationFmgPageValue: fmgPageValues.MOLDING_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
destinationPageData: routeData.CAPABILITY_QUESTIONS,
destinationFmgPageValue: fmgPageValues.CAPABILITY_QUESTIONS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CASH,
destinationPageData: routeData.SERVICE_LOCATION,
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
},
{
scenario: navigationScenarios.CLICKED_FORWARD_WITH_INSURANCE,
destinationPageData: routeData.INSURANCE_COMPANY,
destinationFmgPageValue: fmgPageValues.INSURANCE_COMPANY,
},
],
},
{
pageName: routeData.INSURANCE_COMPANY.name,
fmgPageValue: fmgPageValues.INSURANCE_COMPANY,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_PAY_ON_MY_OWN,
destinationPageData: routeData.QUOTE,
params: {
offer: "cash",
},
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.INSURANCE_DETAILS,
destinationFmgPageValue: fmgPageValues.INSURANCE_DETAILS,
},
],
},
{
pageName: routeData.SERVICE_LOCATION.name,
fmgPageValue: fmgPageValues.SERVICE_LOCATION,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.QUOTE,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.SCHEDULE,
destinationFmgPageValue: fmgPageValues.SCHEDULE,
},
],
},
{
pageName: routeData.SCHEDULE.name,
fmgPageValue: fmgPageValues.SCHEDULE,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.SERVICE_LOCATION,
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CUSTOMER_DETAILS,
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
},
{
scenario: navigationScenarios.CLICKED_CHANGE_LOCATION,
destinationPageData: routeData.SERVICE_LOCATION,
destinationFmgPageValue: fmgPageValues.SERVICE_LOCATION,
},
],
},
{
pageName: routeData.CUSTOMER_DETAILS.name,
fmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.SCHEDULE,
destinationFmgPageValue: fmgPageValues.SCHEDULE,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.PAYMENT_METHOD,
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
},
{
scenario: navigationScenarios.CLICKED_PAY_NOW,
destinationPageData: routeData.PAYMENT_METHOD,
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
},
],
},
{
pageName: routeData.PAYMENT_METHOD.name,
fmgPageValue: fmgPageValues.PAYMENT_METHOD,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.CUSTOMER_DETAILS,
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CONFIRMATION,
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
},
{
scenario: navigationScenarios.CLICKED_PAY_NOW,
destinationPageData: routeData.PAYMENT,
destinationFmgPageValue: fmgPageValues.PAYMENT,
},
{
scenario: navigationScenarios.CLICKED_INSURANCE,
destinationPageData: routeData.INSURANCE_COMPANY,
destinationFmgPageValue: fmgPageValues.INSURANCE_COMPANY,
},
],
},
{
pageName: routeData.PAYMENT.name,
fmgPageValue: fmgPageValues.PAYMENT,
maps: [
{
scenario: navigationScenarios.CLICKED_BACK,
destinationPageData: routeData.PAYMENT_METHOD,
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
},
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.CONFIRMATION,
},
{
scenario: navigationScenarios.PIA_ERROR,
destinationPageData: routeData.PAYMENT_METHOD,
params: {
piaError: "true",
},
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
},
],
},
{
pageName: routeData.PAYMENT_PIA_RETURN.name,
fmgPageValue: fmgPageValues.PAYMENT_PIA_RETURN,
maps: [
{
scenario: navigationScenarios.PIA_ERROR,
destinationPageData: routeData.PAYMENT_METHOD,
params: {
piaError: "true",
},
destinationFmgPageValue: fmgPageValues.PAYMENT_METHOD,
},
{
scenario: navigationScenarios.PIA_CC_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.CREDIT_CARD,
},
},
{
scenario: navigationScenarios.PIA_APPLE_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.APPLE_PAY,
},
},
{
scenario: navigationScenarios.PIA_AFTERPAY_ERROR,
destinationPageData: routeData.PAYMENT,
params: {
piaErrorType: paymentMethods.AFTERPAY,
},
destinationFmgPageValue: fmgPageValues.PAYMENT,
},
{
scenario: navigationScenarios.PIA_SUCCESS,
destinationPageData: routeData.CONFIRMATION,
destinationFmgPageValue: fmgPageValues.CONFIRMATION,
},
],
},
{
pageName: routeData.CONFIRMATION.name,
fmgPageValue: fmgPageValues.CONFIRMATION,
},
// The destination page for return user does not matter. the router will invoke implicit navigation
{
pageName: routeData.RETURN_USER.name,
fmgPageValue: fmgPageValues.RETURN_USER,
maps: [
{
scenario: navigationScenarios.CLICKED_FORWARD,
destinationPageData: routeData.LOAD_SESSION,
},
{
scenario: navigationScenarios.CLICKED_RESTART,
destinationPageData: routeData.RESTART,
destinationFmgPageValue: fmgPageValues.VEHICLE,
},
],
},

View file

@ -10,7 +10,7 @@ import { applicationConfig } from "@/constants/application-config";
import { experimentTriggers } from "@/constants/experiments";
import { damageLocationsSelected } from "@/constants/damage-locations-selected";
import { singleWindshieldCarIds } from "@/constants/single-windshield-carids";
import { routeData } from "@/router/constants/routes";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
import { deepEqual } from "@/helpers/object-helper";
import baseMixin from "@/mixins/base-mixin.js";
@ -199,7 +199,6 @@ const getDefaultState = () => {
triggeredSiteEntry: false,
affiliateCookies: [],
loggingOption: false,
hasAlreadyTriggeredError: false,
},
};
};
@ -599,10 +598,10 @@ export const mutations = {
state.order.damage.partQuestionAnswers = null;
state.order.damage.moldingQuestionAnswers = null;
state.order.damage.capabilityQuestionAnswers = null;
state.applicationUser.pageData[routeData.PART_QUESTIONS.name] = null;
state.applicationUser.pageData[routeData.VEHICLE_PARTS.name] = null;
state.applicationUser.pageData[routeData.MOLDING_QUESTIONS.name] = null;
state.applicationUser.pageData[routeData.CAPABILITY_QUESTIONS.name] = null;
state.applicationUser.pageData[fmgPageValues.PART_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.VEHICLE_PARTS] = null;
state.applicationUser.pageData[fmgPageValues.MOLDING_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.CAPABILITY_QUESTIONS] = null;
},
resetSchedule(state) {
state.order.schedule.date = null;
@ -666,10 +665,10 @@ export const mutations = {
state.order.isRecalAckOptIn = sessionInformation.order.isRecalAckOptIn;
if (state.order.vehicle.vin !== sessionInformation.order.vehicle?.vin) {
state.applicationUser.pageData[routeData.PART_QUESTIONS.name] = null;
state.applicationUser.pageData[routeData.VEHICLE_PARTS.name] = null;
state.applicationUser.pageData[routeData.MOLDING_QUESTIONS.name] = null;
state.applicationUser.pageData[routeData.CAPABILITY_QUESTIONS.name] = null;
state.applicationUser.pageData[fmgPageValues.PART_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.VEHICLE_PARTS] = null;
state.applicationUser.pageData[fmgPageValues.MOLDING_QUESTIONS] = null;
state.applicationUser.pageData[fmgPageValues.CAPABILITY_QUESTIONS] = null;
}
state.order.vehicle = Object.assign(state.order.vehicle, {
@ -825,9 +824,6 @@ export const mutations = {
updateAffiliateCookies(state, affiliateCookies) {
state.applicationUser.affiliateCookies = affiliateCookies;
},
updateHasTriggeredError(state, hasTriggeredError) {
state.applicationUser.hasAlreadyTriggeredError = hasTriggeredError;
},
};
// Export Getters
@ -1065,7 +1061,7 @@ export const getters = {
// if we're here, then we have both email and phone so get the value from pageData to reflect what they entered on the page.
// if they didn't enter anything on the page default to email
return (
state.applicationUser.pageData[routeData.SERVICE_ZIP.name]?.emailOrSmsValue ??
state.applicationUser.pageData[fmgPageValues.EMAIL_SMS_PAGES]?.emailOrSmsValue ??
state.order.customer.emailAddress
);
},
@ -1989,7 +1985,7 @@ export const actions = {
getPartFromCapabilityQuestionAnswer(context, { payload, pageNameToLog }) {
const glassLocation = payload;
const pageData = context.getters.pageData(routeData.CAPABILITY_QUESTIONS.name);
const pageData = context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS);
const part = pageData.partsOrQuestions.find((x) => x.glassLocation === glassLocation)
.parts[0];
@ -2627,15 +2623,15 @@ export const actions = {
context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.VEHICLE_PARTS.name,
page: fmgPageValues.VEHICLE_PARTS,
data: null,
});
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.MOLDING_QUESTIONS.name,
page: fmgPageValues.MOLDING_QUESTIONS,
data: null,
});
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.CAPABILITY_QUESTIONS.name,
page: fmgPageValues.CAPABILITY_QUESTIONS,
data: null,
});
}
@ -2646,8 +2642,8 @@ export const actions = {
resetMoldingAndCapabilityQuestionAnswersIfNeeded(context, matchedParts) {
const partsOrQuestionsDataToCompareWith =
context.getters.pageData(routeData.MOLDING_QUESTIONS.name)?.partsOrQuestions ??
context.getters.pageData(routeData.CAPABILITY_QUESTIONS.name)?.partsOrQuestions ??
context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS)?.partsOrQuestions ??
context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)?.partsOrQuestions ??
[];
function getAllPartNumbers(partsOrQuestions) {
@ -2676,11 +2672,11 @@ export const actions = {
context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.MOLDING_QUESTIONS.name,
page: fmgPageValues.MOLDING_QUESTIONS,
data: null,
});
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.CAPABILITY_QUESTIONS.name,
page: fmgPageValues.CAPABILITY_QUESTIONS,
data: null,
});
}
@ -2708,7 +2704,7 @@ export const actions = {
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_PAGE_DATA, {
page: routeData.CAPABILITY_QUESTIONS.name,
page: fmgPageValues.CAPABILITY_QUESTIONS,
data: null,
});
}
@ -3432,10 +3428,6 @@ export const actions = {
}
}
},
updateHasTriggeredError(context, hasAlreadyTriggeredError) {
context.commit(storeMutations.UPDATE_HAS_TRIGGERED_ERROR, hasAlreadyTriggeredError);
},
};
export default createStore({

Some files were not shown because too many files have changed in this diff Show more