diff --git a/src/layouts/policy-endorsements/policy-endorsements.spec.js b/src/layouts/policy-endorsements/policy-endorsements.spec.js new file mode 100644 index 00000000..86b8fa73 --- /dev/null +++ b/src/layouts/policy-endorsements/policy-endorsements.spec.js @@ -0,0 +1,118 @@ +// Components +import policyEndorsements from '@/layouts/policy-endorsements/policy-endorsements.vue'; + +// Supporting Files +import { shallowMount } from '@vue/test-utils'; +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'; + +describe('policyEndorsements.vue', () => { + describe('Rendering', () => { + test('Should render site header', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions()); + + // Act + const siteHeader = wrapper.findComponent({ ref: 'siteHeader' }); + + // Assert + expect(siteHeader.exists()).toBe(true); + }); + test('Should render site subheader', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions()); + + // Act + const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' }); + + // Assert + expect(siteSubHeader.exists()).toBe(true); + }); + test('Should render schoolProperty buttonQuestion component', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions()); + + // Act + const buttonQuestion = wrapper.findComponent({ ref: 'schoolPropertyQuestion' }); + + // Assert + expect(buttonQuestion.exists()).toBe(true); + }); + test('Should render parkingLot buttonQuestion component', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions()); + + // Act + const buttonQuestion = wrapper.findComponent({ ref: 'parkingLotQuestion' }); + + // Assert + expect(buttonQuestion.exists()).toBe(true); + }); + test('Should render site footer', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions()); + + // Act + const siteFooter = wrapper.findComponent({ ref: 'siteFooter' }); + + // Assert + expect(siteFooter.exists()).toBe(true); + }); + }); + describe('Navigation', () => { + test('Back button clicked triggers navigation', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions({ + router: { + navigate: jest.fn() + } + })); + + // Act + wrapper.vm.backButtonAction(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigate) + .toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, undefined); + }); + test('Forward button clicked triggers navigation', () => { + // Arrange + const wrapper = shallowMount(policyEndorsements, getMountOptions({ + router: { + navigate: jest.fn() + } + })); + + // Act + wrapper.vm.forwardButtonAction(); + wrapper.vm.navigateForward(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalled(); + expect(wrapper.vm.$router.navigate) + .toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined); + }); + test('Forward button clicked saves endorsement question answers', () => { + // Arrange + const mountOptions = getMountOptions({ + router: { + navigate: jest.fn() + }, + global: { + plugins: [createTestingPinia()] + } + }); + + const wrapper = shallowMount(policyEndorsements, mountOptions); + + // Act + wrapper.vm.forwardButtonAction(); + + // Assert + expect(useMainStore().saveEndorsementQuestionAnswers).toHaveBeenCalledWith(wrapper.vm.questionAnswersArray); + }); + }); +}); diff --git a/src/layouts/policy-endorsements/policy-endorsements.vue b/src/layouts/policy-endorsements/policy-endorsements.vue new file mode 100644 index 00000000..22154818 --- /dev/null +++ b/src/layouts/policy-endorsements/policy-endorsements.vue @@ -0,0 +1,192 @@ + + + + diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue index 4b75e92d..f92a8475 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.vue +++ b/src/layouts/policy-vehicles/policy-vehicles.vue @@ -118,6 +118,14 @@ export default { ? vehicle?.coverages[0].deductible : 0; }, + selectedVehicleHasEndorsements() { + const vehicle = this.policyVehicles.find((policyVehicle) => + policyVehicle?.vin === this.selectedVehicleVin); + if (!vehicle) { + return false; + } + return vehicle.endorsements?.length > 0; + }, repairWaivedForSelectedVehicle() { const vehicle = this.policyVehicles.find((policyVehicle) => policyVehicle.vin === this.selectedVehicleVin); @@ -198,6 +206,11 @@ export default { {}, {} ); + } else if (this.selectedVehicleHasEndorsements) { + this.$router.navigate( + this.navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS, + this.$route + ); } else { this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_LISTED_VEHICLE, diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js index d79f748f..db5b783f 100644 --- a/src/router/router-constants/issPage-values.js +++ b/src/router/router-constants/issPage-values.js @@ -9,6 +9,7 @@ const issPageValues = Object.freeze({ CAPABILITY_QUESTIONS: 'capability-questions', CONTACT_CONFIRMATION: 'contact-confirmation', CONTACT_DETAILS: 'contact-details', + POLICY_ENDORSEMENTS: 'policy-endorsements', ESTIMATE: 'estimate', COVERAGE_STATEMENT: 'coverage-statement', LICENSE_PLATE_LOOKUP: 'license-plate-lookup', diff --git a/src/router/router-constants/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index 38b59ba9..3ecc72bc 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -25,6 +25,7 @@ const navigationScenarios = Object.freeze({ // Policy Vehicle CLICKED_FORWARD_LISTED_VEHICLE: 'CLICKED_FORWARD_LISTED_VEHICLE', CLICKED_FORWARD_NON_LISTED_VEHICLE: 'CLICKED_FORWARD_NON_LISTED_VEHICLE', + CLICKED_FORWARD_WITH_ENDORSEMENTS: 'CLICKED_FORWARD_WITH_ENDORSEMENTS', // Vehicle Damage CLICKED_FORWARD_WITH_REPAIR: 'CLICKED_FORWARD_WITH_REPAIR', diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 11de260a..8cd033fd 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -409,7 +409,12 @@ const routingTable = () => [ { scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, destinationIssPageValue: issPageValues.BAILOUT_PAGE + }, + { + scenario: navigationScenarios.CLICKED_FORWARD_WITH_ENDORSEMENTS, + destinationIssPageValue: issPageValues.POLICY_ENDORSEMENTS } + ] }, { @@ -620,7 +625,21 @@ const routingTable = () => [ destinationIssPageValue: issPageValues.CONTACT_CONFIRMATION } ] + }, + { + issPageValue: issPageValues.POLICY_ENDORSEMENTS, + maps: [ + { + scenario: navigationScenarios.CLICKED_BACK, + destinationIssPageValue: issPageValues.POLICY_VEHICLES + }, + { + scenario: navigationScenarios.CLICKED_FORWARD, + destinationIssPageValue: issPageValues.VEHICLE_DAMAGE + } + ] } + ]; export { routingTable }; diff --git a/src/store/index.js b/src/store/index.js index 06f9a004..38f6550d 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -59,7 +59,8 @@ const getDefaultState = () => ({ deductible: { repair: null, // numerical value; how much customer owes on deductible in repair case replace: null // numerical value; how much customer owes on deductible in replace case, - } + }, + endorsementQuestionAnswers: null }, customer: { address: { @@ -910,6 +911,20 @@ export const useMainStore = defineStore({ this.applicationUser.saveSessionPromise = null; }, + saveEndorsementQuestionAnswers(endorsementQuestionAnswersArray) { + // if endorsement question answers have changed, reset question answers + const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(this.order.policy.endorsementQuestionAnswers, 'result'); + const sortedEndorsementQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(endorsementQuestionAnswersArray, 'result'); + const haveEndorsementQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedEndorsementQuestionAnswersArray.length + || !sortedPreviousResultsArray?.every((x, i) => x.result === sortedEndorsementQuestionAnswersArray[i].result); + + if (haveEndorsementQuestionAnswersChanged) { + this.updateEndorsementQuestionAnswers(null); + } + + this.updateEndorsementQuestionAnswers(endorsementQuestionAnswersArray); + }, + saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); const isGlassToReplaceTheSame = this.order.damage.glassToReplace?.length === selectedGlassToReplace.length @@ -1159,6 +1174,10 @@ export const useMainStore = defineStore({ } }, + updateEndorsementQuestionAnswers(answersArray) { + this.order.policy.endorsementQuestionAnswers = answersArray; + }, + updateIsRepair(isRepair) { this.order.damage.isRepair = isRepair; }, diff --git a/src/store/store.spec.js b/src/store/store.spec.js index d03784f5..5ee963ab 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -955,4 +955,26 @@ describe('Store', () => { ); }); }); + + describe('saveEndorsementQuestionAnswers method', () => { + it('method should update endorsement question data in store', () => { + // Arrange + const questionNum = getRandomInt(1, 100); + const questionText = getRandomString(50, 300); + const selectedAnswer = getRandomString(2, 3); + const endorsementQuestionAnswersArray = [ + { + questionNum, + questionText, + selectedAnswer + } + ]; + + // Act + store.saveEndorsementQuestionAnswers(endorsementQuestionAnswersArray); + + // Assert + expect(store.order.policy.endorsementQuestionAnswers).toEqual(endorsementQuestionAnswersArray); + }); + }); });