Merge branch 'develop' into feature/Digital/CSR-1417

This commit is contained in:
hiteshkumar87 2023-10-16 17:06:03 +05:30 committed by GitHub
commit aefac08554
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 613 additions and 140 deletions

View file

@ -27,7 +27,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: { coverageThreshold: {
global: { global: {
statements: 77, statements: 75,
}, },
}, },
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit // Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit

View file

@ -138,6 +138,18 @@ const endpoints = {
url: "/price/api/v1/price/order-items", url: "/price/api/v1/price/order-items",
method: "GET", method: "GET",
}, },
ValidatePromo: {
url: "/price/api/v1/price/order-promo",
method: "POST",
},
RevalidatePromos: {
url: "/price/api/v1/price/revalidated-order-promos",
method: "POST",
},
TaxOrderItems: {
url: "/price/api/v1/price/taxed-order-items",
method: "GET",
},
LogExperimentExposureIfAssigned: { LogExperimentExposureIfAssigned: {
url: "/experiments/api/v1/experiments/log-exposure", url: "/experiments/api/v1/experiments/log-exposure",
method: "POST", method: "POST",

View file

@ -41,6 +41,7 @@ const storeActions = {
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse", UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
VALIDATE_ZIP: "validateZip", VALIDATE_ZIP: "validateZip",
PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "priceOrderItemsAndSaveServerData", PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "priceOrderItemsAndSaveServerData",
TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA: "taxOrderItemsAndSaveServerData",
LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure",
LOG_PAGE_VIEW: "logPageView", LOG_PAGE_VIEW: "logPageView",
LOG_CUSTOM_EVENT: "logCustomEvent", LOG_CUSTOM_EVENT: "logCustomEvent",
@ -50,6 +51,8 @@ const storeActions = {
CLEAR_VIN: "clearVin", CLEAR_VIN: "clearVin",
RESET_SAVE_SESSION_PROMISE: "resetSaveSessionPromise", RESET_SAVE_SESSION_PROMISE: "resetSaveSessionPromise",
GET_SIGNATURE: "getSignature", GET_SIGNATURE: "getSignature",
VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA: "validateOrderPromoAndSaveServerData",
REVALIDATE_ORDER_PROMOS_AND_UPDATE_STORE: "revalidateOrderPromosAndUpdateStore",
// DEPENDENCY MUTATIONS // DEPENDENCY MUTATIONS
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies", RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
@ -83,6 +86,7 @@ const storeActions = {
SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING: SAVE_SUPPORTING_ITEMS_SUPPRESSING_STATE_RESETTING:
"saveSupportingItemsSuppressingStateResetting", "saveSupportingItemsSuppressingStateResetting",
SAVE_VAPS: "saveVaps", SAVE_VAPS: "saveVaps",
SAVE_PROMOS: "savePromos",
SAVE_CUSTOMER_DETAILS: "saveCustomerDetails", SAVE_CUSTOMER_DETAILS: "saveCustomerDetails",
SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes", SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag", SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag",

View file

@ -26,6 +26,8 @@ const storeMutations = {
UPDATE_VAPS: "updateVaps", UPDATE_VAPS: "updateVaps",
UPDATE_SUPPORTING_ITEMS: "updateSupportingItems", UPDATE_SUPPORTING_ITEMS: "updateSupportingItems",
UPDATE_LINE_ITEMS_SERVER_DATA: "updateLineItemsServerData", UPDATE_LINE_ITEMS_SERVER_DATA: "updateLineItemsServerData",
UPDATE_INACTIVE_PROMOS: "updateInactivePromos",
UPDATE_PROMOS: "updatePromos",
UPDATE_REGISTRATION: "updateRegistration", UPDATE_REGISTRATION: "updateRegistration",

View file

@ -21,9 +21,8 @@ export default {
name: "add-vaps-modal-buttons", name: "add-vaps-modal-buttons",
props: { props: {
cartItems: Object, cartItems: Object,
rainDefenseItem: Object,
wiperItems: Object,
vapsTilesCmsName: String, vapsTilesCmsName: String,
availableLineItems: Object,
}, },
data() { data() {
return { return {
@ -55,13 +54,19 @@ export default {
}); });
}, },
rainDefensePrice() { rainDefensePrice() {
const lineItem = this.rainDefenseItem; // const lineItem = this.rainDefenseItem;
const lineItem = this.availableLineItems.find((item) => {
return item.partType === "RAIN DEFENSE";
});
const price = lineItem.laborAmount + lineItem.sellingPrice + lineItem.kitPrice; const price = lineItem.laborAmount + lineItem.sellingPrice + lineItem.kitPrice;
return parseFloat(price).toFixed(2); return parseFloat(price).toFixed(2);
}, },
wipersPrice() { wipersPrice() {
let price = 0; let price = 0;
const lineItems = this.wiperItems; const lineItems = this.availableLineItems.filter((item) => {
return item.partType.includes(" WIPER");
});
lineItems?.forEach((item) => { lineItems?.forEach((item) => {
price += item.laborAmount + item.sellingPrice + item.kitPrice; price += item.laborAmount + item.sellingPrice + item.kitPrice;
}); });

View file

@ -54,36 +54,28 @@
</template> </template>
<script> <script>
import cart from "@/fmg-components/cart/cart";
import baseMixin from "@/mixins/base-mixin.js"; import baseMixin from "@/mixins/base-mixin.js";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import { packageNames } from "@/constants/package-names";
import { import {
getHighestFullySatisfiedTier, getHighestFullySatisfiedTier,
containsLineItemWithPartType, containsLineItemWithPartType,
getPackageContents, getPackageContents,
findLineItemsWithPartType, findLineItemsWithPartType,
} from "@/helpers/service-package-helper"; } from "@/helpers/service-package-helper";
import reviewBlock from "@/layouts/review/review-block/review-block";
import textLink from "@/ux-components/text-link/text-link"; import textLink from "@/ux-components/text-link/text-link";
import textBlock from "@/digital-components/text-block/text-block"; import textBlock from "@/digital-components/text-block/text-block";
export default { export default {
name: "modal", name: "modal",
props: { props: {
headerCmsWidgetName: String,
servicePackageOptionsCmsName: String,
damage: Object, damage: Object,
storeLineItems: Object, servicePackageOptionsCmsName: String,
availableLineItems: Object, availableLineItems: Object,
allowableCartItems: Object, lineItems: Object,
}, },
data() { data() {
return { return {
isActive: false, isActive: false,
//availableVaps: [], TO DO Do we need this?
packageWithVAPS: false, packageWithVAPS: false,
// packageLevel: "",
amountDue: this.getAmountDue(), amountDue: this.getAmountDue(),
}; };
}, },
@ -91,11 +83,6 @@ export default {
toggleClass: function (event) { toggleClass: function (event) {
this.isActive = !this.isActive; this.isActive = !this.isActive;
}, },
initializeComponent(apiResponses) {
//TO DO Do we need this?
// const vapsFromApi = [...apiResponses.wipers, apiResponses.rainDefense];
// this.availableVaps = vapsFromApi;
},
getPackagePriceString(packageName) { getPackagePriceString(packageName) {
const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2); const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2);
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat; return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
@ -104,7 +91,7 @@ export default {
let priceFloat = this.isInsuranceSelected let priceFloat = this.isInsuranceSelected
? 0 ? 0
: baseMixin.methods.getTierOnePackagePrice( : baseMixin.methods.getTierOnePackagePrice(
baseMixin.methods.filterOutFees(this.nullSafeAvailableLineItems) baseMixin.methods.filterOutFees(this.availableLineItems)
); );
priceFloat += this.getVapsPrice(packageName); priceFloat += this.getVapsPrice(packageName);
@ -131,7 +118,7 @@ export default {
getVapsLineItemsForSelectedPackage(packageName) { getVapsLineItemsForSelectedPackage(packageName) {
const packageContentTypes = getPackageContents( const packageContentTypes = getPackageContents(
this.glassToReplace, this.glassToReplace,
this.nullSafeAvailableLineItems, this.availableLineItems,
this.isRepair, this.isRepair,
packageName packageName
); );
@ -140,10 +127,9 @@ export default {
packageContentTypes.forEach((vapType) => { packageContentTypes.forEach((vapType) => {
vapsLineItemsForSelectedPackage.push( vapsLineItemsForSelectedPackage.push(
...findLineItemsWithPartType(vapType, this.nullSafeAvailableLineItems) ...findLineItemsWithPartType(vapType, this.availableLineItems)
); );
}); });
// console.log("VapsLineItems:", vapsLineItemsForSelectedPackage);
return vapsLineItemsForSelectedPackage; return vapsLineItemsForSelectedPackage;
}, },
}, },
@ -184,7 +170,7 @@ export default {
displayedPackageLineItems() { displayedPackageLineItems() {
const displayedPackageLineItems = []; const displayedPackageLineItems = [];
const packageLineItems = this.getVapsLineItemsForSelectedPackage(this.packageLevel); const packageLineItems = this.getVapsLineItemsForSelectedPackage(this.packageLevel);
//TO DO Could we get the same list from this.storeLineItems? // TODO Determine if we could get the same list from this.lineItems?
packageLineItems?.forEach((item) => { packageLineItems?.forEach((item) => {
let price = item.sellingPrice + item.kitPrice + item.laborAmount; let price = item.sellingPrice + item.kitPrice + item.laborAmount;
const packageLineItem = { const packageLineItem = {
@ -195,7 +181,6 @@ export default {
}; };
displayedPackageLineItems.push(packageLineItem); displayedPackageLineItems.push(packageLineItem);
}); });
// console.log("What displayedPackageLineItems is", packageLineItems);
return displayedPackageLineItems; return displayedPackageLineItems;
}, },
displayedNonPackageLineItems() { displayedNonPackageLineItems() {
@ -237,11 +222,11 @@ export default {
return this.damage.isRepair; return this.damage.isRepair;
}, },
vaps() { vaps() {
const vaps = this.storeLineItems?.vaps; const vaps = this.lineItems?.vaps;
return vaps?.length > 0 ? vaps : []; return vaps?.length > 0 ? vaps : [];
}, },
supportingItems() { supportingItems() {
const supportingItems = this.storeLineItems?.supportingItems; const supportingItems = this.lineItems?.supportingItems;
return supportingItems?.length > 0 ? supportingItems : []; return supportingItems?.length > 0 ? supportingItems : [];
}, },
recycleLabel() { recycleLabel() {
@ -259,9 +244,6 @@ export default {
// } // }
return true; return true;
}, },
nullSafeAvailableLineItems() {
return this.availableLineItems ?? [];
},
}, },
components: { components: {
textBlock, textBlock,

View file

@ -159,8 +159,8 @@ export default {
.modal { .modal {
&.menu-modal { &.menu-modal {
left: auto; left: auto;
height: calc(100% - 72px); height: calc(100% - 56px);
top: 72px; top: 56px;
border-top: 1px solid $gray-300; border-top: 1px solid $gray-300;
overflow-x: visible; overflow-x: visible;
overflow-y: visible; overflow-y: visible;

View file

@ -14,7 +14,10 @@
:displayGenericVehicleImage="false" /> :displayGenericVehicleImage="false" />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" /> <funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
</div>
</div>
<div class="row justify-content-md-center">
<div class="col-md-6 col-xl-4">
<alert <alert
ref="alertFewMoreQuestions" ref="alertFewMoreQuestions"
cmsWidgetName="alertWidget" cmsWidgetName="alertWidget"

View file

@ -9,6 +9,7 @@ import {
addMinutes, addMinutes,
shortTimeString, shortTimeString,
} from "./date-helper"; } from "./date-helper";
describe("date-helper.js", () => { describe("date-helper.js", () => {
it("get12HourTimeMobileFormat should return time in expected 12 hour mobile format.", () => { it("get12HourTimeMobileFormat should return time in expected 12 hour mobile format.", () => {
// Define some sample times and their expected 12-hour formats // Define some sample times and their expected 12-hour formats
@ -28,6 +29,7 @@ describe("date-helper.js", () => {
expect(result).toEqual(testCase.expected); expect(result).toEqual(testCase.expected);
} }
}); });
// Test if the function returns the correct 12-hour format for some sample times // Test if the function returns the correct 12-hour format for some sample times
it("should return the correct 12-hour format", function () { it("should return the correct 12-hour format", function () {
// Define some sample times and their expected 12-hour formats // Define some sample times and their expected 12-hour formats
@ -47,6 +49,7 @@ describe("date-helper.js", () => {
expect(result).toEqual(testCase.expected); expect(result).toEqual(testCase.expected);
} }
}); });
it("getDateFormat should return date in the given format.", () => { it("getDateFormat should return date in the given format.", () => {
// Arrange / Act // Arrange / Act
const date = new Date("2023-10-01"); const date = new Date("2023-10-01");
@ -74,6 +77,7 @@ describe("date-helper.js", () => {
expect(result).toEqual(testCase.expected); expect(result).toEqual(testCase.expected);
} }
}); });
it("calculateDuration should return duration in hhmm format.", () => { it("calculateDuration should return duration in hhmm format.", () => {
// Arrange / Act // Arrange / Act
const startDate = new Date("2023-10-01 10:00:00"); const startDate = new Date("2023-10-01 10:00:00");
@ -83,6 +87,7 @@ describe("date-helper.js", () => {
// Assert // Assert
expect(duration).toEqual("1300"); expect(duration).toEqual("1300");
}); });
it("padTo2Digits should return time in 2 digit format.", () => { it("padTo2Digits should return time in 2 digit format.", () => {
// Define some sample time values and their expected strings // Define some sample time values and their expected strings
const testCases = [ const testCases = [
@ -100,6 +105,7 @@ describe("date-helper.js", () => {
expect(result).toEqual(testCase.expected); expect(result).toEqual(testCase.expected);
} }
}); });
it("combineDateAndTime should return combined dateTime format.", () => { it("combineDateAndTime should return combined dateTime format.", () => {
// Define some sample inputs and their expected outputs // Define some sample inputs and their expected outputs
const testCases = [ const testCases = [
@ -117,6 +123,7 @@ describe("date-helper.js", () => {
expect(result.getTime()).toEqual(testCase.expected.getTime()); expect(result.getTime()).toEqual(testCase.expected.getTime());
} }
}); });
it("addMinutes should add given time to date.", () => { it("addMinutes should add given time to date.", () => {
// Define some sample inputs and their expected outputs // Define some sample inputs and their expected outputs
const testCases = [ const testCases = [
@ -154,6 +161,7 @@ describe("date-helper.js", () => {
expect(result.getTime()).toEqual(testCase.expected.getTime()); expect(result.getTime()).toEqual(testCase.expected.getTime());
} }
}); });
it("shortTimeString should return time in short format.", () => { it("shortTimeString should return time in short format.", () => {
// Define some sample dates and their expected short time strings // Define some sample dates and their expected short time strings
const testCases = [ const testCases = [

View file

@ -0,0 +1,101 @@
import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { partTypeStrings } from "@/constants/part-type-strings";
import baseMixin from "@/mixins/base-mixin.js";
export const promoPartNumberStrings = {
WIPER_DISCOUNT_PART_NUMBER: "WIPER DISCOUNT",
RAIN_DEFENSE_DISCOUNT_PART_NUMBER: "DISC RAIN DEFEN",
GLASS_DISCOUNT_PART_NUMBER: "DISCOUNT",
GLASS_CLEANER_DISCOUNT_PART_NUMBER: "DISC GLASS CLN",
};
export const pagesToStripPromoQueryStringFrom = ["quote", "payment-method"];
export function getAddableVapsFromAvailableLineItems(availableLineItems) {
const addableVaps = [];
addableVaps.push(...findLineItemsWithPartType(partTypeStrings.FRONT_WIPER, availableLineItems));
addableVaps.push(
...findLineItemsWithPartType(partTypeStrings.RAIN_DEFENSE, availableLineItems)
);
return addableVaps;
}
export function removeVapsPromosFromPromoArray(promoArray) {
if (!promoArray) {
return [];
}
const filteredPromoArray = promoArray.filter((promo) => {
return (
promo.partNumber != promoPartNumberStrings.WIPER_DISCOUNT_PART_NUMBER &&
promo.partNumber != promoPartNumberStrings.RAIN_DEFENSE_DISCOUNT_PART_NUMBER &&
promo.partNumber != promoPartNumberStrings.GLASS_CLEANER_DISCOUNT_PART_NUMBER
);
});
return filteredPromoArray;
}
export async function revalidatePromosAndValidateNewPromo(
newPromo,
pricedLineItems,
pageNameToLog
) {
const hasActivePromos = store.getters.order.lineItems.promos;
const hasHasInactivePromos = store.getters.order.lineItems.inactivePromos;
const hasNewPromo = !!newPromo;
const addableVaps = getAddableVapsFromAvailableLineItems(pricedLineItems);
let validatePromoResponse = null;
let revalidatePromoResponse = null;
if (hasActivePromos || hasHasInactivePromos) {
revalidatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.REVALIDATE_ORDER_PROMOS_AND_UPDATE_STORE,
null,
pageNameToLog,
false
);
}
if (hasNewPromo) {
validatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA,
{
promoCode: newPromo,
addableVaps: addableVaps,
},
pageNameToLog,
false
);
}
return { validatePromoResponse, revalidatePromoResponse };
}
export function getPromosThatMatchLineItemsOnOrder(promos, lineItemsOnOrder) {
const matchingPromos = [];
promos.forEach((promo) => {
let allIdsMatch = true;
promo.discountedLineItemIds.forEach((id) => {
if (lineItemsOnOrder.filter((x) => x.id === id).length === 0) {
allIdsMatch = false;
return;
}
});
if (allIdsMatch) {
matchingPromos.push(promo);
}
});
return matchingPromos;
}
export function shouldStripPromoQueryString(fmgPageQueryValue) {
return pagesToStripPromoQueryStringFrom.includes(fmgPageQueryValue);
}
// private methods
function findLineItemsWithPartType(typeToFind, itemsToSearch) {
const partTypeMatches = itemsToSearch?.filter(
(lineItem) => lineItem.partType.toUpperCase() === typeToFind.toUpperCase()
);
return partTypeMatches;
}

View file

@ -115,16 +115,16 @@ describe("confirmation.vue", () => {
}); });
}); });
describe("computed properties...", () => { describe("computed properties...", () => {
test("ScheduleDateFormatted should return date in expected format.", () => { // test("ScheduleDateFormatted should return date in expected format.", () => {
//Arrange // //Arrange
const { wrapper } = setupMocks({}); // const { wrapper } = setupMocks({});
// Act // // Act
const testValue = wrapper.vm.ScheduleDateFormatted; // const testValue = wrapper.vm.ScheduleDateFormatted;
// Assert // // Assert
expect(testValue).toEqual("Sunday, January 1"); // expect(testValue).toEqual("Sunday, January 1");
}); // });
test("ScheduleTimeFormatted should return mobile time in expected format.", () => { test("ScheduleTimeFormatted should return mobile time in expected format.", () => {
//Arrange //Arrange
store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE; store.getters.order.serviceLocation.appointmentType = AppointmentTypeStrings.MOBILE;

View file

@ -17,8 +17,8 @@
<cart <cart
:damage="damageInfo" :damage="damageInfo"
:storeLineItems="storeLineItems" :availableLineItems="availableLineItems"
:availableLineItems="cartItems" :lineItems="lineItems"
servicePackageOptionsCmsName="ServicePackageTitle" servicePackageOptionsCmsName="ServicePackageTitle"
@cart-remove="cartRemove" /> @cart-remove="cartRemove" />
@ -34,10 +34,12 @@
<add-vaps-modal-buttons <add-vaps-modal-buttons
:cartItems="cartItems" :cartItems="cartItems"
:wiperItems="availableWipers" :availableLineItems="availableLineItems"
:rainDefenseItem="availableRainDefense" vapsTilesCmsName="VapsProductTiles"
vapsTilesCmsName="VapsProductTiles" /> v-on="{ 'buttonEvent.openModal': openModal }" />
<button @click="openModal('RainDefenseModal')">OPEN MODAL</button>
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
<paymentMethodQuestion <paymentMethodQuestion
v-if="!isPiaDisabled" v-if="!isPiaDisabled"
v-model="paymentMethodInternalModel" /> v-model="paymentMethodInternalModel" />
@ -64,6 +66,7 @@ import paymentMethodQuestion from "@/layouts/payment-method/payment-method-quest
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue"; import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
import cart from "@/fmg-components/cart/cart"; import cart from "@/fmg-components/cart/cart";
import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons"; import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons";
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js"; import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
import alert from "@/ux-components/alert/alert"; import alert from "@/ux-components/alert/alert";
@ -88,11 +91,14 @@ export default {
null, null,
"payment-method" "payment-method"
); );
const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging( const rainDefensePromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_RAIN_DEFENSE, storeActions.GET_RAIN_DEFENSE,
null, null,
"payment-method" "payment-method"
); );
console.log("rainDefensePromise: ", rainDefensePromise);
const supportingItemsPromise = baseMixin.methods.dispatchStoreActionWithLogging( const supportingItemsPromise = baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_SUPPORTING_ITEMS, storeActions.GET_SUPPORTING_ITEMS,
null, null,
@ -119,16 +125,17 @@ export default {
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const clonedGlassParts = store.getters.order.lineItems.glassParts
? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts)) const glassParts = (await store.getters.order.lineItems.glassParts) ?? [];
: [];
const availableLineItems = [ const availableLineItems = [
resultMap.rainDefense, resultMap.rainDefense,
...resultMap.supportingItems, ...resultMap.supportingItems,
...resultMap.wipers, ...resultMap.wipers,
...clonedGlassParts, ...glassParts,
]; ];
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
const pricedAvailableLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA, storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
{ {
availableLineItems: availableLineItems, availableLineItems: availableLineItems,
@ -136,30 +143,25 @@ export default {
"payment-method", "payment-method",
false false
); );
const storeLineItems = store.getters.lineItems; const lineItems = store.getters.lineItems;
const cartItems = [
...clonedGlassParts, const cartItems = [...glassParts, ...lineItems.supportingItems, ...lineItems.vaps]; // TOBEREMOVED BY AJC IN CSR-1384
...storeLineItems.supportingItems,
...storeLineItems.vaps,
];
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.cartItems = cartItems; // TOBEREMOVED BY AJC IN CSR-1384
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.availableLineItems = pricingResults; vm.availableLineItems = pricedAvailableLineItems;
vm.availableWipers = resultMap.wipers; vm.lineItems = lineItems;
vm.availableRainDefense = resultMap.rainDefense;
vm.cartItems = cartItems;
}); });
}, },
data() { data() {
return { return {
cartItems: [], cartItems: [], // TOBEREMOVED BY AJC IN CSR-1384
availableWipers: null,
availableRainDefense: null, lineItems: [],
availableLineItems: null, availableLineItems: [],
supportingItems: null,
pricedGlassParts: null,
displayPaypalAlert: this.getPaypalAlert(), displayPaypalAlert: this.getPaypalAlert(),
paymentMethodInternalModel: null, paymentMethodInternalModel: null,
}; };
@ -217,6 +219,9 @@ export default {
packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs
); );
}, },
openModal(modalName) {
this.$refs[modalName].openModal();
},
getPaypalAlert() { getPaypalAlert() {
return store.getters.order.payment.piaErrorCode ? true : false; return store.getters.order.payment.piaErrorCode ? true : false;
}, },
@ -231,7 +236,7 @@ export default {
const matchedIndices = []; const matchedIndices = [];
this.cartItems.forEach((cartItem, i) => { this.cartItems.forEach((cartItem, i) => {
if (cartItem.partType === item.partType) { if (cartItem.partType === item.partType) {
console.log("adding this to matchedIndices: ", i); // console.log("adding this to matchedIndices: ", i);
matchedIndices.push(i); matchedIndices.push(i);
} }
}); });
@ -244,6 +249,17 @@ export default {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route); this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
}, },
async forwardButtonAction() { async forwardButtonAction() {
switch (this.paymentMethod) {
case paymentMethods.CREDIT_CARD:
this.piaSetup("cc");
break;
case paymentMethods.PAYPAL:
this.piaSetup("pp");
break;
case paymentMethods.AFTERPAY:
this.piaSetup("ap");
break;
default:
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false); this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
this.dispatchStoreAction(this.storeActions.SAVE_WORK_ORDER_FLAG, true, false); this.dispatchStoreAction(this.storeActions.SAVE_WORK_ORDER_FLAG, true, false);
await submitWorkOrder({ pageNameToLog: "payment-method" }); await submitWorkOrder({ pageNameToLog: "payment-method" });
@ -251,6 +267,7 @@ export default {
this.navigationScenarios.CLICKED_FORWARD, this.navigationScenarios.CLICKED_FORWARD,
this.$route this.$route
); );
}
}, },
async ccdPayment() { async ccdPayment() {
this.piaSetup("cc"); this.piaSetup("cc");
@ -264,16 +281,18 @@ export default {
async piaSetup(payNowType) { async piaSetup(payNowType) {
this.$refs.loadingModal.showModal(); this.$refs.loadingModal.showModal();
//leaving site, clear any save session promises that we will not be able to resolve when we return // since we're leaving the site for pia, clear any save session promises that we will not be able to resolve when we return
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
await this.dispatchStoreAction(storeActions.SAVE_PAY_NOW_TYPE, payNowType, false); await this.dispatchStoreAction(storeActions.SAVE_PAY_NOW_TYPE, payNowType, false);
// make sure pia error codes are reset, and get a pia work order in delete status // make sure pia error codes are reset
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false); this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
this.dispatchStoreAction(storeActions.SAVE_PIA_WORK_ORDER, true);
// if we don't have a work order in delete substatus, set the flag and submit
if (!store.getters.order.workOrderNumber) { if (!store.getters.order.workOrderNumber) {
this.dispatchStoreAction(storeActions.SAVE_PIA_WORK_ORDER, true);
await submitWorkOrder({ pageNameToLog: "payment-method" }); await submitWorkOrder({ pageNameToLog: "payment-method" });
this.dispatchStoreAction(storeActions.SAVE_PIA_WORK_ORDER, false);
} }
this.$router.navigateWithoutSaving( this.$router.navigateWithoutSaving(
@ -284,12 +303,9 @@ export default {
}, },
computed: { computed: {
damageInfo() { damageInfo() {
// console.log("this.$store.getters.damage ", this.$store.getters.damage)
return this.$store.getters.damage; return this.$store.getters.damage;
}, },
storeLineItems() {
// console.log("storeLineItems, aka lineItems from store: ", this.$store.getters.lineItems)
return this.$store.getters.lineItems;
},
customCtaCopy() { customCtaCopy() {
switch (this.paymentMethod) { switch (this.paymentMethod) {
case paymentMethods.CREDIT_CARD: case paymentMethods.CREDIT_CARD:
@ -308,7 +324,8 @@ export default {
const enablePIA = const enablePIA =
this.getSettingValue(experimentSettings.SUBMIT_ORDER_ENABLE_PIA) === "true"; this.getSettingValue(experimentSettings.SUBMIT_ORDER_ENABLE_PIA) === "true";
return !(piaExperience && enablePIA); return false;
//return !(piaExperience && enablePIA);
}, },
paymentMethod() { paymentMethod() {
if (this.isPiaDisabled) { if (this.isPiaDisabled) {
@ -332,6 +349,7 @@ export default {
cart, cart,
alert, alert,
addVapsModalButtons, addVapsModalButtons,
contentGroupModal,
paymentMethodQuestion, paymentMethodQuestion,
}, },
}; };

View file

@ -21,6 +21,12 @@ jest.mock("@/helpers/heritage-integration/navigation-helper", () => ({
navigateToHeritageFunnel: jest.fn(), navigateToHeritageFunnel: jest.fn(),
})); }));
jest.mock("@/helpers/promotions-helper", () => ({
revalidatePromosAndValidateNewPromo: jest.fn(() => {
return { validatePromoResponse: null, revalidatePromoResponse: null };
}),
}));
jest.mock( jest.mock(
"@/store", "@/store",
() => { () => {
@ -43,11 +49,20 @@ jest.mock("@/mixins/base-mixin", () => ({
getTierOnePackagePrice() { getTierOnePackagePrice() {
return mockTierOnePrice; return mockTierOnePrice;
}, },
filterOutFees() { filterOutFees(items) {
return null; return null;
}, },
}, },
})); }));
const mockMixin = {
methods: {
filterOutFees: jest.fn().mockImplementation(() => {
return null;
}),
},
};
let mockTierOnePrice = 501; let mockTierOnePrice = 501;
const mockPriceOrderStoreAction = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA; const mockPriceOrderStoreAction = storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA;
@ -93,6 +108,16 @@ afterEach(() => {
describe("quote.vue", () => { describe("quote.vue", () => {
test("IsInsurance false should navigateWithSaving", async () => { test("IsInsurance false should navigateWithSaving", async () => {
//Arrange //Arrange
store.getters.payment = {
insuranceCoverage: {},
isInsurance: false,
};
store.getters.order = {
lineItems: [],
payment: {
parentAccountNumber: 167132,
},
};
const { wrapper } = setupMocks({ const { wrapper } = setupMocks({
customMountOptions: { customMountOptions: {
router: { router: {
@ -102,11 +127,6 @@ describe("quote.vue", () => {
}, },
}); });
store.getters.payment = {
insuranceCoverage: {},
isInsurance: false,
};
wrapper.vm.dispatchStoreAction = jest.fn(() => { wrapper.vm.dispatchStoreAction = jest.fn(() => {
return { return {
data: [], data: [],
@ -124,20 +144,28 @@ describe("quote.vue", () => {
test("IsInsurance true should navigateToHeritageFunnel", async () => { test("IsInsurance true should navigateToHeritageFunnel", async () => {
//Arrange //Arrange
store.getters = {
payment: {
insuranceCoverage: {},
isInsurance: true,
},
order: {
lineItems: [],
payment: {
parentAccountNumber: null,
},
},
};
const { wrapper } = setupMocks({ const { wrapper } = setupMocks({
customMountOptions: { customMountOptions: {
router: { router: {
navigateWithSaving: jest.fn(), navigateWithSaving: jest.fn(),
}, },
route: { quote }, route: { quote },
mixins: [mockMixin],
}, },
}); });
store.getters.payment = {
insuranceCoverage: {},
isInsurance: true,
};
wrapper.vm.dispatchStoreAction = jest.fn(() => { wrapper.vm.dispatchStoreAction = jest.fn(() => {
return { return {
data: [], data: [],
@ -154,9 +182,9 @@ describe("quote.vue", () => {
}); });
test("should pass arePagePrerequisitesValid with a repair order", () => { test("should pass arePagePrerequisitesValid with a repair order", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: [],
serviceLocation: { serviceLocation: {
zipCode: "12345", zipCode: "12345",
zipCodeCtu: "value", zipCodeCtu: "value",
@ -172,6 +200,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
@ -179,7 +208,6 @@ describe("quote.vue", () => {
}); });
test("should pass arePagePrerequisitesValid with a replace order", () => { test("should pass arePagePrerequisitesValid with a replace order", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
serviceLocation: { serviceLocation: {
@ -200,6 +228,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
@ -207,9 +236,9 @@ describe("quote.vue", () => {
}); });
test("should fail arePagePrerequisitesValid without glass parts or flagged as repair", () => { test("should fail arePagePrerequisitesValid without glass parts or flagged as repair", () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: [],
serviceLocation: { serviceLocation: {
zipCode: "12345", zipCode: "12345",
zipCodeCtu: "value", zipCodeCtu: "value",
@ -220,6 +249,7 @@ describe("quote.vue", () => {
referralNumber: "1234567", referralNumber: "1234567",
}, },
}; };
const { wrapper } = setupMocks({});
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
@ -227,8 +257,6 @@ describe("quote.vue", () => {
}); });
test("should have non-null values for necessary data members after 'beforeRouteEnter'", async () => { test("should have non-null values for necessary data members after 'beforeRouteEnter'", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -236,7 +264,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
//mock this to avoid needing to populate this.$route in an unrelated test //mock this to avoid needing to populate this.$route in an unrelated test
wrapper.vm.getDefaultIsInsuranceSelectedValue = jest.fn(); wrapper.vm.getDefaultIsInsuranceSelectedValue = jest.fn();
@ -257,8 +285,6 @@ describe("quote.vue", () => {
}); });
test("should default to insurance if query param 'isInsurance' is true", async () => { test("should default to insurance if query param 'isInsurance' is true", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -272,6 +298,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
wrapper.vm.$route = { query: { isInsurance: "true" } }; wrapper.vm.$route = { query: { isInsurance: "true" } };
//Act //Act
@ -287,8 +314,6 @@ describe("quote.vue", () => {
}); });
test("should default to cash if query param 'isInsurance' is false", async () => { test("should default to cash if query param 'isInsurance' is false", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -302,6 +327,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
wrapper.vm.$route = { query: { isInsurance: "false" } }; wrapper.vm.$route = { query: { isInsurance: "false" } };
//Act //Act
@ -317,7 +343,6 @@ describe("quote.vue", () => {
}); });
test("should default to insurance if insurance selection is saved to store", async () => { test("should default to insurance if insurance selection is saved to store", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
@ -332,6 +357,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
// Ensure that query param isn't overriding selection // Ensure that query param isn't overriding selection
wrapper.vm.$route = { query: null }; wrapper.vm.$route = { query: null };
@ -348,8 +374,6 @@ describe("quote.vue", () => {
}); });
test("should default to cash if cash selection is saved to store", async () => { test("should default to cash if cash selection is saved to store", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -363,6 +387,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
// Ensure that query param isn't overriding selection // Ensure that query param isn't overriding selection
wrapper.vm.$route = { query: null }; wrapper.vm.$route = { query: null };
@ -380,8 +405,6 @@ describe("quote.vue", () => {
test("should default to cash if total economy package price is under $500", async () => { test("should default to cash if total economy package price is under $500", async () => {
// Also needs no query parameter or previous selection in store to be present // Also needs no query parameter or previous selection in store to be present
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -396,6 +419,7 @@ describe("quote.vue", () => {
}, },
}; };
mockTierOnePrice = 200; mockTierOnePrice = 200;
const { wrapper } = setupMocks({});
// Ensure that query param isn't overriding selection // Ensure that query param isn't overriding selection
wrapper.vm.$route = { query: null }; wrapper.vm.$route = { query: null };
@ -413,7 +437,6 @@ describe("quote.vue", () => {
test("should default to insurance if total economy package price is over $500", async () => { test("should default to insurance if total economy package price is over $500", async () => {
// Also needs no query parameter or previous selection in store to be present // Also needs no query parameter or previous selection in store to be present
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
@ -429,6 +452,7 @@ describe("quote.vue", () => {
}, },
}; };
mockTierOnePrice = 505; mockTierOnePrice = 505;
const { wrapper } = setupMocks({});
// Ensure that query param isn't overriding selection // Ensure that query param isn't overriding selection
wrapper.vm.$route = { query: null }; wrapper.vm.$route = { query: null };
@ -445,7 +469,7 @@ describe("quote.vue", () => {
}); });
test("Should default to insurence if user Service zip is from certain States", async () => { test("Should default to insurence if user Service zip is from certain States", async () => {
//Arrange //Arrange
const { wrapper } = setupMocks({});
store.getters = { store.getters = {
order: { order: {
lineItems: { lineItems: {
@ -459,6 +483,7 @@ describe("quote.vue", () => {
}, },
}, },
}; };
const { wrapper } = setupMocks({});
wrapper.vm.$route = { query: null }; wrapper.vm.$route = { query: null };
//Act //Act
await quote.beforeRouteEnter.call( await quote.beforeRouteEnter.call(

View file

@ -29,6 +29,7 @@
:availableLineItems="availableLineItems" :availableLineItems="availableLineItems"
:isInsuranceSelected="isInsuranceSelected" :isInsuranceSelected="isInsuranceSelected"
@vapsItemsSelected="vapsItemsSelectedAction" @vapsItemsSelected="vapsItemsSelectedAction"
:activePromos="allActivePromos"
v-on="{ 'buttonEvent.openModal': openModalAction }" v-on="{ 'buttonEvent.openModal': openModalAction }"
validationRules="option-required" validationRules="option-required"
isRequired /> isRequired />
@ -79,6 +80,10 @@ import { Form, defineRule } from "vee-validate";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { applicationConfig } from "@/constants/application-config"; import { applicationConfig } from "@/constants/application-config";
import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states"; import { payWithInsuranceStates } from "@/constants/pay-with-insurance-states";
import { revalidatePromosAndValidateNewPromo } from "@/helpers/promotions-helper";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { setTransitionHooks } from "vue";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED)); defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
export default { export default {
@ -122,14 +127,12 @@ export default {
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const clonedGlassParts = store.getters.order.lineItems.glassParts const nullSafeGlassParts = store.getters.order.lineItems.glassParts ?? [];
? JSON.parse(JSON.stringify(store.getters.order.lineItems.glassParts))
: [];
const availableLineItems = [ const availableLineItems = [
resultMap.rainDefense, resultMap.rainDefense,
...resultMap.supportingItems, ...resultMap.supportingItems,
...resultMap.wipers, ...resultMap.wipers,
...clonedGlassParts, ...nullSafeGlassParts,
]; ];
const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging( const pricingResults = await baseMixin.methods.dispatchStoreActionWithLogging(
@ -146,13 +149,26 @@ export default {
resultMap.supportingItems, resultMap.supportingItems,
false false
); );
// Promo logic
const promoCodeFromQueryString = getQuerystringParameter(queryStrings.PROMO);
const { validatePromoResponse, revalidatePromoResponse } =
await revalidatePromosAndValidateNewPromo(
promoCodeFromQueryString,
pricingResults,
"quote"
);
// End of promo logic
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.pricedGlassParts = clonedGlassParts; vm.pricedGlassParts = nullSafeGlassParts;
vm.supportingItems = resultMap.supportingItems; vm.supportingItems = resultMap.supportingItems;
vm.availableLineItems = pricingResults; vm.availableLineItems = pricingResults;
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems); vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);
vm.newValidatedPromos = validatePromoResponse?.data.orderPromos;
}); });
}, },
data() { data() {
@ -162,8 +178,18 @@ export default {
availableLineItems: null, availableLineItems: null,
supportingItems: null, supportingItems: null,
pricedGlassParts: null, pricedGlassParts: null,
newValidatedPromos: null,
}; };
}, },
computed: {
allActivePromos() {
const allActivePromos = [];
if (this.newValidatedPromos) allActivePromos.push(...this.newValidatedPromos);
if (this.$store.getters.order.lineItems.promos)
allActivePromos.push(...this.$store.getters.order.lineItems.promos);
return allActivePromos;
},
},
methods: { methods: {
openModalAction(modalName) { openModalAction(modalName) {
this.$refs[modalName].openModal(); this.$refs[modalName].openModal();
@ -239,6 +265,7 @@ export default {
} }
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false); this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
this.dispatchStoreAction(this.storeActions.SAVE_PROMOS, this.newValidatedPromos, false);
const payment = this.$store.getters.payment; const payment = this.$store.getters.payment;
if (payment.isInsurance) { if (payment.isInsurance) {

View file

@ -29,6 +29,10 @@ import {
containsLineItemWithPartType, containsLineItemWithPartType,
findLineItemsWithPartType, findLineItemsWithPartType,
} from "@/helpers/service-package-helper"; } from "@/helpers/service-package-helper";
import {
getPromosThatMatchLineItemsOnOrder,
removeVapsPromosFromPromoArray,
} from "@/helpers/promotions-helper";
export default { export default {
name: "servicePackageQuestion", name: "servicePackageQuestion",
@ -40,6 +44,7 @@ export default {
isRequired: Boolean, isRequired: Boolean,
isInsuranceSelected: Boolean, isInsuranceSelected: Boolean,
availableLineItems: null, availableLineItems: null,
activePromos: null,
}, },
data() { data() {
return { return {
@ -86,8 +91,11 @@ export default {
buttonLabel: this.getHeaderTextFromCms(answer.SubWidgetName), buttonLabel: this.getHeaderTextFromCms(answer.SubWidgetName),
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName), buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName), buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
buttonAuxillaryCopy: this.getPackagePriceString(answer.Name), buttonAuxillaryCopy: this.getDiscountedPackagePriceString(answer.Name),
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName), buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
additionalButtonData: {
strikeThroughPrice: this.getPackagePriceString(answer.Name),
},
})); }));
return modifiedAnswers; return modifiedAnswers;
}, },
@ -161,21 +169,33 @@ export default {
return this.processIfStatements(footerText, "custom", this.getCustomValueFromString); return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
}, },
getPackagePriceString(packageName) { getPackagePriceString(packageName) {
const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2); const formattedPriceFloat = parseFloat(
this.getPackagePrice(packageName, { discountedPrice: false })
).toFixed(2);
return "$" + formattedPriceFloat;
},
getDiscountedPackagePriceString(packageName) {
const formattedPriceFloat = parseFloat(
this.getPackagePrice(packageName, { discountedPrice: true })
).toFixed(2);
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat; return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
}, },
getPackagePrice(packageName) { getPackagePrice(packageName, { discountedPrice = false }) {
const lineItemsToPrice = [...this.nullSafeAvailableLineItems];
if (discountedPrice) {
lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
}
let priceFloat = this.isInsuranceSelected let priceFloat = this.isInsuranceSelected
? 0 ? 0
: baseMixin.methods.getTierOnePackagePrice( : baseMixin.methods.getTierOnePackagePrice(
baseMixin.methods.filterOutFees(this.nullSafeAvailableLineItems) baseMixin.methods.filterOutFees(lineItemsToPrice)
); );
priceFloat += this.getVapsPrice(packageName); priceFloat += this.getVapsPrice(packageName, discountedPrice);
return priceFloat; return priceFloat;
}, },
getVapsPrice(packageName) { getVapsPrice(packageName, applyPromoDiscounts = false) {
const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName); const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName);
let price = 0; let price = 0;
@ -184,6 +204,16 @@ export default {
price += baseMixin.methods.getTotalLineItemPrice(item); price += baseMixin.methods.getTotalLineItemPrice(item);
}); });
if (applyPromoDiscounts && this.activePromos) {
const relevantPromos = getPromosThatMatchLineItemsOnOrder(
this.activePromos,
vapsItems
);
relevantPromos.forEach((promo) => {
price += baseMixin.methods.getTotalLineItemPrice(promo);
});
}
return price; return price;
}, },
selectDefaultPackage() { selectDefaultPackage() {

View file

@ -494,6 +494,9 @@ export default {
this.updateAndSaveSupportingItems(); this.updateAndSaveSupportingItems();
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route); this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
}, },
openModalAction(modalName) {
this.$refs[modalName].openModal();
},
}, },
watch: { watch: {
selectedAppointmentType: { selectedAppointmentType: {

View file

@ -28,6 +28,7 @@ import store from "@/store";
import analyticsMixin from "@/mixins/analytics-mixin"; import analyticsMixin from "@/mixins/analytics-mixin";
import { experimentTriggers } from "../constants/experiments"; import { experimentTriggers } from "../constants/experiments";
import { applicationConfig } from "../constants/application-config"; import { applicationConfig } from "../constants/application-config";
import { shouldStripPromoQueryString } from "@/helpers/promotions-helper";
const routes = [ const routes = [
{ {
@ -283,7 +284,7 @@ async function navigate(
queryStringsObject[queryStrings.ZIP_CODE] = zip; queryStringsObject[queryStrings.ZIP_CODE] = zip;
} }
if (promo) { if (promo && !shouldStripPromoQueryString(currentRoute.query.fmgPage)) {
queryStringsObject[queryStrings.PROMO] = promo; queryStringsObject[queryStrings.PROMO] = promo;
} }

View file

@ -14,6 +14,7 @@ import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper
import { deepEqual } from "@/helpers/object-helper"; import { deepEqual } from "@/helpers/object-helper";
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants"; import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
import { getQuerystringParameter } from "@/helpers/querystring-helper"; import { getQuerystringParameter } from "@/helpers/querystring-helper";
import { deepClone } from "@/helpers/object-helper";
import { queryStrings } from "@/constants/query-strings"; import { queryStrings } from "@/constants/query-strings";
import { partTypeStrings } from "@/constants/part-type-strings"; import { partTypeStrings } from "@/constants/part-type-strings";
import { import {
@ -84,6 +85,7 @@ const getDefaultState = () => {
supportingItems: null, supportingItems: null,
vaps: null, vaps: null,
serverData: null, serverData: null,
promos: null,
}, },
payment: { payment: {
isInsurance: null, isInsurance: null,
@ -94,6 +96,7 @@ const getDefaultState = () => {
parentAccountNumber: 0, parentAccountNumber: 0,
payNowType: "cc", payNowType: "cc",
piaErrorCode: null, piaErrorCode: null,
inactivePromos: null,
}, },
schedule: { schedule: {
date: null, date: null,
@ -194,6 +197,12 @@ export const mutations = {
updateLineItemsServerData(state, serverData) { updateLineItemsServerData(state, serverData) {
state.order.lineItems.serverData = serverData; state.order.lineItems.serverData = serverData;
}, },
updateInactivePromos(state, inactivePromos) {
state.order.payment.inactivePromos = inactivePromos;
},
updatePromos(state, promos) {
state.order.lineItems.promos = promos;
},
updatePageData(state, pageData) { updatePageData(state, pageData) {
state.applicationUser.pageData[pageData.page] = pageData.data; state.applicationUser.pageData[pageData.page] = pageData.data;
}, },
@ -1234,10 +1243,10 @@ export const actions = {
return response; return response;
}, },
getWipers(context, { pageNameToLog }) { async getWipers(context, { pageNameToLog }) {
const carId = context.getters.vehicle.carId; const carId = context.getters.vehicle.carId;
const serviceZipCode = context.getters.order.serviceLocation.zipCode; const serviceZipCode = context.getters.order.serviceLocation.zipCode;
return globalMethods const response = await globalMethods
.callHttpClient({ .callHttpClient({
method: endpoints.GetWipers.method, method: endpoints.GetWipers.method,
endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`, endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`,
@ -1248,15 +1257,20 @@ export const actions = {
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow // The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
return []; return [];
}); });
syncLineItemIds(response.data, context.getters.order.lineItems.vaps);
return response;
}, },
getRainDefense(context, { pageNameToLog }) { async getRainDefense(context, { pageNameToLog }) {
return globalMethods.callHttpClient({ const response = await globalMethods.callHttpClient({
method: endpoints.GetRainDefense.method, method: endpoints.GetRainDefense.method,
endpoint: endpoints.GetRainDefense.url, endpoint: endpoints.GetRainDefense.url,
logApiCall: true, logApiCall: true,
pageNameToLog: pageNameToLog, pageNameToLog: pageNameToLog,
}); });
syncLineItemIds([response.data], context.getters.order.lineItems.vaps);
return response;
}, },
getMobileFeePart(context, { pageNameToLog }) { getMobileFeePart(context, { pageNameToLog }) {
@ -1536,6 +1550,7 @@ export const actions = {
endpoint: endpoints.SaveSession.url, endpoint: endpoints.SaveSession.url,
payload: { payload: {
submitAfterSave: context.state.submitAfterSave, submitAfterSave: context.state.submitAfterSave,
userAgent: navigator.userAgent,
applicationUser: { applicationUser: {
crmCustomerId: applicationUser.crmCustomerId, crmCustomerId: applicationUser.crmCustomerId,
experiments: applicationUser.experiments, experiments: applicationUser.experiments,
@ -1581,6 +1596,7 @@ export const actions = {
supportingItems: lineItems.supportingItems, supportingItems: lineItems.supportingItems,
vaps: lineItems.vaps, vaps: lineItems.vaps,
serverData: lineItems.serverData, serverData: lineItems.serverData,
promos: lineItems.promos,
}, },
payment: { payment: {
InsuranceCoverage: { InsuranceCoverage: {
@ -1588,6 +1604,7 @@ export const actions = {
}, },
isInsurance: order.payment.isInsurance, isInsurance: order.payment.isInsurance,
parentAccountNumber: order.payment.parentAccountNumber, parentAccountNumber: order.payment.parentAccountNumber,
inactivePromos: order.payment.inactivePromos,
}, },
serviceLocation: { serviceLocation: {
streetAddress: order.serviceLocation.address, streetAddress: order.serviceLocation.address,
@ -2006,17 +2023,21 @@ export const actions = {
if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) { if (!deepEqual(supportingItems, context.state.order.lineItems.supportingItems)) {
context.dispatch(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES); context.dispatch(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES);
} }
addGuidToLineItemsIfNotAlreadyThere(supportingItems);
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems); context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
}, },
saveSupportingItemsSuppressingStateResetting(context, supportingItems) { saveSupportingItemsSuppressingStateResetting(context, supportingItems) {
addGuidToLineItemsIfNotAlreadyThere(supportingItems);
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems); context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
}, },
saveVaps(context, vaps) { saveVaps(context, vaps) {
addGuidToLineItemsIfNotAlreadyThere(vaps);
context.commit(storeMutations.UPDATE_VAPS, vaps); context.commit(storeMutations.UPDATE_VAPS, vaps);
}, },
savePromos(context, promos) {
context.commit(storeMutations.UPDATE_PROMOS, promos);
},
// Price order actions // Price order actions
async priceOrderItemsAndSaveServerData( async priceOrderItemsAndSaveServerData(
@ -2026,14 +2047,18 @@ export const actions = {
const zipCodeToUse = serviceZipCode const zipCodeToUse = serviceZipCode
? serviceZipCode ? serviceZipCode
: context.getters.order.serviceLocation.zipCode; : context.getters.order.serviceLocation.zipCode;
const ctuToUse = serviceZipCodeCtu const ctuToUse = serviceZipCodeCtu
? serviceZipCodeCtu ? serviceZipCodeCtu
: context.getters.order.serviceLocation.zipCodeCtu; : context.getters.order.serviceLocation.zipCodeCtu;
const flattenedLineItemsWithChildParts = const flattenedLineItemsWithChildParts =
getFlattenedArrayOfLineItemsWithChildParts(availableLineItems); getFlattenedArrayOfLineItemsWithChildParts(availableLineItems);
const lineItemsWithOnlyPartNumbers = flattenedLineItemsWithChildParts.map((lineItem) => ({ const lineItemsWithOnlyPartNumbers = flattenedLineItemsWithChildParts.map((lineItem) => ({
partNumber: lineItem.partNumber, partNumber: lineItem.partNumber,
})); }));
const availableLineItemsFormattedForRequest = const availableLineItemsFormattedForRequest =
buildQueryStringParameterFromArrayOfComplexObjects( buildQueryStringParameterFromArrayOfComplexObjects(
lineItemsWithOnlyPartNumbers, lineItemsWithOnlyPartNumbers,
@ -2067,9 +2092,160 @@ export const actions = {
context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData); context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData);
availableLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems); const pricedLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems);
return availableLineItems; return pricedLineItems;
},
// Tax order actions
async taxOrderItemsAndSaveServerData(
context,
{
payload: {
billToAccountNumber,
providerNumber,
appointmentType,
serviceLocationState,
serviceLocationZipCode,
pricedLineItems,
},
pageNameToLog,
}
) {
const flattenedLineItemsWithChildParts =
getFlattenedArrayOfLineItemsWithChildParts(pricedLineItems);
const lineItemsWithOnlyPriceInfo = flattenedLineItemsWithChildParts.map((lineItem) => ({
partNumber: lineItem.partNumber,
laborAmount: lineItem.laborAmount,
kitPrice: lineItem.kitPrice,
sellingPrice: lineItem.sellingPrice,
}));
const pricedLineItemsFormattedForRequest =
buildQueryStringParameterFromArrayOfComplexObjects(
lineItemsWithOnlyPriceInfo,
"lineItems"
);
let queryString =
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
`&BillToAccountNumber=${billToAccountNumber}` +
`&ProviderNumber=${providerNumber}` +
`&AppointmentType=${appointmentType}` +
`&ServiceLocation.State=${serviceLocationState}` +
`&ServiceLocation.ZipCode=${serviceLocationZipCode}` +
`&${pricedLineItemsFormattedForRequest}`;
const lineItemServerData = context.getters.order.lineItems.serverData;
if (lineItemServerData) {
queryString += `&ServerData=${encodeURIComponent(lineItemServerData)}`;
}
const response = await globalMethods.callHttpClient({
method: endpoints.TaxOrderItems.method,
endpoint: `${endpoints.TaxOrderItems.url}?${queryString}`,
logApiCall: true,
pageNameToLog: pageNameToLog,
});
context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData);
const taxedLineItems = addTaxesToPricedLineItems(
pricedLineItems,
response.data.taxedLineItems
);
return taxedLineItems;
},
async validateOrderPromoAndSaveServerData(
context,
{ payload: { promoCode, addableVaps }, pageNameToLog }
) {
const order = context.getters.order;
addGuidToLineItemsIfNotAlreadyThere(addableVaps);
const requestObject = {
promoCode: promoCode,
order: {
appointmentType: order.serviceLocation.appointmentType,
carId: order.vehicle.carId,
correlationId: order.referralCorrelationId,
eon: order.eon,
isRepair: order.damage.isRepair,
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
lineItemsOnOrder: getArrayOfAllLineItems(order.lineItems),
addableVaps: addableVaps,
parentAccountNumber: order.payment.parentAccountNumber,
referralSequenceNumber: order.referralSequenceNumber,
serviceState: order.serviceLocation.state,
serverData: order.lineItems.serverData,
vehicleYear: "" + order.vehicle.year,
zipCodeOrProviderCtu:
order.serviceLocation.appointmentType === "Inshop"
? order.serviceLocation.provider.address.zipCodeCtu
: order.serviceLocation.zipCodeCtu,
},
};
const validateResponse = await globalMethods.callHttpClient({
method: endpoints.ValidatePromo.method,
endpoint: endpoints.ValidatePromo.url,
payload: requestObject,
logApiCall: true,
pageNameToLog: pageNameToLog,
});
context.commit(
storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA,
validateResponse.data.lineItemsServerData
);
return validateResponse;
},
async revalidateOrderPromosAndUpdateStore(context, { pageNameToLog }) {
const order = context.getters.order;
let requestObject = {
inactivePromos: order.payment.inactivePromos,
order: {
appointmentType: order.serviceLocation.appointmentType,
carId: order.vehicle.carId,
correlationId: order.referralCorrelationId,
eon: order.eon,
isRepair: order.damage.isRepair,
glassToReplace: renameGlassToReplaceAttributes(order.damage.glassToReplace),
lineItemsOnOrder: getArrayOfAllLineItems(order.lineItems),
parentAccountNumber: order.payment.parentAccountNumber,
referralSequenceNumber: order.referralSequenceNumber,
serviceState: order.serviceLocation.state,
serverData: order.lineItems.serverData,
vehicleYear: "" + order.vehicle.year,
zipCodeOrProviderCtu:
order.serviceLocation.appointmentType === "Inshop"
? order.serviceLocation.provider.address.zipCodeCtu
: order.serviceLocation.zipCodeCtu,
},
};
const revalidateResponse = await globalMethods.callHttpClient({
method: endpoints.RevalidatePromos.method,
endpoint: endpoints.RevalidatePromos.url,
payload: requestObject,
logApiCall: true,
pageNameToLog: pageNameToLog,
});
const revalidationErrorPromoCodes = revalidateResponse.data.errors.map((x) => x.promoCode);
context.commit(storeMutations.UPDATE_PROMOS, revalidateResponse.data.promoLineItems);
context.commit(storeMutations.UPDATE_INACTIVE_PROMOS, revalidationErrorPromoCodes);
context.commit(
storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA,
revalidateResponse.data.lineItemsServerData
);
return revalidateResponse;
}, },
// Misc order actions // Misc order actions
@ -2136,7 +2312,7 @@ export const actions = {
if (!deepEqual(parts, context.state.order.lineItems.glassParts)) { if (!deepEqual(parts, context.state.order.lineItems.glassParts)) {
context.dispatch(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES); context.dispatch(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES);
} }
addGuidToLineItemsIfNotAlreadyThere(parts);
context.commit(storeMutations.UPDATE_GLASS_PARTS, parts); context.commit(storeMutations.UPDATE_GLASS_PARTS, parts);
}, },
@ -2277,21 +2453,55 @@ function convertGlassPieceNamingFromApi(glassArray) {
} }
function addPricesToLineItems(lineItems, pricingLineItems) { function addPricesToLineItems(lineItems, pricingLineItems) {
lineItems.forEach((lineItem) => { const pricedLineItems = deepClone(lineItems);
pricedLineItems.forEach((lineItem) => {
let lineItemIndex = pricingLineItems.findIndex( let lineItemIndex = pricingLineItems.findIndex(
(pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber (pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber
); );
if (lineItem.childParts) { if (lineItem.childParts) {
addPricesToLineItems(lineItem.childParts, pricingLineItems); addPricesToLineItems(lineItem.childParts, pricingLineItems);
} }
let pricedLineItem = pricingLineItems.splice(lineItemIndex, 1)[0]; let pricedLineItem = pricingLineItems.splice(lineItemIndex, 1)[0];
lineItem.laborAmount = pricedLineItem.laborAmount; lineItem.laborAmount = pricedLineItem.laborAmount;
lineItem.sellingPrice = pricedLineItem.sellingPrice; lineItem.sellingPrice = pricedLineItem.sellingPrice;
lineItem.kitPrice = pricedLineItem.kitPrice; lineItem.kitPrice = pricedLineItem.kitPrice;
}); });
return pricedLineItems;
}
function addTaxesToPricedLineItems(lineItems, taxingLineItems) {
lineItems.forEach((lineItem) => {
let lineItemIndex = taxingLineItems.findIndex(
(taxingLineItem) => taxingLineItem.partNumber === lineItem.partNumber
);
if (lineItem.childParts) {
addTaxesToPricedLineItems(lineItem.childParts, taxingLineItems);
}
let taxedLineItem = taxingLineItems.splice(lineItemIndex, 1)[0];
lineItem.SalesTax = taxedLineItem.SalesTax;
});
return lineItems; return lineItems;
} }
function getArrayOfAllLineItems(lineItems) {
let consolidatedLineItemsArray = [];
if (lineItems.glassParts != null)
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.glassParts];
if (lineItems.supportingItems != null)
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.supportingItems];
if (lineItems.vaps != null)
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.vaps];
if (lineItems.promos != null)
consolidatedLineItemsArray = [...consolidatedLineItemsArray, ...lineItems.promos];
return consolidatedLineItemsArray;
}
function getFlattenedArrayOfLineItemsWithChildParts(lineItems) { function getFlattenedArrayOfLineItemsWithChildParts(lineItems) {
let flattenedArray = []; let flattenedArray = [];
lineItems?.forEach((lineItem) => { lineItems?.forEach((lineItem) => {
@ -2326,6 +2536,37 @@ function convertGlassPieceToBackEndCompatibleFormat(glassPieces) {
}); });
} }
function renameGlassToReplaceAttributes(glassToReplace) {
let newGlassToReplace = [];
if (glassToReplace) {
glassToReplace.forEach((item) => {
newGlassToReplace.push({ location: item.glassLocation, name: item.glassName });
});
}
return newGlassToReplace;
}
function addGuidToLineItemsIfNotAlreadyThere(lineItems) {
lineItems.forEach((lineItem) => {
if (!lineItem.id) {
lineItem.id = crypto.randomUUID();
}
});
}
function syncLineItemIds(lineItemsWithoutIds, lineItemsWithIds) {
if (!lineItemsWithIds || !lineItemsWithoutIds) {
return;
}
lineItemsWithoutIds.forEach((noId) => {
lineItemsWithIds.forEach((withId) => {
if (noId.partNumber === withId.partNumber && noId.partType === withId.partType) {
noId.id = withId.id;
}
});
});
}
function providersEqual(providerA, providerB) { function providersEqual(providerA, providerB) {
return ( return (
providerA.providerNumber === providerB.providerNumber && providerA.providerNumber === providerB.providerNumber &&

View file

@ -9,6 +9,8 @@ import { AppointmentTypeStrings } from "@/constants/schedule-constants";
// Mock global method // Mock global method
globalMethods.callHttpClient = jest.fn(); globalMethods.callHttpClient = jest.fn();
global.crypto = { randomUUID: jest.fn() };
describe("Mutations", () => { describe("Mutations", () => {
it("Updates vehicle year in state", () => { it("Updates vehicle year in state", () => {
// Arrange // Arrange
@ -1378,6 +1380,8 @@ describe("Actions", () => {
state: state, state: state,
}; };
context.state.order.lineItems = [];
const commit = jest.fn(); const commit = jest.fn();
const dispatch = jest.fn(); const dispatch = jest.fn();
@ -1385,10 +1389,10 @@ describe("Actions", () => {
context.dispatch = dispatch; context.dispatch = dispatch;
// Act // Act
actions.saveGlassParts(context, { glassParts: {} }); actions.saveGlassParts(context, []);
// Assert // Assert
expect(commit).toBeCalledWith(storeMutations.UPDATE_GLASS_PARTS, { glassParts: {} }); expect(commit).toBeCalledWith(storeMutations.UPDATE_GLASS_PARTS, []);
expect(dispatch).toBeCalledWith(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES); expect(dispatch).toBeCalledWith(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES);
}); });
@ -1417,7 +1421,7 @@ describe("Actions", () => {
state: { state: {
order: { order: {
lineItems: { lineItems: {
supportingItems: ["TestValue1", "TestValue2"], supportingItems: [{ partNum: "TestValue1" }, { partNum: "TestValue2" }],
}, },
}, },
}, },
@ -1430,7 +1434,11 @@ describe("Actions", () => {
context.dispatch = dispatch; context.dispatch = dispatch;
// Act // Act
actions.saveSupportingItems(context, ["TestValue3", "TestValue4", "TestValue5"]); actions.saveSupportingItems(context, [
{ partNum: "TestValue3" },
{ partNum: "TestValue4" },
{ partNum: "TestValue5" },
]);
// Assert // Assert
expect(dispatch).toBeCalledWith(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES); expect(dispatch).toBeCalledWith(storeActions.RESET_SERVICE_LOCATION_STATE_AND_DEPENDENCIES);
@ -1442,7 +1450,7 @@ describe("Actions", () => {
state: { state: {
order: { order: {
lineItems: { lineItems: {
supportingItems: ["TestValue1", "TestValue2"], supportingItems: [{ partNum: "TestValue1" }, { partNum: "TestValue2" }],
}, },
}, },
}, },
@ -1455,7 +1463,10 @@ describe("Actions", () => {
context.dispatch = dispatch; context.dispatch = dispatch;
// Act // Act
actions.saveSupportingItems(context, ["TestValue1", "TestValue2"]); actions.saveSupportingItems(context, [
{ partNum: "TestValue1" },
{ partNum: "TestValue2" },
]);
// Assert // Assert
expect(dispatch).not.toBeCalledWith( expect(dispatch).not.toBeCalledWith(