diff --git a/src/layouts/policy-endorsements/policy-endorsements.spec.js b/src/layouts/policy-endorsements/policy-endorsements.spec.js index 86b8fa73..c01818f5 100644 --- a/src/layouts/policy-endorsements/policy-endorsements.spec.js +++ b/src/layouts/policy-endorsements/policy-endorsements.spec.js @@ -7,6 +7,24 @@ import { getMountOptions } from '@/helpers/unit-test-helper.js'; import navigationScenarios from '@/router/router-constants/navigation-scenarios'; import { createTestingPinia } from '@pinia/testing'; import { useMainStore } from '@/store'; +import { getRandomString } from '@/helpers/data-generation'; + +function getMountedComponent(mainInitialState = {}) { + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn() + } + }); + + mountOptions.global.plugins = [createTestingPinia({ + initialState: { + main: mainInitialState + } + })]; + + const wrapper = shallowMount(policyEndorsements, mountOptions); + return { wrapper }; +} describe('policyEndorsements.vue', () => { describe('Rendering', () => { @@ -30,26 +48,70 @@ describe('policyEndorsements.vue', () => { // Assert expect(siteSubHeader.exists()).toBe(true); }); - test('Should render schoolProperty buttonQuestion component', () => { + test('Should render schoolProperty buttonQuestion component if policy vehicle has Educator endorsement', () => { // Arrange - const wrapper = shallowMount(policyEndorsements, getMountOptions()); - - // Act + const mainInitialState = { + order: { + policy: { + endorsements: ['Educator'] + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); const buttonQuestion = wrapper.findComponent({ ref: 'schoolPropertyQuestion' }); // Assert + expect(wrapper.vm.educatorEndorsement).toBeTruthy(); expect(buttonQuestion.exists()).toBe(true); }); - test('Should render parkingLot buttonQuestion component', () => { + test('Should not render schoolProperty buttonQuestion component if policy vehicle does not have Educator endorsement', () => { // Arrange - const wrapper = shallowMount(policyEndorsements, getMountOptions()); + const mainInitialState = { + order: { + policy: { + endorsements: [getRandomString(20, 30)] + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); + const buttonQuestion = wrapper.findComponent({ ref: 'schoolPropertyQuestion' }); - // Act + // Assert + expect(wrapper.vm.educatorEndorsement).toBeFalsy(); + expect(buttonQuestion.exists()).toBe(false); + }); + test('Should render parkingLot buttonQuestion component if policy vehicle has Parking Guard endorsement', () => { + // Arrange + const mainInitialState = { + order: { + policy: { + endorsements: ['Parking Guard'] + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); const buttonQuestion = wrapper.findComponent({ ref: 'parkingLotQuestion' }); // Assert + expect(wrapper.vm.parkingGuardEndorsement).toBeTruthy(); expect(buttonQuestion.exists()).toBe(true); }); + test('Should not render parkingLot buttonQuestion component if policy vehicle does not have Parking Guard endorsement', () => { + // Arrange + const mainInitialState = { + order: { + policy: { + endorsements: [getRandomString(20, 30)] + } + } + }; + const { wrapper } = getMountedComponent(mainInitialState); + const buttonQuestion = wrapper.findComponent({ ref: 'parkingLotQuestion' }); + + // Assert + expect(wrapper.vm.parkingGuardEndorsement).toBeFalsy(); + expect(buttonQuestion.exists()).toBe(false); + }); test('Should render site footer', () => { // Arrange const wrapper = shallowMount(policyEndorsements, getMountOptions()); diff --git a/src/layouts/policy-endorsements/policy-endorsements.vue b/src/layouts/policy-endorsements/policy-endorsements.vue index 22154818..1d4e1972 100644 --- a/src/layouts/policy-endorsements/policy-endorsements.vue +++ b/src/layouts/policy-endorsements/policy-endorsements.vue @@ -16,6 +16,7 @@ cmsWidgetName="SiteSubHeaderWidget" class="mt-5" /> { vin, noCoverage: true, deductible: 0, - repairWaived: false + repairWaived: false, + endorsements: [] }; // Act @@ -135,6 +136,55 @@ describe('policy-vehicles.vue', () => { } ); + test( + // eslint-disable-next-line max-len + 'Selected VIN matches vehicle listed in system and policy vehicle has endorsements => update vehicle and navigate forward with CLICKED_FORWARD_WITH_ENDORSEMENTS scenario.', + async () => { + // Arrange + const { wrapper } = setupMocks({}); + + const vin = getRandomString(17, 17); + const endorsements = [getRandomString(10, 20)]; + await wrapper.setData({ + selectedVehicleVin: vin, + policyVehicles: [ + { + vin, + endorsements + } + ] + }); + + const year = getRandomInt(1998, 2023); + const lookupVehicleResponse = { + data: { + year + } + }; + const store = useMainStore(); + store.lookupVehicleByVin.mockReturnValue(Promise.resolve(lookupVehicleResponse)); + + const expectedInput = { + year, + vin, + noCoverage: true, + deductible: 0, + repairWaived: false, + endorsements + }; + + // Act + await wrapper.vm.forwardButtonAction(); + + // Assert + expect(store.updateVehicle).toHaveBeenCalledWith(expectedInput); + expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( + navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS, + undefined + ); + } + ); + test( 'Error in lookupVehicleByVin call => bailout true and navigate forward with CLICKED_FORWARD_WITH_BAILOUT scenario.', async () => { @@ -408,6 +458,120 @@ describe('policy-vehicles.vue', () => { }); }); + describe('endorsementsForSelectedVehicle computed property', () => { + it('policyVehicles is null => empty endorsements array returned', () => { + // Arrange + const testValues = { + policyVehicles: null + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + const expected = []; + + // Assert + expect(result).toStrictEqual(expected); + }); + + it('policyVehicles is empty => empty endorsements array returned', () => { + // Arrange + const testValues = { + policyVehicles: [] + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + const expected = []; + + // Assert + expect(result).toStrictEqual(expected); + }); + + it('selectedVehicleVin does not match any vin in policyVehicles => empty endorsements array returned', () => { + // Arrange + const selectedVin = getRandomString(17, 17); + const otherVin = getRandomString(17, 17); + const testValues = { + selectedVehicleVin: selectedVin, + policyVehicles: [ + { + vin: otherVin + } + ] + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + const expected = []; + + // Assert + expect(result).toStrictEqual(expected); + }); + + it('vehicle VIN match with endorsements null => empty endorsements array returned', () => { + // Arrange + const vin = getRandomString(17, 17); + const testValues = { + selectedVehicleVin: vin, + policyVehicles: [ + { + vin, + endorsements: null + } + ] + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + const expected = []; + + // Assert + expect(result).toStrictEqual(expected); + }); + + it('vehicle VIN match with empty endorsements => empty endorsements array returned', () => { + // Arrange + const vin = getRandomString(17, 17); + const testValues = { + selectedVehicleVin: vin, + policyVehicles: [ + { + vin, + endorsements: [] + } + ] + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + const expected = []; + + // Assert + expect(result).toStrictEqual(expected); + }); + + it('vehicle VIN match with endorsements => endorsements array returned', () => { + // Arrange + const vin = getRandomString(17, 17); + const endorsements = [getRandomString(10, 20)]; + const testValues = { + selectedVehicleVin: vin, + policyVehicles: [ + { + vin, + endorsements + } + ] + }; + + // Act + const result = policyVehicles.computed.endorsementsForSelectedVehicle.call(testValues); + + // Assert + expect(result).toStrictEqual(endorsements); + }); + }); + test('first vehicle is auto-selected if only one vehicle on policy', async () => { // Arrange const vin = getRandomString(17, 17); diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue index 8e08bd97..8ea67941 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.vue +++ b/src/layouts/policy-vehicles/policy-vehicles.vue @@ -102,12 +102,12 @@ export default { return mappedData; }, noCoverageForSelectedVehicle() { - const vehicle = this.policyVehicles.find((policyVehicle) => + const vehicle = this.policyVehicles?.find((policyVehicle) => policyVehicle.vin === this.selectedVehicleVin); return (vehicle?.coverages?.length ?? 0) === 0; }, deductibleForSelectedVehicle() { - const vehicle = this.policyVehicles.find((policyVehicle) => + const vehicle = this.policyVehicles?.find((policyVehicle) => policyVehicle?.vin === this.selectedVehicleVin); if (!vehicle) { return undefined; @@ -117,16 +117,16 @@ export default { ? vehicle?.coverages[0].deductible : 0; }, - selectedVehicleHasEndorsements() { - const vehicle = this.policyVehicles.find((policyVehicle) => + endorsementsForSelectedVehicle() { + const vehicle = this.policyVehicles?.find((policyVehicle) => policyVehicle?.vin === this.selectedVehicleVin); - if (!vehicle) { - return false; + if (vehicle?.endorsements?.length > 0) { + return vehicle.endorsements; } - return vehicle.endorsements?.length > 0; + return []; }, repairWaivedForSelectedVehicle() { - const vehicle = this.policyVehicles.find((policyVehicle) => + const vehicle = this.policyVehicles?.find((policyVehicle) => policyVehicle.vin === this.selectedVehicleVin); return vehicle?.endorsements?.includes(endorsementOptions.REPAIR_WAIVED) ?? false; }, @@ -161,7 +161,7 @@ export default { }, beforeMount() { if (this.policyVehicles?.length === 1) { - this.selectedVehicleVin = this.policyVehicles[0].vin; + this.selectedVehicleVin = this.policyVehicles[0]?.vin; } }, methods: @@ -182,7 +182,8 @@ export default { vin: this.selectedVehicleVin, noCoverage: this.noCoverageForSelectedVehicle, deductible: this.deductibleForSelectedVehicle, - repairWaived: this.repairWaivedForSelectedVehicle + repairWaived: this.repairWaivedForSelectedVehicle, + endorsements: this.endorsementsForSelectedVehicle }); useMainStore().updateVehicle(this.vehicleFromLookup); @@ -205,7 +206,7 @@ export default { {}, {} ); - } else if (this.selectedVehicleHasEndorsements) { + } else if (this.endorsementsForSelectedVehicle?.length > 0) { this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS, this.$route diff --git a/src/store/index.js b/src/store/index.js index 88197e9e..174a06ef 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -76,6 +76,7 @@ const getDefaultState = () => ({ }, isITAC: null, vehicles: [], + endorsements: [], endorsementQuestionAnswers: null }, customer: { @@ -1168,6 +1169,7 @@ export const useMainStore = defineStore({ : coverageStatuses.PENDING; this.order.policy.deductible.replace = vehicle.deductible; this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible; + this.order.policy.endorsements = vehicle?.endorsements; // TODO logic should be more complicated later on this.order.originalDeductible = parseFloat(vehicle.deductible); diff --git a/src/store/store.spec.js b/src/store/store.spec.js index fd728d27..9fc8f865 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -153,10 +153,12 @@ describe('Store', () => { // Arrange const noCoverage = getRandomBoolean(); const deductible = getRandomInt(1, 500); + const endorsements = [getRandomString(10, 20)]; const vehicle = { noCoverage, deductible, - repairWaived: true + repairWaived: true, + endorsements }; const expectedPolicy = { @@ -164,7 +166,8 @@ describe('Store', () => { deductible: { replace: deductible, repair: 0 - } + }, + endorsements }; // Act @@ -178,10 +181,12 @@ describe('Store', () => { // Arrange const noCoverage = getRandomBoolean(); const deductible = getRandomInt(1, 500); + const endorsements = [getRandomString(10, 20)]; const vehicle = { noCoverage, deductible, - repairWaived: false + repairWaived: false, + endorsements }; const expectedPolicy = { @@ -189,7 +194,8 @@ describe('Store', () => { deductible: { replace: deductible, repair: deductible - } + }, + endorsements }; // Act