Merge branch 'develop' into feature/CASH-286

This commit is contained in:
CarlNation 2025-02-24 09:44:00 -05:00
commit 7b8af8dbf6
12 changed files with 203 additions and 102 deletions

View file

@ -258,7 +258,7 @@ export default {
min-height: 52px;
max-height: 126px;
@include media-breakpoint-up(md) {
max-height: 500px;
max-height: 500px;
}
transition: max-height 0.25s ease-in;

View file

@ -361,13 +361,16 @@ export default {
if (!this.customerQuestions.emailOrSms) {
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
}
else {
} else {
if (vinPagesMixin.methods.isPhoneNumber(this.customerQuestions.emailOrSms)) {
const phone = this.customerQuestions.emailOrSms.replace(/[()]/g, "");
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
} else {
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.customerQuestions.emailOrSms, false);
await this.dispatchStoreAction(
storeActions.SAVE_EMAIL,
this.customerQuestions.emailOrSms,
false
);
}
}

View file

@ -1,105 +1,102 @@
import { shallowMount } from '@vue/test-utils';
import InsuranceCompany from '@/layouts/insurance-company/insurance-company.vue';
import { applicationConfig } from '@/constants/application-config.js';
import { shallowMount } from "@vue/test-utils";
import InsuranceCompany from "@/layouts/insurance-company/insurance-company.vue";
import { applicationConfig } from "@/constants/application-config.js";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
jest.mock('@/store', () => ({
jest.mock("@/store", () => ({
getters: {
order: {
payment: {
parentAccountNumber: '12345',
order: {
payment: {
parentAccountNumber: "12345",
},
},
},
},
}));
}));
var mockRouter = {
navigateWithoutSaving: jest.fn(),
};
};
jest.mock('@/mixins/base-mixin.js', () => ({
jest.mock("@/mixins/base-mixin.js", () => ({
methods: {
navigateWithoutSaving: jest.fn(),
navigateWithoutSaving: jest.fn(),
},
data() {
return {
navigationScenarios: {
CLICKED_BACK: 'clicked_back',
},
};
return {
navigationScenarios: {
CLICKED_BACK: "clicked_back",
},
};
},
}));
}));
describe("insurance-company.vue", () => {
beforeEach(() => {
// Reset the store's parentAccountNumber before each test
store.getters.order.payment.parentAccountNumber = '12345';
});
store.getters.order.payment.parentAccountNumber = "12345";
});
test('should return true when parentAccountNumber matches CASH_PARENT_ACCOUNT_NUMBER', () => {
test("should return true when parentAccountNumber matches CASH_PARENT_ACCOUNT_NUMBER", () => {
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER = "12345";
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store
},
},
});
expect(wrapper.vm.isCashParentAccountNumber()).toBe(true);
});
test('should return false when parentAccountNumber does not match CASH_PARENT_ACCOUNT_NUMBER', () => {
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER = "12345";
store.getters.order.payment.parentAccountNumber = '67890';
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store,
},
},
});
expect(wrapper.vm.isCashParentAccountNumber()).toBe(false);
});
test('should call navigateWithoutSaving with { isCashSelected: true } when forceCashSelection is true', () => {
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store,
$router: mockRouter,
},
mixins: [baseMixin],
mocks: {
$store: store,
},
},
});
});
expect(wrapper.vm.isCashParentAccountNumber()).toBe(true);
});
test("should return false when parentAccountNumber does not match CASH_PARENT_ACCOUNT_NUMBER", () => {
applicationConfig.CASH_PARENT_ACCOUNT_NUMBER = "12345";
store.getters.order.payment.parentAccountNumber = "67890";
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store,
},
},
});
expect(wrapper.vm.isCashParentAccountNumber()).toBe(false);
});
test("should call navigateWithoutSaving with { isCashSelected: true } when forceCashSelection is true", () => {
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store,
$router: mockRouter,
},
mixins: [baseMixin],
},
});
wrapper.vm.backButtonAction(true);
expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith(
wrapper.vm.navigationScenarios.CLICKED_BACK,
wrapper.vm.$route,
{ isCashSelected: true }
wrapper.vm.navigationScenarios.CLICKED_BACK,
wrapper.vm.$route,
{ isCashSelected: true }
);
});
test('should call navigateWithoutSaving with no extra parameter when forceCashSelection is false', () => {
});
test("should call navigateWithoutSaving with no extra parameter when forceCashSelection is false", () => {
const wrapper = shallowMount(InsuranceCompany, {
global: {
mocks: {
$store: store,
$router: mockRouter,
mocks: {
$store: store,
$router: mockRouter,
},
mixins: [baseMixin],
},
mixins: [baseMixin],
},
});
});
wrapper.vm.backButtonAction(false);
expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith(
wrapper.vm.navigationScenarios.CLICKED_BACK,
wrapper.vm.$route
wrapper.vm.navigationScenarios.CLICKED_BACK,
wrapper.vm.$route
);
});
});
});

View file

@ -315,8 +315,7 @@ export default {
if (!this.emailOrSms) {
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
}
else {
} else {
if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
const phone = this.emailOrSms.replace(/[()]/g, "");
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);

View file

@ -59,6 +59,9 @@ jest.mock("@/mixins/base-mixin", () => ({
filterOutFees(items) {
return null;
},
filterOutServicePackageDiscountPart(items) {
return null;
},
isFormValid(form) {
return true;
},

View file

@ -361,16 +361,28 @@ export default {
)
: baseMixin.methods.filterOutFees(availableLineItems);
const lineItemsNoDiscount =
baseMixin.methods.filterOutServicePackageDiscountPart(
lineItemsForCalculatingPrice
);
if (isInsuranceFromQueryString != null) {
if (isInsuranceFromQueryString.toLowerCase() === "true") {
return true;
}
}
return (
baseMixin.methods.getTierOnePackagePrice(lineItemsForCalculatingPrice) >
insuranceThreshold
); // compare base price vs arbitrary threshold (representing insurance price)
const tierOnePrice =
baseMixin.methods.getTierOnePackagePrice(lineItemsNoDiscount);
// prettier-ignore
{
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + " quote tierOnePrice comparison: " + tierOnePrice + " > " + insuranceThreshold + "=" + (tierOnePrice > insuranceThreshold));
}
}
// compare base price vs arbitrary threshold (representing insurance price)
return tierOnePrice > insuranceThreshold;
}
return null;
@ -397,6 +409,12 @@ export default {
}
if (isExternalParameter === externalParameterStatus.NOT_SET) {
// prettier-ignore
{
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select EXTERNAL not set");
}
}
// there are no active or inactive external parameters; use internal threshold
if (internalThreshold) thresholdToUse = internalThreshold;
@ -408,6 +426,13 @@ export default {
} else {
// user came from an external source, however, the externalParms may have been reset on service-zip, property-questions, etc...
if (getBoolFromString(store.getters.externalParameterQuote?.isInsurance)) {
// prettier-ignore
{
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select EXTERNAL ISINSURANCE");
}
}
// did user intentionally select insurance?
vm.isInsuranceSelected = true;
vm.servicePackage = store.getters.externalParameterQuote.servicePackage;
@ -427,6 +452,13 @@ export default {
} else {
if (externalThreshold) thresholdToUse = externalThreshold;
// prettier-ignore
{
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + "quote.vue tab select NOT EXTERNAL");
}
}
vm.isInsuranceSelected = getIsInsuranceSelectedValue(
vm.availableLineItems,
thresholdToUse

View file

@ -18,6 +18,11 @@ import { nextTick } from "vue";
jest.mock("@/store", () => ({
commit: jest.fn(),
dispatch: jest.fn(),
getters: {
applicationUser: {
loggingOption: false,
},
},
}));
const mockExperimentSettings = experimentSettings;
@ -846,6 +851,7 @@ function setupMocks({ mountOptionsMockData, props = mockProps }) {
},
},
};
mountOptionsMockData = Object.assign(mountOptionsMockDataDefault, mountOptionsMockData);
const mountOptions = getMountOptions(mountOptionsMockData);

View file

@ -6,7 +6,7 @@ export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
return null;
}
const zipCodeData = await baseMixin.methods.getZipCodeData(serviceZipCode, pageNameToLog);
const zipCodeData = await getZipCodeData(serviceZipCode);
// Get the Mobile Fee Part
const mobileFeePart = await baseMixin.methods.dispatchStoreActionWithLogging(
@ -103,3 +103,7 @@ export async function getAvailabilityRating(
return shopStatus;
}
export async function getZipCodeData(serviceZipCode) {
return await baseMixin.methods.getZipCodeData(serviceZipCode, "service-location");
}

View file

@ -69,6 +69,15 @@ jest.mock(
getShopProviderData: jest.fn((mockServiceZipCode) => {
return mockGetShopProviderData(mockServiceZipCode);
}),
getZipCodeData: jest.fn().mockImplementation(() => {
return Promise.resolve({
containsMilitaryBase: false,
isServiceable: true,
isValid: true,
state: "testState",
zipCodeCtu: "testCTU",
});
}),
})
);
@ -424,6 +433,7 @@ describe("service-location.vue", () => {
},
selectedAppointmentType: "Mobile",
providerData: { mobileProviderNumber: "01820" },
isGlassServiceableMobile: true,
});
const mobileLocationQuestionsComponent = wrapper.findComponent({
@ -459,6 +469,7 @@ describe("service-location.vue", () => {
isVehicleProtected: true,
};
wrapper.vm.closeModalAction = jest.fn();
// Act
// Trigger the event
@ -483,6 +494,7 @@ describe("service-location.vue", () => {
},
selectedAppointmentType: "Mobile",
providerData: { mobileProviderNumber: "01820" },
isGlassServiceableMobile: true,
});
const mobileLocationQuestionsComponent = wrapper.findComponent({
@ -532,6 +544,7 @@ describe("service-location.vue", () => {
zipCodeCtu: "01526",
};
wrapper.vm.closeModalAction = jest.fn();
// Act
// Trigger the event
@ -563,6 +576,7 @@ describe("service-location.vue", () => {
});
mobileLocationQuestionsComponent.resetComponent = jest.fn();
wrapper.vm.forwardButtonAction = jest.fn();
wrapper.vm.isServiceableMobile = true;
const serviceZipCodeComponent = wrapper.findComponent({
ref: "serviceZipCodeQuestion",
@ -580,6 +594,7 @@ describe("service-location.vue", () => {
isVehicleProtected: "YesAnswer",
};
wrapper.vm.closeModalAction = jest.fn();
// Act
mobileLocationQuestionsComponent.vm.$emit(
"setMobileLocationAndProceed",

View file

@ -149,6 +149,7 @@ import {
getPricedMobileFeePart,
getServiceabilityDetails,
getShopProviderData,
getZipCodeData,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { applicationConfig } from "@/constants/application-config";
@ -206,10 +207,7 @@ export default {
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
const zipCodeDataPromise = baseMixin.methods.getZipCodeData(
serviceZipCode,
"service-location"
);
const zipCodeDataPromise = getZipCodeData(serviceZipCode);
const serviceabilityDetailsPromise = getServiceabilityDetails(
serviceZipCode,
@ -475,17 +473,31 @@ export default {
},
//creating async function as the computed property can not directly handle asynchronous operations or promises.
async setMobileLocationQuestions(newValue) {
if (newValue.addressQuestions.zipCode !== this.zipCode) {
await getShopProviderData(newValue.addressQuestions.zipCode).then((result) => {
this.shopProviderData = result.data;
this.selectedProvider = new Provider(
this.shopProviderData.mobileProviderNumber
);
var newZipCode = newValue.addressQuestions.zipCode;
if (newZipCode !== this.zipCode) {
await getShopProviderData(newZipCode).then((result) => {
if (this.isServiceableMobile) {
this.shopProviderData = result.data;
this.selectedProvider = new Provider(
this.shopProviderData.mobileProviderNumber
);
}
});
}
if (this.isServiceableMobile) {
this.setMobileLocation(newValue);
//proceed to next page
this.forwardButtonAction();
} else {
this.closeModalAction("mobileLocationQuestions");
await getZipCodeData(newZipCode).then((zipCodeData) => {
this.serviceZipCodeQuestion = {
state: zipCodeData.state,
zipCode: newZipCode,
zipCodeCtu: zipCodeData.zipCodeCtu,
};
});
}
this.setMobileLocation(newValue);
//proceed to next page
this.forwardButtonAction();
},
getServiceAddressFromStore() {
return store.getters.order.serviceLocation.address;
@ -669,6 +681,9 @@ export default {
openModalAction(modalName) {
this.$refs[modalName].openModal();
},
closeModalAction(modalName) {
this.$refs[modalName].closeModal();
},
},
watch: {
zipCode: {

View file

@ -334,13 +334,20 @@ export default {
if (!this.emailOrSms) {
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
}
else {
} else {
if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
const phone = this.emailOrSms.replace(/[()]/g, "");
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
await this.dispatchStoreAction(
storeActions.SAVE_PHONE_NUMBER,
phone,
false
);
} else {
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
await this.dispatchStoreAction(
storeActions.SAVE_EMAIL,
this.emailOrSms,
false
);
}
}
@ -391,13 +398,20 @@ export default {
if (!this.emailOrSms) {
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false);
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false);
}
else {
} else {
if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) {
const phone = this.emailOrSms.replace(/[()]/g, "");
await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false);
await this.dispatchStoreAction(
storeActions.SAVE_PHONE_NUMBER,
phone,
false
);
} else {
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false);
await this.dispatchStoreAction(
storeActions.SAVE_EMAIL,
this.emailOrSms,
false
);
}
}

View file

@ -92,6 +92,13 @@ export default {
});
let totalPrice = this.getTotalPriceOfAllLineItemsAndChildParts(lineItemsToPrice, false);
// prettier-ignore
{
if (store.getters.applicationUser.loggingOption) {
console.log(new Date() + " base-mixin getTierOnePackagePrice lineItemsToPrice: " + JSON.stringify(lineItemsToPrice));
console.log(new Date() + " base-mixin getTierOnePackagePrice totalPrice: " + totalPrice);
}
}
return totalPrice;
},
filterOutFees(lineItems) {
@ -103,6 +110,12 @@ export default {
});
return filteredLineItems;
},
filterOutServicePackageDiscountPart(lineItems) {
const filteredLineItems = lineItems?.filter((item) => {
return !item?.partType?.includes(partTypeStrings.SERVICE_PACKAGE_DISCOUNT);
});
return filteredLineItems;
},
filterOutRecalibration(lineItems) {
return getItemsWithoutRecalParts(lineItems);
},