From 6772029d71aa7ec8ec3ff273eab05d737085dbe7 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 17 Feb 2025 15:34:01 -0500 Subject: [PATCH 1/9] CASH-153: put new datePicker behind DisplayPricingByDay experiment check --- src/constants/experiments.js | 1 + src/layouts/schedule/schedule.vue | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 92d27a4a1..d33d7d677 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -18,6 +18,7 @@ const experimentSettings = { INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold", INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold", DISPLAY_MSR: "DisplayMSR", + DISPLAY_PRICING_BY_DAY: "DisplayPricingByDay", }; const experimentTriggers = { diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 63a2d7d64..4902a1088 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -18,7 +18,18 @@ marginTopSizeOverride="1" /> + selectableDate.date === this.selectedDate ); }, + isPricingByDayExperiment() { + return ( + experimentMixin.methods + .getSettingValue(experimentSettings.DISPLAY_PRICING_BY_DAY) + ?.toLowerCase() === "true" + ); + }, }, methods: { splitCopyOnCMSPlaceHolder, @@ -537,6 +558,7 @@ export default { funnelSubHeader, Form, loadingModal, + datePicker, datePicker2, locationAlerts, timeSlotModalQuestion, From 023ae9cd51af20f5760150fd7c5b99bd916aa33a Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 17 Feb 2025 15:34:23 -0500 Subject: [PATCH 2/9] CASH-153: update unit test --- src/layouts/schedule/schedule.spec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/layouts/schedule/schedule.spec.js b/src/layouts/schedule/schedule.spec.js index 270da75f0..18e659ec5 100644 --- a/src/layouts/schedule/schedule.spec.js +++ b/src/layouts/schedule/schedule.spec.js @@ -7,6 +7,7 @@ import { getMountOptions } from "@/helpers/unit-test-helper.js"; import store from "@/store"; import router from "@/router"; import baseMixin from "../../mixins/base-mixin"; +import { experimentSettings } from "../../constants/experiments"; // Mock basemixin jest.mock("@/mixins/base-mixin.js", () => ({ @@ -177,6 +178,7 @@ beforeEach(() => { glassParts: [], supportingItems: [], }, + experimentSettings: {}, }; }); afterEach(() => { From 456f00653f67297400feacd2d999b6860f82fc10 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 17 Feb 2025 15:37:34 -0500 Subject: [PATCH 3/9] CASH-153: update with new experiment name --- src/layouts/schedule/schedule.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 4902a1088..304376377 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -318,7 +318,7 @@ export default { isPricingByDayExperiment() { return ( experimentMixin.methods - .getSettingValue(experimentSettings.DISPLAY_PRICING_BY_DAY) + .getSettingValue(experimentSettings.PRICING_BY_DAY) ?.toLowerCase() === "true" ); }, From 69c9c4576367619cb7a36cd5eed5a78058e52840 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Mon, 17 Feb 2025 15:46:01 -0500 Subject: [PATCH 4/9] CASH-153: move experiment datePicker into new prescribed folder --- .../date-picker => experiment-components}/date-picker-2.vue | 4 ++-- src/layouts/schedule/schedule.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/{digital-components/date-picker => experiment-components}/date-picker-2.vue (99%) diff --git a/src/digital-components/date-picker/date-picker-2.vue b/src/experiment-components/date-picker-2.vue similarity index 99% rename from src/digital-components/date-picker/date-picker-2.vue rename to src/experiment-components/date-picker-2.vue index 8becf6266..414f794e0 100644 --- a/src/digital-components/date-picker/date-picker-2.vue +++ b/src/experiment-components/date-picker-2.vue @@ -99,8 +99,8 @@ // Supporting files import loader from "@/ux-components/loader/loader"; import store from "@/store"; -import { TIMINGFUNC_MAP, BUFFER_OFFSET, MONTHS_OF_YEAR } from "./mixins/constants"; -import { selectableDaysOptions, requiredParameter, forceTwoDigitString } from "./mixins/helpers"; +import { TIMINGFUNC_MAP, BUFFER_OFFSET, MONTHS_OF_YEAR } from "@/digital-components/date-picker/mixins/constants"; +import { selectableDaysOptions, requiredParameter, forceTwoDigitString } from "@/digital-components/date-picker/mixins/helpers"; import { convertDateToDateString, convertDateStringToDate, diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index 304376377..0853664e2 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -81,7 +81,7 @@ import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-heade import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue"; import { Form, defineRule } from "vee-validate"; import datePicker from "@/digital-components/date-picker/date-picker"; -import datePicker2 from "@/digital-components/date-picker/date-picker-2"; +import datePicker2 from "@/experiment-components/date-picker-2"; import locationAlerts from "@/layouts/schedule/location-alerts/location-alerts"; import timeSlotModalQuestion from "./time-slot-modal-question/time-slot-modal-question"; import textBlock from "@/digital-components/text-block/text-block"; From 946c44a25117a6c6a54eb02f3f605a96ce6fba51 Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Tue, 18 Feb 2025 09:24:53 -0500 Subject: [PATCH 5/9] CASH-245 | Add insurance-company unit tests Renamed the file Built the necessary scaffolding to run tests wrote tests covering the pay on my own back button Wrote two other simple tests to help test the scaffolding --- .../insurance-company-spec.js | 3 - .../insurance-company.spec.js | 105 ++++++++++++++++++ 2 files changed, 105 insertions(+), 3 deletions(-) delete mode 100644 src/layouts/insurance-company/insurance-company-spec.js create mode 100644 src/layouts/insurance-company/insurance-company.spec.js diff --git a/src/layouts/insurance-company/insurance-company-spec.js b/src/layouts/insurance-company/insurance-company-spec.js deleted file mode 100644 index bd932b7d2..000000000 --- a/src/layouts/insurance-company/insurance-company-spec.js +++ /dev/null @@ -1,3 +0,0 @@ -describe("insurance-company.vue", () => { - it.todo("Some test for the future"); -}); diff --git a/src/layouts/insurance-company/insurance-company.spec.js b/src/layouts/insurance-company/insurance-company.spec.js new file mode 100644 index 000000000..b1297d13b --- /dev/null +++ b/src/layouts/insurance-company/insurance-company.spec.js @@ -0,0 +1,105 @@ +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', () => ({ + getters: { + order: { + payment: { + parentAccountNumber: '12345', + }, + }, + }, + })); + +var mockRouter = { + navigateWithoutSaving: jest.fn(), + }; + + jest.mock('@/mixins/base-mixin.js', () => ({ + methods: { + navigateWithoutSaving: jest.fn(), + }, + data() { + 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'; + }); + + 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], + }, + }); + + + wrapper.vm.backButtonAction(true); + expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith( + wrapper.vm.navigationScenarios.CLICKED_BACK, + wrapper.vm.$route, + { isCashSelected: true } + ); + }); + + test('should call navigateWithoutSaving with no extra parameter when forceCashSelection is false', () => { + const wrapper = shallowMount(InsuranceCompany, { + global: { + mocks: { + $store: store, + $router: mockRouter, + }, + mixins: [baseMixin], + }, + }); + wrapper.vm.backButtonAction(false); + expect(mockRouter.navigateWithoutSaving).toHaveBeenCalledWith( + wrapper.vm.navigationScenarios.CLICKED_BACK, + wrapper.vm.$route + ); + }); +}); From b2459ffcf69f1f89c0366bd208771b976fcb0e0c Mon Sep 17 00:00:00 2001 From: CarlNation Date: Tue, 18 Feb 2025 13:54:42 -0500 Subject: [PATCH 6/9] CASH-176 CASH-176 clear email/phone field on all pages, not just service zip --- src/layouts/address-lookup/address-lookup.vue | 21 +++++++----- .../license-plate-lookup.vue | 17 +++++++--- src/layouts/vin-lookup/vin-lookup.vue | 34 +++++++++++++------ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/layouts/address-lookup/address-lookup.vue b/src/layouts/address-lookup/address-lookup.vue index e069ee48d..08f602fb4 100644 --- a/src/layouts/address-lookup/address-lookup.vue +++ b/src/layouts/address-lookup/address-lookup.vue @@ -357,15 +357,18 @@ export default { false ); - 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 - ); + // if no value due to field being optional, blank both phone and email address + if (!this.customerQuestions.emailOrSms) { + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false); + } + 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( diff --git a/src/layouts/license-plate-lookup/license-plate-lookup.vue b/src/layouts/license-plate-lookup/license-plate-lookup.vue index e1b3f721e..6f6521dde 100644 --- a/src/layouts/license-plate-lookup/license-plate-lookup.vue +++ b/src/layouts/license-plate-lookup/license-plate-lookup.vue @@ -311,11 +311,18 @@ export default { false ); - if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { - const phone = this.emailOrSms.replace(/[()]/g, ""); - await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); - } else { - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + // if no value due to field being optional, blank both phone and email address + if (!this.emailOrSms) { + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false); + } + else { + if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { + const phone = this.emailOrSms.replace(/[()]/g, ""); + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); + } else { + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + } } await this.dispatchStoreAction( diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 82c54d43a..2c93e7182 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -330,11 +330,18 @@ export default { false ); - if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { - const phone = this.emailOrSms.replace(/[()]/g, ""); - await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); - } else { - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + // if no value due to field being optional, blank both phone and email address + if (!this.emailOrSms) { + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false); + } + else { + if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { + const phone = this.emailOrSms.replace(/[()]/g, ""); + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); + } else { + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + } } await this.dispatchStoreAction( @@ -380,11 +387,18 @@ export default { ); } - if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { - const phone = this.emailOrSms.replace(/[()]/g, ""); - await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); - } else { - await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + // if no value due to field being optional, blank both phone and email address + if (!this.emailOrSms) { + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, "", false); + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, "", false); + } + else { + if (vinPagesMixin.methods.isPhoneNumber(this.emailOrSms)) { + const phone = this.emailOrSms.replace(/[()]/g, ""); + await this.dispatchStoreAction(storeActions.SAVE_PHONE_NUMBER, phone, false); + } else { + await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailOrSms, false); + } } await this.dispatchStoreAction( From 72fd8d1a3cf37cdba8850d7bfc777b4abf7a3121 Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Wed, 19 Feb 2025 13:55:08 -0500 Subject: [PATCH 7/9] Rewrite GetRecalPartNumber(s) helper method --- src/helpers/recal-helper.js | 12 ++++++++++++ src/store/index.js | 24 +++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index c73755e8f..d43da5d34 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -58,3 +58,15 @@ export function getTopLevelPartsWithRecal(lineItems) { return lineItems.filter((li) => isRecalPartOrHasChildRecalPart(li)); } + +export function getRecalPartNumbers(glassPartsArray) { + if (glassPartsArray && glassPartsArray.length > 0) { + const topLevel = glassPartsArray.filter((gp) => isRecalPart(gp)).map((gp) => gp.partNumber); + + const children = glassPartsArray.map((gp) => getRecalPartNumbers(gp.childParts)).flat(); + + return [...topLevel, ...children]; + } else { + return []; + } +} diff --git a/src/store/index.js b/src/store/index.js index 03e8f339a..d52fea200 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -45,6 +45,7 @@ import { containsRecalParts, getTopLevelPartsWithRecal, isRecalPartOrHasChildRecalPart, + getRecalPartNumbers, } from "@/helpers/recal-helper"; import { externalParameterStatus } from "@/constants/external-parameters"; import { experimentSettings } from "@/constants/experiments"; @@ -1712,10 +1713,15 @@ export const actions = { var endPoint = `${endpoints.GetMobileFeePart.url}/?serviceType=${serviceType}&facilityType=${facilityType}&parentAccountNumber=${parentAccountNumber}&billToAccountNumber=${billToAccountNumber}&providerNumber=${providerNumber}&isItacOptimized=${isItacOptimized}&zipCode=${zipCode}`; - const recalPartNumber = getRecalPartNumber(order.lineItems?.glassParts[0]); + const recalPartNumbers = getRecalPartNumbers(order.lineItems?.glassParts); const carId = order.vehicle?.carId; - if (recalPartNumber && carId) { - endPoint = `${endPoint}&partNumbers=${recalPartNumber}&carId=${carId}`; + if (recalPartNumbers && recalPartNumbers.length > 0 && carId) { + let additionalQueryParams = ``; + for (let i = 0; i < recalPartNumbers.length; i++) { + additionalQueryParams += `&partNumbers[${i}]=4${recalPartNumbers[i]}`; + } + additionalQueryParams += `&carId=${carId}`; + endPoint += additionalQueryParams; } if (coverageStatus) { @@ -3760,15 +3766,3 @@ function getExternalParameterDefaultState() { function saveExternalParameterState(externalParameterState) { window.sessionStorage.setItem("externalParameterState", JSON.stringify(externalParameterState)); } - -//This function finds the recalibration part and returns the part number for it. -function getRecalPartNumber(glassPartsArray) { - const recalPart = glassPartsArray.childParts.find( - (item) => item.partType === partTypeStrings.ADAS_RECALIBRATION - ); - if (recalPart) { - return recalPart.partNumber; - } else { - return null; - } -} From bfec10131cda90f8ac358e30f104ced0940ae6c9 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Wed, 19 Feb 2025 14:05:55 -0500 Subject: [PATCH 8/9] CASH-151 CASH-151 style adjustment. only adjust the top spacing when not a service package discount package --- src/experiment-components/service-package-radio.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/experiment-components/service-package-radio.vue b/src/experiment-components/service-package-radio.vue index 8634250ab..a3bfd9937 100644 --- a/src/experiment-components/service-package-radio.vue +++ b/src/experiment-components/service-package-radio.vue @@ -5,6 +5,7 @@ :class="[ this.buttonLabelSubCopy ? 'has-subheader' : '', this.isInsuranceSelected ? 'pricing-by-day-pkg-lbl-ins' : 'pricing-by-day-pkg-lbl', + !this.additionalButtonData.servicePackageDiscount ? 'adjust-top' : '', ]" for="testradio">
@@ -193,7 +194,7 @@ export default { position: absolute; left: -9999px; - + .package-label.pricing-by-day-pkg-lbl { + + .package-label.pricing-by-day-pkg-lbl.adjust-top { /* Copying a component for an experiment will cause duplication of css classes. This can cause problems if you want change the value of something only for the experiment version of the component. So added a more specific selector for the parts I want to change From fa48005be0cf2537259d15fc916fa2889c2f378a Mon Sep 17 00:00:00 2001 From: Chloe Herd Date: Wed, 19 Feb 2025 15:30:04 -0500 Subject: [PATCH 9/9] Fix typo --- src/store/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/store/index.js b/src/store/index.js index d52fea200..7a1f74732 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1718,7 +1718,7 @@ export const actions = { if (recalPartNumbers && recalPartNumbers.length > 0 && carId) { let additionalQueryParams = ``; for (let i = 0; i < recalPartNumbers.length; i++) { - additionalQueryParams += `&partNumbers[${i}]=4${recalPartNumbers[i]}`; + additionalQueryParams += `&partNumbers[${i}]=${recalPartNumbers[i]}`; } additionalQueryParams += `&carId=${carId}`; endPoint += additionalQueryParams;