Merge pull request #1733 from Safelite/feature/CSR-1764.1

CSR-1764
This commit is contained in:
AMSNEHA 2024-02-09 19:29:50 +05:30 committed by GitHub
commit 62bc6f50d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 237 additions and 48 deletions

View file

@ -1,5 +1,25 @@
import { mount, shallowMount } from "@vue/test-utils"; import { mount, shallowMount } from "@vue/test-utils";
import promoModalQuestion from "./promo-modal-question"; 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", () => ({ jest.mock("@/digital-components/textbox-question/textbox-question", () => ({
getCmsContent: jest.fn((widgetName, cmsFieldName) => { getCmsContent: jest.fn((widgetName, cmsFieldName) => {
@ -79,4 +99,127 @@ describe("promo-modal-question.vue", () => {
// Assert // Assert
expect(wrapper.emitted("update:modelValue")).toEqual([[lineItems]]); 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);
});
}); });

View file

@ -101,6 +101,11 @@ export default {
modalWidgetName: String, modalWidgetName: String,
availableVaps: Object, availableVaps: Object,
pageName: String, pageName: String,
taxPromos: {
type: Boolean,
required: false,
default: true,
},
}, },
computed: { computed: {
promoLinkText() { promoLinkText() {
@ -258,7 +263,7 @@ export default {
); );
if (promoCodeData.isValid) { if (promoCodeData.isValid) {
if (this.pageName == "payment-method") { if (this.taxPromos) {
const pricedLineItemsToTax = []; const pricedLineItemsToTax = [];
pricedLineItemsToTax.push(...promoCodeData.promoCode); pricedLineItemsToTax.push(...promoCodeData.promoCode);
const taxedLineItems = const taxedLineItems =

View file

@ -4,6 +4,8 @@ import { applicationConfig } from "@/constants/application-config";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import quote from "@/layouts/quote/quote.vue"; import quote from "@/layouts/quote/quote.vue";
import store from "@/store"; 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 * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
import { nextTick } from "vue"; import { nextTick } from "vue";
@ -133,8 +135,6 @@ describe("quote.vue", () => {
}; };
}); });
wrapper.vm.pricedGlassParts = [];
//Act //Act
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
@ -250,9 +250,8 @@ describe("quote.vue", () => {
); );
//Assert //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.availableLineItems !== null).toBe(true);
expect(wrapper.vm.availableVaps !== null).toBe(true);
// This should have its own test // This should have its own test
//expect(vm.isInsuranceSelected !== null).toBe(true); //expect(vm.isInsuranceSelected !== null).toBe(true);
}); });
@ -510,6 +509,31 @@ describe("quote.vue", () => {
//Assert //Assert
expect(wrapper.vm.isInsuranceSelected).toBe(true); 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 }) { function setupMocks({ customMountOptions }) {

View file

@ -45,6 +45,7 @@
:availableVaps="availableVaps" :availableVaps="availableVaps"
:availableLineItems="availableLineItems" :availableLineItems="availableLineItems"
pageName="quote" pageName="quote"
:taxPromos="false"
modalWidgetName="PromoModalWidget" /> modalWidgetName="PromoModalWidget" />
<textBlock <textBlock
@ -98,8 +99,6 @@ import {
revalidatePromosAndValidateQueryStringPromo, revalidatePromosAndValidateQueryStringPromo,
buildToastMessagesFromRevalidateOrValidatePromoResponse, buildToastMessagesFromRevalidateOrValidatePromoResponse,
createPromoSuccessAlert, createPromoSuccessAlert,
createPromoErrorAlert,
getNewlyInactivatedPromos,
} from "@/helpers/promotions-helper"; } from "@/helpers/promotions-helper";
import { queryStrings } from "@/constants/query-strings"; import { queryStrings } from "@/constants/query-strings";
import { getQuerystringParameter } from "@/helpers/querystring-helper"; import { getQuerystringParameter } from "@/helpers/querystring-helper";
@ -151,7 +150,8 @@ export default {
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const nullSafeGlassParts = store.getters.order.lineItems.glassParts ?? []; const lineItems = store.getters.order.lineItems;
const nullSafeGlassParts = lineItems.glassParts ?? [];
const availableLineItems = [ const availableLineItems = [
resultMap.rainDefense, resultMap.rainDefense,
...resultMap.supportingItems, ...resultMap.supportingItems,
@ -189,7 +189,6 @@ export default {
"quote" "quote"
); );
const lineItems = store.getters.order.lineItems;
lineItems.promos = lineItems.promos ?? []; lineItems.promos = lineItems.promos ?? [];
lineItems.vaps = lineItems.vaps ?? []; lineItems.vaps = lineItems.vaps ?? [];
// End of promo logic // End of promo logic
@ -197,8 +196,6 @@ export default {
// 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 = nullSafeGlassParts;
vm.supportingItems = resultMap.supportingItems;
vm.availableLineItems = pricingResults; vm.availableLineItems = pricingResults;
vm.availableVaps = availableVaps; vm.availableVaps = availableVaps;
vm.lineItems = lineItems; vm.lineItems = lineItems;
@ -227,12 +224,9 @@ export default {
data() { data() {
return { return {
isInsuranceSelected: null, isInsuranceSelected: null,
selectedVaps: null,
availableLineItems: null, availableLineItems: null,
supportingItems: null,
pricedGlassParts: null,
lineItems: [],
availableVaps: [], availableVaps: [],
lineItems: [],
}; };
}, },
computed: { computed: {
@ -282,30 +276,7 @@ export default {
} }
}, },
vapsItemsSelectedAction(vapsItemsSelected) { vapsItemsSelectedAction(vapsItemsSelected) {
this.selectedVaps = vapsItemsSelected; this.lineItems.vaps = 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);
});
}
}, },
backButtonAction() { backButtonAction() {
vehicleQuestionsMixin.methods.navigateBack(this); vehicleQuestionsMixin.methods.navigateBack(this);
@ -329,18 +300,18 @@ export default {
this.$store.getters.order.payment.parentAccountNumber != this.$store.getters.order.payment.parentAccountNumber !=
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER 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.dispatchStoreAction(
this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING, this.storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
this.pricedGlassParts, this.lineItems.glassParts,
false false
); );
} }
this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.selectedVaps, false); this.dispatchStoreAction(this.storeActions.SAVE_VAPS, this.lineItems.vaps, false);
this.dispatchStoreAction( this.dispatchStoreAction(
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS, storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
{ {
@ -385,11 +356,6 @@ export default {
); );
const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode); const alert = createPromoSuccessAlert(newlyActivatedPromoCodes[0].promoCode);
this.$refs.funnelHeader.pushGlobalAlert(alert, alert.shouldAutoFade); 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, deep: true,

View file

@ -256,6 +256,57 @@ describe("service-package-question.vue", () => {
// Assert // Assert
expect(wrapper.vm.selectedPackageName).toBe("TierThree"); 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", () => { describe("service-package-question.vue, matching business rules for package display", () => {
// mock scenarios in figma: // mock scenarios in figma: