diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js
index 5fe09edb2..39b1108f2 100644
--- a/src/layouts/vin-lookup/vin-lookup.spec.js
+++ b/src/layouts/vin-lookup/vin-lookup.spec.js
@@ -11,8 +11,9 @@ jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
+ bailoutCode: null,
applicationUser: {
- bailoutCode: null,
+ pageData: {},
},
externalParameterState: {
isExternalParameter: false,
diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue
index 5d89c40c7..35e2a626e 100644
--- a/src/layouts/vin-lookup/vin-lookup.vue
+++ b/src/layouts/vin-lookup/vin-lookup.vue
@@ -525,7 +525,7 @@ export default {
},
getRequiredVinNotFound() {
// Prevents success alert from showing
- var bailoutCode = this.$store.getters.applicationUser.bailoutCode;
+ var bailoutCode = this.$store.getters.bailoutCode;
var vinRequired = this.$store.getters.vehicle.vinRequired;
if (vinRequired && this.vin && bailoutCode == bailoutCodes.PART_NOT_FOUND) {
return true;
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index 7ff1fcd51..58c8e3399 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -34,6 +34,7 @@ import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { containsRecalParts, getRecalPartNumbers } from "@/helpers/recal-helper";
import { getAmountDue, getSubTotal, getSalesTax } from "@/helpers/pricing-helper.js";
import { partTypeStrings } from "@/constants/part-type-strings";
+import { bailoutCodes } from "@/constants/bailout-codes";
import router from "@/router";
export default {
@@ -271,6 +272,9 @@ export default {
sessionData.totalPrice = getAmountDue(order?.lineItems, true);
sessionData.userAgent = navigator.userAgent;
sessionData.cashPriceSubTotal = order?.cashPriceSubTotal;
+ sessionData.bailoutCode = this.getBailoutCodeEnum(
+ applicationUser?.pageData?.bailout?.bailoutCode
+ );
await baseMixin.methods.dispatchStoreAction(
storeActions.LOG_FMG_SESSION_DATA,
@@ -279,6 +283,17 @@ export default {
);
},
+ getBailoutCodeEnum(bailoutCode) {
+ if (bailoutCode) {
+ const bailoutCodeEnum = Object.keys(bailoutCodes).find(
+ (key) => bailoutCodes[key] === bailoutCode
+ );
+ return bailoutCodeEnum ? bailoutCode + "_" + bailoutCodeEnum : bailoutCode;
+ } else {
+ return null;
+ }
+ },
+
pushOrderToDataLayer() {
// helper check for if an object is defined (but maybe falsey)
const isDefined = (x) => x !== null && x !== undefined;
@@ -622,7 +637,7 @@ export default {
}
discount += productPrice * -1;
- subTotal += isQuotePageDiscount ? productPrice : 0;
+ subTotal += productPrice;
} else {
products.push({
productType: productType,
@@ -722,6 +737,9 @@ export default {
if (quotePageDiscount) {
combinedLineItems = combinedLineItems.concat(quotePageDiscount);
}
+ if (lineItems.promos) {
+ combinedLineItems = combinedLineItems.concat(lineItems.promos);
+ }
//Remove child Parts if any
combinedLineItems.forEach((lineItem) => {
diff --git a/src/mixins/analytics-mixin.spec.js b/src/mixins/analytics-mixin.spec.js
index ee7c39e3c..4699a3449 100644
--- a/src/mixins/analytics-mixin.spec.js
+++ b/src/mixins/analytics-mixin.spec.js
@@ -22,6 +22,7 @@ import {
getUserIdValue,
} from "@/helpers/heritage-integration/cookie-helper";
import baseMixin from "./base-mixin";
+import { bailoutCodes } from "@/constants/bailout-codes";
const parts = {
windshield: {
@@ -746,6 +747,71 @@ describe("analyticsMixin.js", () => {
//Assert
expect(gaLabels).toEqual(GaLabels);
});
+
+ describe("getBailoutCodeEnum", () => {
+ test("returns null when bailout code is not provided", () => {
+ expect(analyticsMixin.methods.getBailoutCodeEnum(null)).toBeNull();
+ expect(analyticsMixin.methods.getBailoutCodeEnum(undefined)).toBeNull();
+ });
+
+ test("returns formatted value when bailout code matches a known enum", () => {
+ const result = analyticsMixin.methods.getBailoutCodeEnum(bailoutCodes.PART_NOT_FOUND);
+
+ expect(result).toBe(`${bailoutCodes.PART_NOT_FOUND}_PART_NOT_FOUND`);
+ });
+
+ test("returns original value when bailout code does not match a known enum", () => {
+ expect(analyticsMixin.methods.getBailoutCodeEnum(999)).toBe(999);
+ });
+ });
+
+ describe("pushFmgSessionData", () => {
+ beforeEach(() => {
+ baseMixin.methods.hasSubmittedOrder = jest.fn().mockReturnValue(false);
+ baseMixin.methods.getSubmittedOrder = jest.fn();
+ baseMixin.methods.hasSubmittedApplicationUser = jest.fn().mockReturnValue(false);
+ baseMixin.methods.getSubmittedApplicationUser = jest.fn();
+ store.getters.order = {
+ vehicle: { vinRequired: false },
+ payment: {
+ isInsurance: false,
+ isClaimAndCoverage: false,
+ isPia: false,
+ },
+ damage: { isRepair: false },
+ lineItems: {},
+ serviceLocation: {},
+ customer: {},
+ policy: {},
+ };
+ store.getters.applicationUser = {
+ experiments: [],
+ pageData: {
+ bailout: {
+ bailoutCode: bailoutCodes.PART_NOT_FOUND,
+ },
+ },
+ };
+ });
+
+ test("dispatches session data with formatted bailout code", async () => {
+ const mocks = setupMocksForJsFiles({
+ actionList: [{ actionName: storeActions.LOG_FMG_SESSION_DATA }],
+ });
+
+ await analyticsMixin.methods.pushFmgSessionData();
+
+ expect(mocks.baseMixin.methods.dispatchStoreAction).toHaveBeenCalledWith(
+ storeActions.LOG_FMG_SESSION_DATA,
+ expect.objectContaining({
+ currentPage: "mockedPageName",
+ bailoutCode: `${bailoutCodes.PART_NOT_FOUND}_PART_NOT_FOUND`,
+ }),
+ false
+ );
+ });
+ });
+
describe("initSession", () => {
test("Generates random values for userId and deviceId if not present", async () => {
// Arrange
diff --git a/src/mixins/bailout-mixin.js b/src/mixins/bailout-mixin.js
index f8c724da2..2640f670c 100644
--- a/src/mixins/bailout-mixin.js
+++ b/src/mixins/bailout-mixin.js
@@ -1,12 +1,17 @@
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
+import { routeData } from "@/router/constants/routes";
+import { savePageData } from "@/router/methods/helpers/save-page-data";
export default {
methods: {
navigateToBailoutPage(vm, bailoutCode) {
const self = vm ?? this;
- self.dispatchStoreAction(self.storeActions.SAVE_BAILOUT_CODE, bailoutCode).then(() => {
- self.$router.navigateWithoutSaving(navigationScenarios.BAILOUT, self.pageName);
+ return savePageData(routeData.BAILOUT.name, { bailoutCode }).then(() => {
+ return self.$router.navigateWithoutSaving(
+ navigationScenarios.BAILOUT,
+ self.pageName
+ );
});
},
},
diff --git a/src/mixins/bailout-mixin.spec.js b/src/mixins/bailout-mixin.spec.js
index 9571c6f26..4b7dfee0f 100644
--- a/src/mixins/bailout-mixin.spec.js
+++ b/src/mixins/bailout-mixin.spec.js
@@ -1,33 +1,34 @@
import bailoutMixin from "@/mixins/bailout-mixin";
-import { storeActions } from "@/constants/store-actions.js";
import { navigationScenarios } from "@/router/constants/navigation-scenarios";
import { bailoutCodes } from "@/constants/bailout-codes.js";
+import { routeData } from "@/router/constants/routes";
+
+jest.mock("@/router/methods/helpers/save-page-data", () => ({
+ savePageData: jest.fn().mockResolvedValue(undefined),
+}));
+
+import { savePageData } from "@/router/methods/helpers/save-page-data";
describe("bailout-mixin.js", () => {
- test("navigateToBailoutPage: dispatches SAVE_BAILOUT_CODE action with bailout code", async () => {
- // Arrange
+ beforeEach(() => {
+ savePageData.mockClear();
+ });
+
+ test("navigateToBailoutPage: saves bailout code to pageData", async () => {
const mockVm = createMockVm();
const bailoutCode = bailoutCodes.PART_NOT_FOUND;
- // Act
await bailoutMixin.methods.navigateToBailoutPage(mockVm, bailoutCode);
- // Assert
- expect(mockVm.dispatchStoreAction).toHaveBeenCalledWith(
- storeActions.SAVE_BAILOUT_CODE,
- bailoutCode
- );
+ expect(savePageData).toHaveBeenCalledWith(routeData.BAILOUT.name, { bailoutCode });
});
test("navigateToBailoutPage: navigates to bailout page after saving bailout code", async () => {
- // Arrange
const mockVm = createMockVm();
const bailoutCode = bailoutCodes.PART_NOT_FOUND;
- // Act
await bailoutMixin.methods.navigateToBailoutPage(mockVm, bailoutCode);
- // Assert
expect(mockVm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.BAILOUT,
mockVm.pageName
@@ -35,55 +36,39 @@ describe("bailout-mixin.js", () => {
});
test("navigateToBailoutPage: uses current context (this) when vm is not provided", async () => {
- // Arrange
const mockRouter = {
navigateWithoutSaving: jest.fn().mockResolvedValue(undefined),
};
const mockThis = {
- dispatchStoreAction: jest.fn().mockResolvedValue(undefined),
$router: mockRouter,
- storeActions: storeActions,
pageName: "test-page",
};
-
const bailoutCode = bailoutCodes.PART_NOT_FOUND;
- // Act
await bailoutMixin.methods.navigateToBailoutPage.call(mockThis, undefined, bailoutCode);
- // Assert
- expect(mockThis.dispatchStoreAction).toHaveBeenCalledWith(
- storeActions.SAVE_BAILOUT_CODE,
- bailoutCode
- );
+ expect(savePageData).toHaveBeenCalledWith(routeData.BAILOUT.name, { bailoutCode });
});
- test("navigateToBailoutPage: passes correct bailout code to store", async () => {
- // Arrange
+ test("navigateToBailoutPage: passes correct bailout code to pageData", async () => {
const mockVm = createMockVm();
const customBailoutCode = 999;
- // Act
await bailoutMixin.methods.navigateToBailoutPage(mockVm, customBailoutCode);
- // Assert
- expect(mockVm.dispatchStoreAction).toHaveBeenCalledWith(
- storeActions.SAVE_BAILOUT_CODE,
- customBailoutCode
- );
+ expect(savePageData).toHaveBeenCalledWith(routeData.BAILOUT.name, {
+ bailoutCode: customBailoutCode,
+ });
});
test("navigateToBailoutPage: calls navigateWithoutSaving with correct parameters", async () => {
- // Arrange
const mockVm = createMockVm();
const mockPageName = "vehicle-damage";
mockVm.pageName = mockPageName;
const bailoutCode = bailoutCodes.PART_NOT_FOUND;
- // Act
await bailoutMixin.methods.navigateToBailoutPage(mockVm, bailoutCode);
- // Assert
expect(mockVm.$router.navigateWithoutSaving).toHaveBeenCalledWith(
navigationScenarios.BAILOUT,
mockPageName
@@ -93,11 +78,9 @@ describe("bailout-mixin.js", () => {
function createMockVm() {
return {
- dispatchStoreAction: jest.fn().mockResolvedValue(undefined),
$router: {
navigateWithoutSaving: jest.fn().mockResolvedValue(undefined),
},
- storeActions,
pageName: "test-page",
};
}
diff --git a/src/mixins/vin-pages-mixin.js b/src/mixins/vin-pages-mixin.js
index 78cb134cf..c15529d4f 100644
--- a/src/mixins/vin-pages-mixin.js
+++ b/src/mixins/vin-pages-mixin.js
@@ -37,7 +37,7 @@ export default {
pageNameToLog: pageName,
});
- if (result.PartNotFound) {
+ if (result.PartNotFound || store.getters.vehicle.vinRequired) {
return bailoutMixin.methods.navigateToBailoutPage(
this,
bailoutCodes.PART_NOT_FOUND
diff --git a/src/mixins/vin-pages-mixin.spec.js b/src/mixins/vin-pages-mixin.spec.js
index d9ff6f874..46d755c3c 100644
--- a/src/mixins/vin-pages-mixin.spec.js
+++ b/src/mixins/vin-pages-mixin.spec.js
@@ -3,6 +3,10 @@ import { shallowMount } from "@vue/test-utils";
import { setupMocksForJsFiles, getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeActions } from "@/constants/store-actions";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
+import bailoutMixin from "@/mixins/bailout-mixin";
+import { bailoutCodes } from "@/constants/bailout-codes";
+import store from "@/store";
+import { storeMutations } from "@/constants/store-mutations";
jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
navigateForward: jest.fn(),
@@ -15,6 +19,7 @@ jest.mock("@/helpers/heritage-integration/order-helper.js", () => ({
describe("vin-pages-mixin", () => {
afterEach(() => {
jest.clearAllMocks();
+ store.commit(storeMutations.UPDATE_VIN_REQUIRED, false);
});
describe("navigateForwardWithSingleCarMatch", () => {
@@ -29,6 +34,24 @@ describe("vin-pages-mixin", () => {
// Assert
expect(vehicleQuestionsMixin.methods.navigateForward).toHaveBeenCalled();
});
+
+ test("vinRequired vehicles navigate to bailout after VIN is saved", async () => {
+ // Arrange
+ store.commit(storeMutations.UPDATE_VIN_REQUIRED, true);
+ const { wrapper } = setupMocks({});
+ bailoutMixin.methods.navigateToBailoutPage = jest.fn();
+ vehicleQuestionsMixin.methods.navigateForward = jest.fn();
+
+ // Act
+ await wrapper.vm.navigateForwardWithSingleCarMatch();
+
+ // Assert
+ expect(bailoutMixin.methods.navigateToBailoutPage).toHaveBeenCalledWith(
+ wrapper.vm,
+ bailoutCodes.PART_NOT_FOUND
+ );
+ expect(vehicleQuestionsMixin.methods.navigateForward).not.toHaveBeenCalled();
+ });
});
});
diff --git a/src/router/methods/before-each.js b/src/router/methods/before-each.js
index 84e653551..3e1dd540d 100644
--- a/src/router/methods/before-each.js
+++ b/src/router/methods/before-each.js
@@ -193,5 +193,5 @@ export async function beforeEach(to, from) {
function getIsBailout(submittedState) {
const submittedStateObj = JSON.parse(submittedState);
- return !!submittedStateObj?.applicationUser?.bailoutCode;
+ return !!submittedStateObj?.applicationUser?.pageData?.bailout?.bailoutCode;
}
diff --git a/src/router/methods/navigate.js b/src/router/methods/navigate.js
index 63e20d96c..288278137 100644
--- a/src/router/methods/navigate.js
+++ b/src/router/methods/navigate.js
@@ -3,6 +3,7 @@ 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 { navigationScenarios } from "@/router/constants/navigation-scenarios";
+import { routeData } from "@/router/constants/routes";
import router from "@/router";
import store from "@/store";
@@ -79,9 +80,13 @@ export async function navigateWithSaving(scenario, currentPageName) {
export async function navigateWithPageData(scenario, currentPageName, pageData = {}) {
const nextPage = getDestination(currentPageName, scenario);
- if (pageData && pageData.bailoutCode) {
- pageData.AppName = "FixMyGlass";
- await savePageData(currentPageName, pageData);
+ if (currentPageName === routeData.BAILOUT.name) {
+ const existingPageData = store.getters.pageData(routeData.BAILOUT.name) ?? {};
+ await savePageData(routeData.BAILOUT.name, {
+ ...existingPageData,
+ ...pageData,
+ AppName: "FixMyGlass",
+ });
} else {
await savePageData(nextPage.name, pageData);
}
diff --git a/src/store/index.js b/src/store/index.js
index 48ac63181..bb4f77378 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -229,7 +229,6 @@ const getDefaultState = () => {
affiliateCookies: [],
loggingOption: false,
hasAlreadyTriggeredError: false,
- bailoutCode: null,
},
idempotencyKeyFields: {
referralCorrelationId: null,
@@ -506,6 +505,9 @@ export const mutations = {
state.order.vehicle.carId = vehicleInfo.carId;
state.order.vehicle.category = vehicleInfo.category;
state.order.vehicle.vin = vehicleInfo.vin;
+ if (vehicleInfo.vinRequired !== undefined) {
+ state.order.vehicle.vinRequired = vehicleInfo.vinRequired;
+ }
state.order.vehicle.imageUrl = vehicleInfo.imageUrl;
state.order.vehicle.imageVifNumber = vehicleInfo.imageVifNumber;
@@ -1035,9 +1037,6 @@ export const mutations = {
state.idempotencyKeyFields.totalInCents = totalInCents;
state.idempotencyKeyFields.expiryTime = expiryTime;
},
- updateBailoutCode(state, bailoutCode) {
- state.applicationUser.bailoutCode = bailoutCode;
- },
};
// Export Getters
@@ -1160,6 +1159,7 @@ export const getters = {
pageData: (state) => (page) => {
return state.applicationUser.pageData[page];
},
+ bailoutCode: (state) => state.applicationUser.pageData.bailout?.bailoutCode,
applicationUser: (state) => state.applicationUser,
order: (state) => state.order,
payment: (state) => state.order.payment,
@@ -1849,6 +1849,7 @@ export const actions = {
totalPrice,
userAgent,
cashPriceSubTotal,
+ bailoutCode,
}
) {
var payload = {
@@ -1903,6 +1904,7 @@ export const actions = {
userAgent: userAgent,
cashPriceSubTotal: cashPriceSubTotal,
billToAccountNumber: billToAccountNumber,
+ bailoutCode: bailoutCode,
};
return globalMethods.callHttpClient({
@@ -2001,7 +2003,7 @@ export const actions = {
const glassArrayForPayload = convertGlassPieceNamingForApi(glassArray);
const partsOrQuestionsEndpoint = vehicle.vinRequired
- ? endpoints.GetPartsOrQuestionsV3
+ ? endpoints.GetPartsOrQuestionsV2
: endpoints.GetPartsOrQuestions;
const response = await globalMethods
@@ -3980,10 +3982,6 @@ export const actions = {
context.commit(storeMutations.UPDATE_IDEMPOTENCY_KEY, newKey);
}
},
-
- saveBailoutCode(context, bailoutCode) {
- context.commit(storeMutations.UPDATE_BAILOUT_CODE, bailoutCode);
- },
};
export default createStore({
diff --git a/src/styles/common-styles.scss b/src/styles/common-styles.scss
index ce1354f16..c619196fa 100644
--- a/src/styles/common-styles.scss
+++ b/src/styles/common-styles.scss
@@ -102,8 +102,3 @@ option,
.btn {
letter-spacing: 0.03rem;
}
-
-.page-gradient {
- height: 12px;
- background: linear-gradient(to bottom, rgba(0, 0, 0, 0.08), rgba(0, 0, 0, 0));
-}