diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 1c0edd15..41a51f84 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -16,7 +16,8 @@ const experimentSettings = Object.freeze({ ISS_MOBILE_FIRST_MAX_MOBILE_DAYS: 'MaxMobileDays', ISS_MOBILE_FIRST_MAX_PM_MOBILE_DAYS: 'MaxPmMobileDays', ISS_MOBILE_FIRST_SHOW_FIRST_MOBILE_APPOINTMENT: 'ShowMobileFirstAppointment', - ISS_ENABLE_ADYEN_V1: 'ISS_Enable_Adyen_V1' + ISS_ENABLE_ADYEN_V1: 'ISS_Enable_Adyen_V1', + MSR_SPLIT_PAY_ENABLED: 'EnableMSRSplitPay' }); const experimentTest = Object.freeze({ diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index 029aee25..0bb650ff 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -1,3 +1,4 @@ +import partNumberStrings from '@/constants/part-number-strings'; import partTypeStrings from '@/constants/part-type-strings'; import { deepClone, getNonFalseValuesOfPropertyInArrayOfObjects } from '@/helpers/object-helper'; @@ -117,3 +118,7 @@ export function anyPartWithRequiresRecalFlag(lineItems) { return flattened.some((li) => li.requiresRecalibration === true); } + +export function hasMSRPart(lineItems) { + return lineItems?.feeItems?.some((item) => item.partNumber === partNumberStrings.RECAL_MOBILEDUAL || item.partNumber === partNumberStrings.RECAL_MOBILE) ?? false +} diff --git a/src/iss-components/cart-dropdown/cart-dropdown.spec.js b/src/iss-components/cart-dropdown/cart-dropdown.spec.js index 16692604..1efd6907 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.spec.js +++ b/src/iss-components/cart-dropdown/cart-dropdown.spec.js @@ -13,6 +13,7 @@ import { getPriceOfLineItems } from '@/helpers/price-calculator.js'; import coverageStatuses from '@/constants/coverage-statuses'; import coverageType from '@/constants/coverage-type'; import * as cartHelper from '@/helpers/cart-helper'; +import { experimentSettings } from '@/constants/experiments'; const VERIFYING_COVERAGE = 'Verifying coverage'; @@ -30,7 +31,7 @@ jest.mock('@/helpers/service-package-helper', () => ({ getPackageContents: jest.fn() })); -function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) { +function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}, experimentMockFunction = jest.fn(() => 'false')) { const mountOptions = getMountOptions({ router: { navigate: jest.fn() @@ -44,7 +45,7 @@ function getMountedComponent(mainInitialState = {}, initialData = {}, propsData }); useMainStore(testingPinia); - mountOptions.global.mixins[0].methods.getSettingValue = jest.fn(() => 'false'); + mountOptions.global.mixins[0].methods.getSettingValue = experimentMockFunction; mountOptions.global.plugins = [testingPinia]; mountOptions.data = () => (initialData); mountOptions.propsData = propsData; @@ -804,12 +805,16 @@ describe('cart-dropdown component', () => { partType: partTypeStrings.REPLACE_FEE })); }); - test('when mobileFee, includes mobile fee', () => { + test('when mobile fee should be included, includes mobile fee', () => { // Arrange const storeData = { order: { lineItems: { - feeItems: [{ partType: partTypeStrings.MOBILE_FEE }] + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, sellingPrice: 123}] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.NO_COMP } } }; @@ -977,6 +982,153 @@ describe('cart-dropdown component', () => { expect(result.name).toBe(expectedName); }); }); + describe('includeMobileFeeInCart', () => { + test('returns false with no mobile fee', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(false); + }); + + test('returns false with a mobile fee with no price', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 0 }] + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(false); + }); + + test('returns true for priced mobile fee for No Comp', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 100 }] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.NO_COMP + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(true); + }); + + test('returns true for priced mobile fee for ITAC', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 100 }] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.ITAC + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(true); + }); + + test('returns false for priced mobile fee for Deductible without Split Pay', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 100 }] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.Deductible + } + } + }; + const { wrapper } = getMountedComponent(storeData); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(false); + }); + + test('returns false for priced mobile fee for Deductible with Split Pay and isInsurable=true', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 100, isInsurable: true }] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.Deductible + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, {}, (settingName) => (settingName === experimentSettings.MSR_SPLIT_PAY_ENABLED).toString()); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(false); + }); + + test('returns true for priced mobile fee for Deductible with Split Pay and isInsurable=false', () => { + // Arrange + const storeData = { + order: { + lineItems: { + feeItems: [{ partType: partTypeStrings.MOBILE_FEE, price: 100, isInsurable: false }] + }, + insuranceCoverage: { + coverageStatus: coverageStatuses.VERIFIED, + coverageType: coverageType.Deductible + } + } + }; + const { wrapper } = getMountedComponent(storeData, {}, {}, (settingName) => (settingName === experimentSettings.MSR_SPLIT_PAY_ENABLED).toString()); + + // Act + const result = wrapper.vm.includeMobileFeeInCart; + + // Assert + expect(result).toBe(true); + }); + }); }); describe('method', () => { const dollarAmount = '$84.00'; diff --git a/src/iss-components/cart-dropdown/cart-dropdown.vue b/src/iss-components/cart-dropdown/cart-dropdown.vue index 19a7fe71..9572f9af 100644 --- a/src/iss-components/cart-dropdown/cart-dropdown.vue +++ b/src/iss-components/cart-dropdown/cart-dropdown.vue @@ -146,6 +146,8 @@ import { } from '@/helpers/cart-helper'; import { getPriceOfLineItem, getPriceOfLineItems, getTaxOfLineItems } from '@/helpers/price-calculator'; import { processIfStatements } from '@/helpers/cms-content-helper'; +import partNumberStrings from '@/constants/part-number-strings'; +import { hasMSRPart } from '@/helpers/recal-helper'; const VERIFYING_COVERAGE = 'Verifying coverage'; const ADVANCED_MOBILE_MODAL_REF_NAME = 'advancedMobileModal'; @@ -229,7 +231,8 @@ export default { servicePrice() { const price = getPriceOfLineItems(getServiceLineItems(this.cartOrder)) ?? 0; const recycleFee = this.recycleFeeLineItem ? getPriceOfLineItem(this.recycleFeeLineItem) : 0; - return price - this.recalibrationPrice - recycleFee; + const mobileFee = this.mobileFeeCartItem ? this.mobileFeeCartItem.subTotal : 0; + return price - this.recalibrationPrice - recycleFee - mobileFee; }, isUnverified() { return isOrderUnverified(this.cartOrder); @@ -270,7 +273,6 @@ export default { cartItems() { const items = []; const isRecycleFeeHidden = this.getSettingValue(experimentSettings.ISS_FEATURE_TOGGLE_IS_RECYCLE_FEE_HIDDEN) === 'true'; - const isMobileFeeHidden = this.getSettingValue(experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true'; if (this.isITAC || this.isNoComp) { items.push(this.warrantyCartItem); } @@ -291,7 +293,7 @@ export default { } }); items.push(...vapsCartItems.filter((item) => item != null)); - if (this.mobileFeeCartItem && !isMobileFeeHidden && !this.mobileFeeCartItem.isInsurable) { + if (this.includeMobileFeeInCart) { items.push(this.mobileFeeCartItem); } return items; @@ -380,6 +382,34 @@ export default { return { feeAmount: this.mobileFeeCartItem ? formatAmountInDollars(this.mobileFeeCartItem.subTotal) : '' } + }, + hasMSRPart() { + return hasMSRPart(this.cartOrder.lineItems); + }, + includeMobileFeeInCart() { + if (!this.mobileFeeCartItem || this.mobileFeeCartItem.subTotal === 0) { + return false; + } + + const isMobileFeeHidden = this.getSettingValue(experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true'; + if (isMobileFeeHidden) { + return false; + } + + if (this.isITAC || this.isNoComp) { + return true; + } + + const isSplitPayEnabled = this.getSettingValue(experimentSettings.MSR_SPLIT_PAY_ENABLED) === 'true'; + if (!isSplitPayEnabled) { + return false; + } + + if (!this.mobileFeeCartItem.isInsurable) { + return true; + } + + return false; } }, methods: { diff --git a/src/layouts/contact-details/contact-details.vue b/src/layouts/contact-details/contact-details.vue index 2af0960d..1f5c6304 100644 --- a/src/layouts/contact-details/contact-details.vue +++ b/src/layouts/contact-details/contact-details.vue @@ -17,12 +17,11 @@ ref="siteSubHeader" class="subheader" :cmsWidgetName="widget.siteSubHeader" /> - + :cmsWidgetName="appointmentInformationWidget" /> diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue index 31b09b27..1f68e584 100644 --- a/src/layouts/payment-method/payment-method.vue +++ b/src/layouts/payment-method/payment-method.vue @@ -33,8 +33,6 @@ + :showAsPaid="false" /> diff --git a/src/layouts/payment-page/payment-page.vue b/src/layouts/payment-page/payment-page.vue index d116b502..9f936bb8 100644 --- a/src/layouts/payment-page/payment-page.vue +++ b/src/layouts/payment-page/payment-page.vue @@ -45,9 +45,7 @@ ref="cart" class="cart-dropdown-component" :readOnly="true" - :showAsPaid="false" - recyclingModalCmsWidgetName="RecycleModal" - servicePackageTitleWidgetName="ServicePackageTitle" /> + :showAsPaid="false" />