diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index ee0eee749..003d28b0d 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -33,7 +33,8 @@
class="small mt-4"
v-model="lineItems"
:availableVaps="availableVaps"
- pageName="payment-method"
+ :taxPromos="taxPromos"
+ :pageName="payment - method"
modalWidgetName="PromoModalWidget" />
@@ -309,6 +310,7 @@ export default {
return {
lineItems: [],
availableVaps: [],
+ taxPromos: true,
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
inactivePromos: this.getInactivePromosFromStore(),
};
diff --git a/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js b/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
index 16d170e82..1dcc2ac70 100644
--- a/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
+++ b/src/layouts/payment-method/promo-modal-question/promo-modal-question.spec.js
@@ -1,5 +1,25 @@
import { mount, shallowMount } from "@vue/test-utils";
import promoModalQuestion from "./promo-modal-question";
+import { storeActions } from "@/constants/store-actions";
+import baseMixin from "@/mixins/base-mixin.js";
+
+let mockReturnsForStoreActions = {};
+
+jest.mock("@/mixins/base-mixin", () => ({
+ ...jest.requireActual("@/mixins/base-mixin"),
+ methods: {
+ dispatchStoreActionWithLogging: jest.fn(
+ (action, { promoCode, addableVaps }, pageNameToLog, someBool) => {
+ return mockReturnsForStoreActions[action];
+ }
+ ),
+ },
+}));
+
+afterEach(() => {
+ // reset store action returns
+ mockReturnsForStoreActions = {};
+});
jest.mock("@/digital-components/textbox-question/textbox-question", () => ({
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
@@ -79,4 +99,127 @@ describe("promo-modal-question.vue", () => {
// Assert
expect(wrapper.emitted("update:modelValue")).toEqual([[lineItems]]);
});
+ it("focuses on the input element when focusOnPromoInput is called", async () => {
+ // Arrange
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+ attachTo: document.body,
+ });
+ const focusMock = jest.fn();
+ const inputMock = { focus: focusMock };
+
+ // Mock document.getElementById to return the inputMock
+ jest.spyOn(document, "getElementById").mockReturnValue(inputMock);
+
+ //Act
+
+ wrapper.vm.focusOnPromoInput();
+ await wrapper.vm.$nextTick();
+
+ //Assert
+ expect(focusMock).toHaveBeenCalled();
+ });
+ it("returns a validate response on applying promo", async () => {
+ // Arrange
+ const newPromo = "testPromo";
+ const pageNameToLog = "testPage";
+ const validateResponse = { orderPromos: [] };
+ const addableVaps = [];
+ mockReturnsForStoreActions[storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA] =
+ validateResponse;
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+ attachTo: document.body,
+ });
+ // Act
+
+ wrapper.vm.getPromoCodeData();
+
+ const promoValidationResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
+ storeActions.VALIDATE_ORDER_PROMO_AND_SAVE_SERVER_DATA,
+ {
+ newPromo,
+ lineItems,
+ addableVaps,
+ },
+ pageNameToLog,
+ false
+ );
+
+ // Assert
+ expect(promoValidationResponse).toEqual(validateResponse);
+ });
+ test("If promocode is valid return taxed lineItems", async () => {
+ //Arrange
+ const taxedlineItems = {};
+
+ mockReturnsForStoreActions[storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA] =
+ taxedlineItems;
+
+ const lineItems = {
+ glassParts: [],
+ supportingItems: [],
+ vaps: [],
+ promos: [],
+ };
+
+ let promoCode = "1wiper0";
+ const pricedLineItemsToTax = [];
+
+ pricedLineItemsToTax.push(promoCode);
+ const wrapper = mount(promoModalQuestion, {
+ mixins: [mockMixin],
+
+ props: {
+ modelValue: lineItems,
+ modalWidgetName: modalWidgetName,
+ },
+
+ attachTo: document.body,
+ });
+ wrapper.vm.addPromoCode();
+
+ const taxedLineItems = await baseMixin.methods.dispatchStoreActionWithLogging(
+ storeActions.TAX_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
+ {
+ billToAccountNumber: "87291",
+ providerNumber: 2,
+ appointmentType: "IN_SHOP",
+ serviceLocationCity: "city",
+ serviceLocationState: "state",
+ serviceLocationZipCode: "12345",
+ pricedLineItems: pricedLineItemsToTax,
+ },
+
+ "payment-method",
+
+ false
+ );
+
+ // Assert
+
+ expect(taxedLineItems).toEqual(taxedlineItems);
+ });
});
diff --git a/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue b/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
index a68ff4dbe..ede99df1a 100644
--- a/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
+++ b/src/layouts/payment-method/promo-modal-question/promo-modal-question.vue
@@ -101,6 +101,7 @@ export default {
modalWidgetName: String,
availableVaps: Object,
pageName: String,
+ taxPromos: Boolean,
},
computed: {
promoLinkText() {
@@ -258,7 +259,7 @@ export default {
);
if (promoCodeData.isValid) {
- if (this.pageName == "payment-method") {
+ if (this.taxPromos) {
const pricedLineItemsToTax = [];
pricedLineItemsToTax.push(...promoCodeData.promoCode);
const taxedLineItems =
diff --git a/src/layouts/quote/quote.spec.js b/src/layouts/quote/quote.spec.js
index fc9b4c4eb..4a0814acd 100644
--- a/src/layouts/quote/quote.spec.js
+++ b/src/layouts/quote/quote.spec.js
@@ -4,6 +4,8 @@ import { applicationConfig } from "@/constants/application-config";
import { storeActions } from "@/constants/store-actions";
import quote from "@/layouts/quote/quote.vue";
import store from "@/store";
+import promotionsHelper from "@/helpers/promotions-helper";
+import baseMixin from "@/mixins/base-mixin.js";
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
import { nextTick } from "vue";
@@ -133,8 +135,6 @@ describe("quote.vue", () => {
};
});
- wrapper.vm.pricedGlassParts = [];
-
//Act
await wrapper.vm.forwardButtonAction();
@@ -250,9 +250,8 @@ describe("quote.vue", () => {
);
//Assert
- expect(wrapper.vm.pricedGlassParts !== null).toBe(true);
- expect(wrapper.vm.supportingItems !== null).toBe(true);
expect(wrapper.vm.availableLineItems !== null).toBe(true);
+ expect(wrapper.vm.availableVaps !== null).toBe(true);
// This should have its own test
//expect(vm.isInsuranceSelected !== null).toBe(true);
});
@@ -510,6 +509,31 @@ describe("quote.vue", () => {
//Assert
expect(wrapper.vm.isInsuranceSelected).toBe(true);
});
+ test("On forward button action save promos", async () => {
+ //Arrange
+ store.getters.payment = {
+ insuranceCoverage: {},
+ isInsurance: false,
+ };
+ store.getters.order = {
+ lineItems: [],
+ payment: {
+ parentAccountNumber: 167132,
+ },
+ };
+ const { wrapper } = setupMocks({
+ customMountOptions: {
+ router: {
+ navigateWithSaving: jest.fn(),
+ },
+ route: { quote },
+ },
+ });
+
+ wrapper.vm.forwardButtonAction();
+
+ expect(wrapper.vm.lineItems.promos !== null).toBe(true);
+ });
});
function setupMocks({ customMountOptions }) {
diff --git a/src/layouts/quote/quote.vue b/src/layouts/quote/quote.vue
index ff552ee82..257d953e7 100644
--- a/src/layouts/quote/quote.vue
+++ b/src/layouts/quote/quote.vue
@@ -98,8 +98,6 @@ import {
revalidatePromosAndValidateQueryStringPromo,
buildToastMessagesFromRevalidateOrValidatePromoResponse,
createPromoSuccessAlert,
- createPromoErrorAlert,
- getNewlyInactivatedPromos,
} from "@/helpers/promotions-helper";
import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper";
@@ -151,7 +149,8 @@ export default {
];
const resultMap = await settleAllPromises(promiseResultMap);
- const nullSafeGlassParts = store.getters.order.lineItems.glassParts ?? [];
+ const lineItems = store.getters.order.lineItems;
+ const nullSafeGlassParts = lineItems.glassParts ?? [];
const availableLineItems = [
resultMap.rainDefense,
...resultMap.supportingItems,
@@ -189,7 +188,6 @@ export default {
"quote"
);
- const lineItems = store.getters.order.lineItems;
lineItems.promos = lineItems.promos ?? [];
lineItems.vaps = lineItems.vaps ?? [];
// End of promo logic
@@ -197,8 +195,6 @@ export default {
// Call the "next" function to complete the transition to this page.
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
- vm.pricedGlassParts = nullSafeGlassParts;
- vm.supportingItems = resultMap.supportingItems;
vm.availableLineItems = pricingResults;
vm.availableVaps = availableVaps;
vm.lineItems = lineItems;
@@ -227,12 +223,9 @@ export default {
data() {
return {
isInsuranceSelected: null,
- selectedVaps: null,
availableLineItems: null,
- supportingItems: null,
- pricedGlassParts: null,
- lineItems: [],
availableVaps: [],
+ lineItems: [],
};
},
computed: {
@@ -282,30 +275,7 @@ export default {
}
},
vapsItemsSelectedAction(vapsItemsSelected) {
- this.selectedVaps = vapsItemsSelected;
- },
- async revalidatePromos() {
- this.$refs.loadingModal.showModal();
- const revalidatePromoResponse = await baseMixin.methods.dispatchStoreActionWithLogging(
- storeActions.REVALIDATE_ORDER_PROMOS_AND_SAVE_SERVER_DATA,
- {
- activePromosToUse: this.lineItems.promos,
- inactivePromosToUse: this.$store.getters.order.payment.inactivePromos,
- lineItemsToUse: this.lineItems,
- },
- "quote",
- false
- );
- // Handle error alerts here, success alerts are handled in the watcher
- if (revalidatePromoResponse.errors.length) {
- getNewlyInactivatedPromos(
- this.inactivePromos,
- revalidatePromoResponse.errors
- ).forEach((promoCode) => {
- const errorAlert = createPromoErrorAlert(promoCode);
- this.$refs.funnelHeader.pushGlobalAlert(errorAlert, errorAlert.shouldAutoFade);
- });
- }
+ this.lineItems.vaps = vapsItemsSelected;
},
backButtonAction() {
vehicleQuestionsMixin.methods.navigateBack(this);
@@ -329,18 +299,18 @@ export default {
this.$store.getters.order.payment.parentAccountNumber !=
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER
) {
- this.supportingItems = this.filterOutFees(this.supportingItems);
+ this.lineItems.supportingItems = this.filterOutFees(this.lineItems.supportingItems);
}
- if (this.pricedGlassParts.length > 0) {
+ if (this.lineItems.glassParts?.length > 0) {
this.dispatchStoreAction(
this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
- this.pricedGlassParts,
+ this.lineItems.glassParts,
false
);
}
- this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false);
+ this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false);
this.dispatchStoreAction(
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
{
@@ -385,11 +355,6 @@ export default {
);
const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode);
this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade);
- } else if (
- oldValue.promos.length == newValue.promos.length &&
- oldValue.vaps.length != newValue.vaps.length
- ) {
- this.revalidatePromos();
}
},
deep: true,
diff --git a/src/layouts/quote/service-package-question/service-package-question.spec.js b/src/layouts/quote/service-package-question/service-package-question.spec.js
index c156ef34c..8163c6324 100644
--- a/src/layouts/quote/service-package-question/service-package-question.spec.js
+++ b/src/layouts/quote/service-package-question/service-package-question.spec.js
@@ -256,6 +256,57 @@ describe("service-package-question.vue", () => {
// Assert
expect(wrapper.vm.selectedPackageName).toBe("TierThree");
});
+ it("should select default package if promos are added", async () => {
+ //Arrange
+ mockProps.activePromos != null;
+ const wrapper = setupMocks({
+ mountOptionsMockData: {
+ store: {
+ getters: {
+ order: {
+ damage: {
+ isRepair: false,
+ glassToReplace: [{ glassLocation: "Windshield" }],
+ },
+ },
+ lineItems: {
+ vaps: [],
+ },
+ hasAnyNonWindshieldGlassParts: false,
+ payment: {
+ isInsurance: false,
+ },
+ },
+ },
+ },
+ });
+
+ //Act
+ wrapper.setProps({
+ activePromos: [
+ {
+ discountedLineItemIds: [
+ {
+ 0: "428ec73c-38e4-4e14-8703-a987b0391898",
+ 1: "79db94d7-163c-4408-a1ec-f83e58c11992",
+ },
+ ],
+ partType: "PROMO_DISCOUNT",
+ promoCode: "1WIPER0",
+ partNumber: "WIPER DISCOUNT",
+ laborAmount: 0,
+ sellingPrice: -10,
+ kitPrice: 0,
+ salesTax: null,
+ },
+ ],
+ });
+ const selectDefaultPackageMock = jest.spyOn(wrapper.vm, "selectDefaultPackage");
+ await nextTick();
+
+ //Assert
+ expect(selectDefaultPackageMock).toHaveBeenCalled();
+ });
});
describe("service-package-question.vue, matching business rules for package display", () => {
// mock scenarios in figma: