diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index dc4da7e1b..615e5ecf6 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -546,7 +546,7 @@ export default { const affiliateCookies = store.getters.applicationUser.affiliateCookies; var cookieArray = []; affiliateCookies.forEach((item) => { - let cookieObject = convertCookieStringToObject(item); + let cookieObject = convertCookieStringToObject(item.CookieValue); cookieArray.push(cookieObject); }); const sortedCookies = cookieArray.sort( @@ -569,33 +569,34 @@ export default { coupons = promoString; } refSequenceNum = submittedOrder.referralSequenceNumber; - } - if (isDefined(submittedOrder.payment.isInsurance)) { - accountType = submittedOrder.payment.isInsurance ? "insurance" : "cash"; - } else { - accountType = ""; - } - const lineItems = submittedOrder.lineItems ?? {}; - const combinedLineItems = [ - ...(lineItems.glassParts ?? []), - ...(lineItems.supportingItems ?? []), - ...(lineItems.vaps ?? []), - ...(lineItems.promos ?? []), - ]; - const isPricingAvailable = - combinedLineItems.length > 0 && - combinedLineItems.every( - (lineItem) => - isDefined(lineItem.kitPrice) && - isDefined(lineItem.laborAmount) && - isDefined(lineItem.sellingPrice) - ); - if (accountType == "cash" && isPricingAvailable) { - const quoteAmountWithDiscount = baseMixin.methods - .getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false) - .toFixed(2); - amount = parseFloat(quoteAmountWithDiscount); + if (isDefined(submittedOrder.payment.isInsurance)) { + accountType = submittedOrder.payment.isInsurance ? "insurance" : "cash"; + } else { + accountType = ""; + } + const lineItems = submittedOrder.lineItems ?? {}; + const combinedLineItems = [ + ...(lineItems.glassParts ?? []), + ...(lineItems.supportingItems ?? []), + ...(lineItems.vaps ?? []), + ...(lineItems.promos ?? []), + ]; + + const isPricingAvailable = + combinedLineItems.length > 0 && + combinedLineItems.every( + (lineItem) => + isDefined(lineItem.kitPrice) && + isDefined(lineItem.laborAmount) && + isDefined(lineItem.sellingPrice) + ); + if (accountType == "cash" && isPricingAvailable) { + const quoteAmountWithDiscount = baseMixin.methods + .getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false) + .toFixed(2); + amount = parseFloat(quoteAmountWithDiscount); + } } } pushToDataLayerIfDefined({ diff --git a/src/mixins/analytics-mixin.spec.js b/src/mixins/analytics-mixin.spec.js index e56840c61..6266b97a1 100644 --- a/src/mixins/analytics-mixin.spec.js +++ b/src/mixins/analytics-mixin.spec.js @@ -1,4 +1,6 @@ import analyticsMixin from "@/mixins/analytics-mixin"; +import baseMixin from "@/mixins/base-mixin"; +import { shallowMount } from "@vue/test-utils"; import { setupMocksForJsFiles, setupCookies, @@ -851,4 +853,198 @@ describe("analyticsMixin.js", () => { expect(mocks.baseMixin.methods.dispatchStoreAction).toBeCalled(); }); }); + describe("push product array and ecommerce cart to data layer", () => { + let wrapper; + + beforeEach(() => { + wrapper = shallowMount(analyticsMixin); + }); + + it("should push product array to data layer correctly", () => { + // Mock the methods + baseMixin.methods.hasSubmittedOrder = jest.fn(); + baseMixin.methods.getSubmittedOrder = jest.fn(); + baseMixin.methods.getTotalPriceOfAllLineItemsAndChildParts = jest.fn(); + baseMixin.methods.hasSubmittedOrder.mockReturnValue(true); + baseMixin.methods.getSubmittedOrder.mockReturnValue({ + lineItems: { + glassParts: [{ partNumber: "GP1", partType: "glass" }], + supportingItems: [{ partNumber: "SI1", partType: "support" }], + vaps: [{ partNumber: "VAP1", partType: "vap" }], + promos: [{ partNumber: "DISCOUNT", partType: "promo", promoCode: "PROMO4" }], + }, + }); + baseMixin.methods.getTotalPriceOfAllLineItemsAndChildParts.mockReturnValue(100); + + // Call the function + wrapper.vm.pushProductArrayToDataLayer(); + + // Assertions + expect(baseMixin.methods.hasSubmittedOrder).toHaveBeenCalled(); + expect(baseMixin.methods.getSubmittedOrder).toHaveBeenCalled(); + expect(baseMixin.methods.getTotalPriceOfAllLineItemsAndChildParts).toHaveBeenCalled(); + }); + it("should push eCommerce cart to data layer correctly", () => { + // Mock the methods + (baseMixin.methods.hasSubmittedOrder = jest.fn()), + (baseMixin.methods.getSubmittedOrder = jest.fn()), + baseMixin.methods.hasSubmittedOrder.mockReturnValue(true); + baseMixin.methods.getSubmittedOrder.mockReturnValue({ + lineItems: { + supportingItems: [ + { partType: "RECALIBRATION", partNumber: "R1" }, + { partType: "DISPOSAL FEE", partNumber: "D1" }, + { partType: "MOBILE FEE", partNumber: "M1" }, + { partType: "REPAIR FEE", partNumber: "RF1" }, + ], + vaps: [{ partType: "FRONT WIPER", partNumber: "FW1" }], + }, + payment: { isInsurance: true }, + policy: { isItac: true, isNoComp: false }, + }); + + // Call the function + wrapper.vm.pushECommerceCartToDataLayer(); + + // Assertions + expect(baseMixin.methods.hasSubmittedOrder).toHaveBeenCalled(); + expect(baseMixin.methods.getSubmittedOrder).toHaveBeenCalled(); + expect(baseMixin.methods.getTotalPriceOfAllLineItemsAndChildParts).toHaveBeenCalled(); + }); + }); + + describe("pushCommissionJunctionGtmDataToDataLayer", () => { + it("should handle empty affiliateCookies", () => { + store.getters = { + applicationUser: { + affiliateCookies: [], + }, + }; + + baseMixin.methods.hasSubmittedOrder = jest.fn(); + baseMixin.methods.hasSubmittedOrder.mockReturnValue(false); + const result = analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer(); + expect(result).toBeUndefined(); + }); + + test("Pushes populated data to data layer", () => { + baseMixin.methods.hasSubmittedOrder = jest.fn(); + baseMixin.methods.hasSubmittedOrder.mockReturnValue(true); + baseMixin.methods.getSubmittedOrder = jest.fn(); + baseMixin.methods.getSubmittedOrder.mockReturnValue({ + vehicle: { + year: "2020", + make: "acura", + model: "mdx", + style: "4-door sedan", + carId: "dummyCarId", + category: "dummyCategory", + vin: "dummyVin", + }, + serviceLocation: { + address: "add1", + address2: "add2", + city: "city", + state: "state", + zipCode: "11111", + zipCodeCtu: "11110", + appointmentType: "IN_SHOP", + isVehicleProtected: true, + provider: { + providerNumber: 2, + address: { + streetAddress: "add3", + city: "city2", + state: "state2", + zipCode: "22222", + zipCodeCtu: "22220", + }, + }, + techNotes: "", + }, + customer: { + firstName: "first", + lastName: "last", + emailAddress: "builddigitaltest@safelite.com", + phoneNumber: "555-555-5555", + isSmsOptIn: false, + }, + damage: { + isRepair: false, + numberOfChips: null, + glassToReplace: [{ glassName: "single", glassLocation: "windshield" }], + }, + lineItems: { + glassParts: [parts.windshield], + supportingItems: [], + vaps: [parts.frontWipers], + promos: [ + { + promoCode: "promoTEST", + kitPrice: 0, + sellingPrice: 0, + laborAmount: 0, + salesTax: 0, + }, + { + promoCode: "promoTEST2", + kitPrice: 0, + sellingPrice: 0, + laborAmount: 0, + salesTax: 0, + }, + ], + }, + payment: { + isInsurance: false, + insuranceCoverage: { + isVerified: null, + coverageStatus: null, + coverageVerificationType: null, + }, + isPia: true, + piaType: "Afterpay", + inactivePromos: [], + }, + schedule: { + date: "date", + startTime: "start", + endTime: "end", + jobMinMinutes: "30", + jobMaxMinutes: "45", + }, + workOrderNumber: "01820-111111", + workOrderId: "222222222222", + referralSequenceNumber: "1111111", + }); + store.getters = { + applicationUser: { + affiliateCookies: [ + { + CookieName: "Cookie1", + CookieValue: "timestamp=2023-09-18/12:00:00&tagEvent=event1", + }, + { + CookieName: "Cookie2", + CookieValue: "timestamp=2023-09-19/12:00:00&tagEvent=event2", + }, + ], + }, + }; + // Arrange + window.dataLayer = []; + + // Act + analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer(); + + const result = window.dataLayer[0]; + + // Assert + console.log(result); + const allFieldsPopulated = Object.keys(result).every( + (key) => result[key] === false || !!result[key] + ); + expect(allFieldsPopulated).toBe(true); + }); + }); });