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" />
-