diff --git a/src/helpers/recal-helper.js b/src/helpers/recal-helper.js index 0bb650ff..5b86e63a 100644 --- a/src/helpers/recal-helper.js +++ b/src/helpers/recal-helper.js @@ -120,5 +120,9 @@ export function anyPartWithRequiresRecalFlag(lineItems) { } export function hasMSRPart(lineItems) { - return lineItems?.feeItems?.some((item) => item.partNumber === partNumberStrings.RECAL_MOBILEDUAL || item.partNumber === partNumberStrings.RECAL_MOBILE) ?? false + return lineItems?.feeItems?.some((item) => isMSRPart(item)) ?? false; +} + +export function isMSRPart(part) { + return part.partNumber === partNumberStrings.RECAL_MOBILEDUAL || part.partNumber === partNumberStrings.RECAL_MOBILE; } diff --git a/src/layouts/schedule-page/service-location/service-location.spec.js b/src/layouts/schedule-page/service-location/service-location.spec.js index eb77d52c..f3485ac4 100644 --- a/src/layouts/schedule-page/service-location/service-location.spec.js +++ b/src/layouts/schedule-page/service-location/service-location.spec.js @@ -4,9 +4,11 @@ import { createTestingPinia } from '@pinia/testing'; import { AppointmentTypeStrings } from '@/constants/schedule-constants'; import navigationScenarios from '@/router/router-constants/navigation-scenarios'; import routerParams from '@/router/router-constants/router-params'; -import { getPricedMobileFeePart } from '@/helpers/service-location-helper'; import { useMainStore } from '@/store'; import serviceLocation from '@/layouts/schedule-page/service-location/service-location.vue'; +import coverageTypes from '@/constants/coverage-type'; +import coverageStatuses from '@/constants/coverage-statuses'; +import { experimentSettings } from '@/constants/experiments'; const mockGetServiceabilityDetails = () => { const serviceabilityDetails = { @@ -84,12 +86,23 @@ const mockProviders = () => Promise.resolve([ isSafeliteShop: true } ]); +const defaultMobileFeePart = { + "partNumber": "RECAL MOBILEDUAL", + "description": null, + "partType": "MOBILE FEE", + "isInsurable": false, + "displayName": "Advanced mobile", + "type": null, + "laborAmount": 0, + "sellingPrice": 50, + "kitPrice": 0 +} jest.mock( '@/helpers/service-location-helper', () => ({ getZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)), getMobileZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)), - getPricedMobileFeePart: jest.fn(() => Promise.resolve(null)) + getPricedMobileFeePart: jest.fn(() => Promise.resolve(defaultMobileFeePart)) }) ); @@ -135,13 +148,17 @@ const mountOptions = { } } }; -function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP }) { +function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP, coverageStatus = coverageStatuses.PENDING, coverageType = coverageTypes.NONE }, splitPaySettingValue = 'false') { mountOptions.global.plugins = [createTestingPinia({ initialState: { main: { order: { serviceLocation: { appointmentType + }, + insuranceCoverage: { + coverageStatus, + coverageType } } } @@ -149,6 +166,23 @@ function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP }) { })]; useMainStore().getSafeliteProviders = jest.fn().mockImplementation(() => mockProviders()); useMainStore().getServiceabilityDetails = jest.fn((mockServiceZipCode) => mockGetServiceabilityDetails(mockServiceZipCode)); + const mockMixin = { + methods: { + getSettingValue: jest.fn((settingName) => { + if (settingName === experimentSettings.MSR_SPLIT_PAY_ENABLED) { + return splitPaySettingValue; + } + + return 'false'; + }) + } + }; + const cmsMixin = { + methods: { + getCmsContent: jest.fn(() => "") + } + } + mountOptions.mixins = [mockMixin, cmsMixin]; const wrapper = mount(serviceLocation, mountOptions); wrapper.vm.$router.navigateWithSpinner = jest.fn(); @@ -212,4 +246,91 @@ describe('service-location.vue', () => { expect(wrapper.vm.zipContainsMilitaryBase).toBe(true); }); }); + describe('computed', () => { + describe('displayMSRFeeAlert', () => { + test('returns false with no mobile fee', () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.mobileFeePart = null; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(false); + }); + + test('returns false with a mobile fee with no price', () => { + // Arrange + const { wrapper } = setupMocks({}); + wrapper.vm.mobileFeePart = { ...defaultMobileFeePart, sellingPrice: 0 }; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(false); + }); + + test('returns true for priced mobile fee for No Comp', () => { + // Arrange + const { wrapper } = setupMocks({ coverageStatus: coverageStatuses.VERIFIED, coverageType: coverageTypes.NO_COMP }); + wrapper.vm.mobileFeePart = defaultMobileFeePart; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(true); + }); + + test('returns true for priced mobile fee for ITAC', () => { + // Arrange + const { wrapper } = setupMocks({ coverageStatus: coverageStatuses.VERIFIED, coverageType: coverageTypes.ITAC }); + wrapper.vm.mobileFeePart = defaultMobileFeePart; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(true); + }); + + test('returns false for priced mobile fee for Deductible without Split Pay', () => { + // Arrange + const { wrapper } = setupMocks({ coverageStatus: coverageStatuses.VERIFIED, coverageType: coverageTypes.Deductible }, 'false'); + wrapper.vm.mobileFeePart = defaultMobileFeePart; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(false); + }); + + test('returns false for priced mobile fee for Deductible with Split Pay and isInsurable=true', () => { + // Arrange + const { wrapper } = setupMocks({ coverageStatus: coverageStatuses.VERIFIED, coverageType: coverageTypes.Deductible }, 'true'); + wrapper.vm.mobileFeePart = { ...defaultMobileFeePart, isInsurable: true }; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(false); + }); + + test('returns true for priced mobile fee for Deductible with Split Pay and isInsurable=false', () => { + // Arrange + const { wrapper } = setupMocks({ coverageStatus: coverageStatuses.VERIFIED, coverageType: coverageTypes.Deductible }, 'true'); + wrapper.vm.mobileFeePart = { ...defaultMobileFeePart, isInsurable: false }; + + // Act + const result = wrapper.vm.displayMSRFeeAlert; + + // Assert + expect(result).toBe(true); + }); + }); + }); }); diff --git a/src/layouts/schedule-page/service-location/service-location.vue b/src/layouts/schedule-page/service-location/service-location.vue index 0681c0f9..595cc5cb 100644 --- a/src/layouts/schedule-page/service-location/service-location.vue +++ b/src/layouts/schedule-page/service-location/service-location.vue @@ -94,6 +94,12 @@ {{ militaryBaseWarningText }} +