From ade752091f26f358e9b7e940e8ce484c34bbc541 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Fri, 9 Jun 2023 09:36:33 -0400 Subject: [PATCH 01/20] Adding register claim endpoint to endpoints file --- src/constants/endpoints.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index ca2c297f..be1ad311 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -125,7 +125,11 @@ const endpoints = { CoveragePolicyInfo: { url: '/coverage/api/v1/coverage/get-policy-information', method: 'POST' -} + }, + RegisterClaim: { + url: '/coverage/api/v1/coverage/register-claim', + method: 'POST' + } }; export { endpoints }; From e6ae82780aeac09a0c1ba30346a55b2476c8db67 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Fri, 9 Jun 2023 09:55:04 -0400 Subject: [PATCH 02/20] Partial register claim method added to store --- src/store/index.js | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/store/index.js b/src/store/index.js index 7b7d4dd0..ca36e9a3 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -347,6 +347,28 @@ export const useMainStore = defineStore({ }; } }, + // TODO determine what inputs are required to get a response + registerClaim() { + try { + const response = globalMethods.callHttpClient({ + method: endpoints.RegisterClaim.method, + endpoint: endpoints.RegisterClaim.url, + payload: { + // accountNumber: accountNumber, + // policyNumber: policyNumber, + // dateOfLoss: dateOfLoss, + // zipCode: zipCode + } + }); + return response; + } catch (responseError) { + return { + error: { + status: responseError.status + } + }; + } + }, async lookupVinByPlate(licensePlate, licenseState) { try { const response = await globalMethods.callHttpClient({ From b16fe6656e85d20422d527a972cc315362c19e52 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 14 Jun 2023 15:48:23 -0400 Subject: [PATCH 03/20] First pass --- src/constants/coverage-statuses.js | 7 + .../coverage-statement/coverage-statement.vue | 58 +++- src/layouts/vehicle-damage/vehicle-damage.vue | 316 +++++++++--------- src/store/index.js | 68 +++- 4 files changed, 278 insertions(+), 171 deletions(-) create mode 100644 src/constants/coverage-statuses.js diff --git a/src/constants/coverage-statuses.js b/src/constants/coverage-statuses.js new file mode 100644 index 00000000..76d46f2e --- /dev/null +++ b/src/constants/coverage-statuses.js @@ -0,0 +1,7 @@ +const coverageStatuses = { + PENDING: "Pending", + NO_COMP: "No Comp", + VERIFIED: "Verified", +}; + +export { coverageStatuses }; \ No newline at end of file diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index f1128f8a..af77b84d 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -58,6 +58,7 @@ import { settleAllPromises } from '@/helpers/layout-helper'; import { getDamageString } from '@/helpers/damage-helper.js'; import { useMainStore } from "@/store"; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; +import { coverageStatuses } from '../../constants/coverage-statuses'; export default { name: 'coverage-statement', @@ -76,11 +77,11 @@ export default { }, computed: { bodyText() { - if (useMainStore().order.damage.isRepair) { + if (useMainStore().damage.isRepair) { return this.unverifiedNonADASRepairBodyText; } else { - let parts = useMainStore().order.lineItems.glassParts; + let parts = useMainStore().lineItems.glassParts; // if ADAS, display ADASNextSteps if (parts.filter(part => part.requiresRecalibration).length > 0) { @@ -124,16 +125,65 @@ export default { const resultMap = await settleAllPromises(promiseResultMap); next((vm) => { - vm.setCmsContent(resultMap.cmsContent); + vm.setCmsContent(resultMap.cmsContent); }); }, + async mounted() { + let registerClaimResponse = null; + if (useMainStore().isClaimRegistrationRequired){ + registerClaimResponse = await this.getRegisterClaimResponse(); + } + this.setInsuranceCoverageValues(registerClaimResponse); + }, methods: { arePagePrerequisitesValid() { - if (useMainStore().order.vehicle.vin) { + if (useMainStore().vehicle.vin) { return true; } return false; }, + + async getRegisterClaimResponse() { + try { + registerClaimResponse = await useMainStore().registerClaim(); + const promiseResultMap = [ + { + resultKey: 'registerClaimResponse', + promise: registerClaimResponse + }, + ]; + + const resultMap = await settleAllPromises(promiseResultMap); + return resultMap.registerClaimResponse; + } + catch(responseError) { + return { + error: { + status: responseError.status + } + } + } + }, + + // TODO wait for confirmation from Jeremy + setInsuranceCoverageValues(registerClaimResponse) { + // null => claim reg not required + // success => verified + // failed => not verified + + const registerClaimFailed = registerClaimResponse.error; + if (useMainStore().isClaimRegistrationRequired) { + useMainStore().payment.insuranceCoverage.isVerified = !registerClaimFailed; + useMainStore().payment.insuranceCoverage.coverageStatus = registerClaimFailed + ? coverageStatuses.PENDING + : coverageStatuses.VERIFIED; // TODO include no comp case as well + } + else { // TODO confirm + useMainStore().payment.insuranceCoverage.isVerified = true; + // What about no comp??? + useMainStore().payment.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED; + } + }, async forwardButtonAction() { return this.navigateForward(); diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 5106203c..c0a43337 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -315,170 +315,170 @@ export default { this.selectedGlassToReplace(), this.selectedWindshieldOptions.selectedWindshieldChipCount); return this.navigateForward(); - }, + }, - navigateForward() { - if (this.mainStore.damage.isRepair) { + navigateForward() { + if (this.mainStore.damage.isRepair) { + this.$router.navigate( + this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR, + this.$route + ); + } + else { + // If vin already exists, navigate directly to vin-lookup + if (this.mainStore.order.vehicle.vin) { this.$router.navigate( - this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR, + this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, + this.$route + ); + } else { + this.$router.navigate( + this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, this.$route ); } - else { - // If vin already exists, navigate directly to vin-lookup - if (this.mainStore.order.vehicle.vin) { - this.$router.navigate( - this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, - this.$route - ); - } else { - this.$router.navigate( - this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN, - this.$route - ); - } - } - }, - - selectedGlassToReplace() { - const selectedGlassToReplace = []; - if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) { - this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach( - (wsItem) => { - selectedGlassToReplace.push({ - glassLocation: damageLocationsSelected.WINDSHIELD, - glassName: wsItem, - }); - } - ); - } - - if (this.isDriverSideReplace) { - this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach((driverItem) => { - selectedGlassToReplace.push({ - glassLocation: damageLocationsSelected.DRIVER, - glassName: driverItem, - }); - }); - } - - if (this.isPassengerSideReplace) { - this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach( - (passengerItem) => { - selectedGlassToReplace.push({ - glassLocation: damageLocationsSelected.PASSENGER, - glassName: passengerItem, - }); - } - ); - } - - if (this.isRearWindowDamageLocation) { - selectedGlassToReplace.push({ - glassLocation: damageLocationsSelected.REAR, - glassName: this.selectedRearReplaceOptions, - }); - } - - return selectedGlassToReplace; - }, - }, - computed: { - isWindshieldDamageLocation() { - return this.selectedDamageLocations.some((selectedDamages) => { - return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD; - }); - }, - isSideDoorDamageLocation() { - return this.selectedDamageLocations.some((selectedDamages) => { - return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR; - }); - }, - isRearWindowDamageLocation() { - return this.selectedDamageLocations.some((selectedDamages) => { - return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW; - }); - }, - isWindshieldRepair() { - return ( - this.isWindshieldDamageLocation && - this.selectedWindshieldOptions.selectedWindshieldDamageType === - damageLocationsSelected.REPAIR - ); - }, - isDriverSideReplace() { - if (!this.isSideDoorDamageLocation) return false; - - return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) => { - return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE; - }); - }, - isPassengerSideReplace() { - if (!this.isSideDoorDamageLocation) return false; - - return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) => { - return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE; - }); - }, - hasRepairReplaceConflict() { - return ( - this.isWindshieldDamageLocation && - this.selectedDamageLocations.length > 1 && - this.isWindshieldRepair - ); - }, - hasSplitSingleConflict() { - if ( - !this.selectedDamageLocations?.includes("Windshield") || - this.selectedWindshieldOptions.selectedWindshieldDamageType === - damageLocationsSelected.REPAIR || - !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions - ) - return false; - - return ( - this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( - (selectedSingleWindshield) => { - return ( - selectedSingleWindshield.toUpperCase() === - damageLocationsSelected.SINGLE.toUpperCase() - ); - } - ) && - (this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( - (selectedDriverWindshield) => { - return ( - selectedDriverWindshield.toUpperCase() === - damageLocationsSelected.DRIVER.toUpperCase() - ); - } - ) || - this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( - (selectedPassengerWindshield) => { - return ( - selectedPassengerWindshield.toUpperCase() === - damageLocationsSelected.PASSENGER.toUpperCase() - ); - } - )) - ); - }, - shouldDisplayVehicleChangeAlert() { - return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]; } }, - components: { - siteHeader, - siteFooter, - vehicleBanner, - siteSubHeader, - sideDoorOptions, - damageLocationQuestion, - windshieldOptions, - replaceOptionsQuestion, - Form, - alert, + selectedGlassToReplace() { + const selectedGlassToReplace = []; + if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) { + this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach( + (wsItem) => { + selectedGlassToReplace.push({ + glassLocation: damageLocationsSelected.WINDSHIELD, + glassName: wsItem, + }); + } + ); + } + + if (this.isDriverSideReplace) { + this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach((driverItem) => { + selectedGlassToReplace.push({ + glassLocation: damageLocationsSelected.DRIVER, + glassName: driverItem, + }); + }); + } + + if (this.isPassengerSideReplace) { + this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach( + (passengerItem) => { + selectedGlassToReplace.push({ + glassLocation: damageLocationsSelected.PASSENGER, + glassName: passengerItem, + }); + } + ); + } + + if (this.isRearWindowDamageLocation) { + selectedGlassToReplace.push({ + glassLocation: damageLocationsSelected.REAR, + glassName: this.selectedRearReplaceOptions, + }); + } + + return selectedGlassToReplace; }, - }; - + }, + computed: { + isWindshieldDamageLocation() { + return this.selectedDamageLocations.some((selectedDamages) => { + return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD; + }); + }, + isSideDoorDamageLocation() { + return this.selectedDamageLocations.some((selectedDamages) => { + return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR; + }); + }, + isRearWindowDamageLocation() { + return this.selectedDamageLocations.some((selectedDamages) => { + return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW; + }); + }, + isWindshieldRepair() { + return ( + this.isWindshieldDamageLocation && + this.selectedWindshieldOptions.selectedWindshieldDamageType === + damageLocationsSelected.REPAIR + ); + }, + isDriverSideReplace() { + if (!this.isSideDoorDamageLocation) return false; + + return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) => { + return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE; + }); + }, + isPassengerSideReplace() { + if (!this.isSideDoorDamageLocation) return false; + + return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) => { + return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE; + }); + }, + hasRepairReplaceConflict() { + return ( + this.isWindshieldDamageLocation && + this.selectedDamageLocations.length > 1 && + this.isWindshieldRepair + ); + }, + hasSplitSingleConflict() { + if ( + !this.selectedDamageLocations?.includes("Windshield") || + this.selectedWindshieldOptions.selectedWindshieldDamageType === + damageLocationsSelected.REPAIR || + !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions + ) + return false; + + return ( + this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( + (selectedSingleWindshield) => { + return ( + selectedSingleWindshield.toUpperCase() === + damageLocationsSelected.SINGLE.toUpperCase() + ); + } + ) && + (this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( + (selectedDriverWindshield) => { + return ( + selectedDriverWindshield.toUpperCase() === + damageLocationsSelected.DRIVER.toUpperCase() + ); + } + ) || + this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( + (selectedPassengerWindshield) => { + return ( + selectedPassengerWindshield.toUpperCase() === + damageLocationsSelected.PASSENGER.toUpperCase() + ); + } + )) + ); + }, + shouldDisplayVehicleChangeAlert() { + return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]; + } + }, + + components: { + siteHeader, + siteFooter, + vehicleBanner, + siteSubHeader, + sideDoorOptions, + damageLocationQuestion, + windshieldOptions, + replaceOptionsQuestion, + Form, + alert, + }, +}; + diff --git a/src/store/index.js b/src/store/index.js index 439544c4..012803e4 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -6,6 +6,7 @@ import { experimentTriggers } from '@/constants/experiments'; import { applicationConfig } from '@/constants/application-config'; import { issPageValues } from '@/router/router-constants/issPage-values'; import { damageLocationsSelected } from '@/constants/damage-locations-selected'; +import { coverageStatuses } from '@/constants/coverage-statuses'; const storeId = 'main'; @@ -48,7 +49,12 @@ const getDefaultState = () => { damageCause: null, damageState: null, damageCity: null, - isDamageGlassOnly: null + isDamageGlassOnly: null, + // TODO set these in code + deductable: { + repair: null, // numerical value; how much customer owes on deductable in repair case + replace: null // numerical value; how much customer owes on deductible in replace case + } }, customer: { address: { @@ -79,7 +85,8 @@ const getDefaultState = () => { payment: { isInsurance: true, insuranceCoverage: { - isVerified: false + isVerified: false, + coverageStatus: coverageStatuses.PENDING } }, referralNumber: null, @@ -125,7 +132,9 @@ export const useMainStore = defineStore({ vehicle: (state) => state.order.vehicle, damage: (state) => state.order.damage, lineItems: (state) => state.order.lineItems, + payment: (state) => state.order.payment, hasAnyNonWindshieldGlassParts: (state) => !state.order.policy.isDamageGlassOnly, + isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired, eventBusItem: (state) => ( eventCategory, eventSubCategory) => { const matchedEvent = state.applicationUser.eventBus.find( @@ -327,7 +336,7 @@ export const useMainStore = defineStore({ } }, getCoveragePolicyInfo({accountNumber, policyNumber, dateOfLoss, zipCode}){ - //todo: replace place holder correlationId with the real thing + //TODO: replace place holder correlationId with the real thing const placeHolderCorrelationId = "00000000-0000-0000-0000-000000000000"; try{ const response = globalMethods.callHttpClient({ @@ -350,17 +359,58 @@ export const useMainStore = defineStore({ }; } }, - // TODO determine what inputs are required to get a response registerClaim() { try { + // TODO: replace place holder correlationId with the real thing + const placeHolderCorrelationId = "00000000-0000-0000-0000-000000000000"; const response = globalMethods.callHttpClient({ method: endpoints.RegisterClaim.method, endpoint: endpoints.RegisterClaim.url, - payload: { - // accountNumber: accountNumber, - // policyNumber: policyNumber, - // dateOfLoss: dateOfLoss, - // zipCode: zipCode + payload: + { + correlationId: placeHolderCorrelationId, + accountNumber: this.issConfig.accountNumber.toString(), + insured: { + firstName: this.order.customer.firstName, + lastName: this.order.customer.lastName, + address: { + addressLine1: this.order.customer.address.streetAddress, + addressLine2: this.order.customer.address.streetAddress2, + city: this.order.customer.address.city, + state: this.order.customer.address.state, + zipCode: this.order.customer.address.zipCode, + country: "US" // TODO set from store + }, + homePhone: { + number: this.order.customer.phoneNumber + } + }, + caller: { + homePhone: {} + }, + policyInfo: { + policyNumber: this.order.policy.policyNumber, + safelitePolicy: { + policies: [] + } + }, + lossInfo: { + dateOfLoss: this.order.policy.dateOfLoss, + // TODO set from store or assume based on user info? + location: { + city: "Somersworth", + state: "NH", + country: "US" + }, + vehicle: { + year: this.order.vehicle.year.toString(), + make: this.order.vehicle.make, + model: this.order.vehicle.model, + vin: this.order.vehicle.vin + }, + }, + // TODO is damage cause sufficient? + damageDescription: this.order.policy.damageCause } }); return response; From 16595c0d8895a095a6a84314d4c814d827c0be04 Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Wed, 21 Jun 2023 15:03:35 -0400 Subject: [PATCH 04/20] refactored to get rid of the !important --- .../site-sub-header/site-sub-header.vue | 22 ++++++++++++++----- .../vehicle-selection/vehicle-selection.vue | 6 +---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/iss-components/site-sub-header/site-sub-header.vue b/src/iss-components/site-sub-header/site-sub-header.vue index 2d5f7342..8d910ac2 100644 --- a/src/iss-components/site-sub-header/site-sub-header.vue +++ b/src/iss-components/site-sub-header/site-sub-header.vue @@ -31,7 +31,8 @@ import buttonBack from "@/iss-components/site-sub-header/button-back/button-back cmsWidgetName: String, hasBackButton: Boolean, justification: String, - issContainingPage: String + issContainingPage: String, + darkGraySubText: Boolean, }, computed: { content() { @@ -53,9 +54,15 @@ import buttonBack from "@/iss-components/site-sub-header/button-back/button-back 'justify-content-center'; }, alternateFormatting() { - return (this.issContainingPage?.toLowerCase() === 'service-packages') ? - 'service-packages-subtext mt-4 mb-2 px-5' : - 'small'; + //override for service-packages unique style + if (this.issContainingPage?.toLowerCase() === 'service-packages') + { + return 'service-packages-subtext mt-4 mb-2 px-5'; + } + else + { + return this.darkGraySubText ? "dark-gray" : "light-gray"; + } } }, methods: { @@ -84,9 +91,14 @@ import buttonBack from "@/iss-components/site-sub-header/button-back/button-back color: inherit; } } - p.small { + p.light-gray { color: $gray-550; } + + p.dark-gray { + color: $darker-gray; + } + p.service-packages-subtext { font-weight: 500 !important; line-height: 24px; diff --git a/src/layouts/vehicle-selection/vehicle-selection.vue b/src/layouts/vehicle-selection/vehicle-selection.vue index 0914aef1..d0996a69 100644 --- a/src/layouts/vehicle-selection/vehicle-selection.vue +++ b/src/layouts/vehicle-selection/vehicle-selection.vue @@ -12,6 +12,7 @@ cmsWidgetName="SiteSubHeaderWidget" class="siteSubHeader" justification="center" + darkGraySubText /> Date: Wed, 21 Jun 2023 16:14:49 -0400 Subject: [PATCH 05/20] Adding deductible setting logic --- src/constants/endorsement-options.js | 9 +++ src/helpers/coverage-statement-helper.js | 37 ++++++++++++ .../coverage-statement/coverage-statement.vue | 57 +++---------------- .../policy-vehicles/policy-vehicles.vue | 33 +++++++++-- src/store/index.js | 34 +++++++---- 5 files changed, 104 insertions(+), 66 deletions(-) create mode 100644 src/constants/endorsement-options.js create mode 100644 src/helpers/coverage-statement-helper.js diff --git a/src/constants/endorsement-options.js b/src/constants/endorsement-options.js new file mode 100644 index 00000000..c343da16 --- /dev/null +++ b/src/constants/endorsement-options.js @@ -0,0 +1,9 @@ +const endorsementOptions = { + EDUCATOR: "Educator", + OEM_APPROVED: "OEM Approved", + FULL_GLASS: "Full Glass Coverage", + PARKING_GUARD: "Parking Guard", + REPAIR_WAIVED: "Repair Waived" +}; + +export { endorsementOptions }; \ No newline at end of file diff --git a/src/helpers/coverage-statement-helper.js b/src/helpers/coverage-statement-helper.js new file mode 100644 index 00000000..187f1ea7 --- /dev/null +++ b/src/helpers/coverage-statement-helper.js @@ -0,0 +1,37 @@ +import { useMainStore } from '@/store'; +import { coverageStatuses } from '@/constants/coverage-statuses'; + +// TODO description +export async function getRegisterClaimResponse() { + try { + const registerClaimResponse = await useMainStore().registerClaim(); + const promiseResultMap = [ + { + resultKey: 'registerClaimResponse', + promise: registerClaimResponse + }, + ]; + + const resultMap = await settleAllPromises(promiseResultMap); + return resultMap.registerClaimResponse; + } + catch(responseError) { + return { + error: { + status: responseError.status + } + } + } +} + +// Deductible/ITAC, No Comp, and Not Verified +// Still need No Comp, ITAC, and Deductible +export function setInsuranceCoverageValues(registerClaimResponse) { + const registerClaimFailed = registerClaimResponse.error; + if (useMainStore().isClaimRegistrationRequired) { + useMainStore().payment.insuranceCoverage.isVerified = !registerClaimFailed; + useMainStore().payment.insuranceCoverage.coverageStatus = registerClaimFailed + ? coverageStatuses.PENDING + : coverageStatuses.VERIFIED; + } +} diff --git a/src/layouts/coverage-statement/coverage-statement.vue b/src/layouts/coverage-statement/coverage-statement.vue index af77b84d..c785b039 100644 --- a/src/layouts/coverage-statement/coverage-statement.vue +++ b/src/layouts/coverage-statement/coverage-statement.vue @@ -58,7 +58,7 @@ import { settleAllPromises } from '@/helpers/layout-helper'; import { getDamageString } from '@/helpers/damage-helper.js'; import { useMainStore } from "@/store"; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; -import { coverageStatuses } from '../../constants/coverage-statuses'; +import { getRegisterClaimResponse, setInsuranceCoverageValues } from '@/helpers/coverage-statement-helper'; export default { name: 'coverage-statement', @@ -127,13 +127,12 @@ export default { next((vm) => { vm.setCmsContent(resultMap.cmsContent); }); - }, - async mounted() { - let registerClaimResponse = null; - if (useMainStore().isClaimRegistrationRequired){ - registerClaimResponse = await this.getRegisterClaimResponse(); - } - this.setInsuranceCoverageValues(registerClaimResponse); + + let registerClaimResponse = null; + if (useMainStore().isClaimRegistrationRequired){ + registerClaimResponse = await getRegisterClaimResponse(); + } + setInsuranceCoverageValues(registerClaimResponse); }, methods: { arePagePrerequisitesValid() { @@ -142,48 +141,6 @@ export default { } return false; }, - - async getRegisterClaimResponse() { - try { - registerClaimResponse = await useMainStore().registerClaim(); - const promiseResultMap = [ - { - resultKey: 'registerClaimResponse', - promise: registerClaimResponse - }, - ]; - - const resultMap = await settleAllPromises(promiseResultMap); - return resultMap.registerClaimResponse; - } - catch(responseError) { - return { - error: { - status: responseError.status - } - } - } - }, - - // TODO wait for confirmation from Jeremy - setInsuranceCoverageValues(registerClaimResponse) { - // null => claim reg not required - // success => verified - // failed => not verified - - const registerClaimFailed = registerClaimResponse.error; - if (useMainStore().isClaimRegistrationRequired) { - useMainStore().payment.insuranceCoverage.isVerified = !registerClaimFailed; - useMainStore().payment.insuranceCoverage.coverageStatus = registerClaimFailed - ? coverageStatuses.PENDING - : coverageStatuses.VERIFIED; // TODO include no comp case as well - } - else { // TODO confirm - useMainStore().payment.insuranceCoverage.isVerified = true; - // What about no comp??? - useMainStore().payment.insuranceCoverage.coverageStatus = coverageStatuses.VERIFIED; - } - }, async forwardButtonAction() { return this.navigateForward(); diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue index a85cc583..48d585ea 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.vue +++ b/src/layouts/policy-vehicles/policy-vehicles.vue @@ -41,7 +41,8 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js'; import { issPageValues } from "@/router/router-constants/issPage-values"; import { useMainStore } from '@/store'; import { errorMessages } from "@/constants/error-messages"; -import {vehicleSelectionOptions} from "@/constants/vehicle-selection-options"; +import { vehicleSelectionOptions } from "@/constants/vehicle-selection-options"; +import { endorsementOptions } from '../../constants/endorsement-options'; // DEFINE VALIDATION RULES defineRule("option-required", required(errorMessages.OPTION_REQUIRED)); @@ -83,7 +84,17 @@ export default { this.bailout = true; return this.navigateForward(); } - this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { vin: this.selectedVehicleVin }); + + this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { + vin: this.selectedVehicleVin, + noCoverage: this.noCoverageForSelectedVehicle, + deductible: this.deductibleForSelectedVehicle, + repairWaived: this.repairWaivedForSelectedVehicle + }); + // Update that verified + // If they go backwards select vehicle => forward => one deductible => back to vehicle selection => forward again => right info + // backwards => vehicle unverified => clear coverage info + // keep this in mind this.mainStore.updateVehicle(this.vehicleFromLookup); } return this.navigateForward(); @@ -145,8 +156,22 @@ export default { }, VehiclesFromApi() { return useMainStore().pageData(issPageValues.POLICY_VEHICLES); - }, - }, + }, + noCoverageForSelectedVehicle() { + const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + return vehicle.coverages.length == 0; + }, + deductibleForSelectedVehicle() { + const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + return vehicle?.coverages?.length == 0 ?? true + ? 0 + : vehicle.coverages[0].deductible; + }, + repairWaivedForSelectedVehicle() { + const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + return vehicle.endorsements?.includes(endorsementOptions.REPAIR_WAIVED) ?? false; + } + }, components: { siteHeader, siteFooter, diff --git a/src/store/index.js b/src/store/index.js index 012803e4..e0e18fdd 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -50,11 +50,13 @@ const getDefaultState = () => { damageState: null, damageCity: null, isDamageGlassOnly: null, - // TODO set these in code - deductable: { - repair: null, // numerical value; how much customer owes on deductable in repair case - replace: null // numerical value; how much customer owes on deductible in replace case - } + noCoverage: null, + deductible: { + // if repair waived, then 0, otherwise same as other + 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, + }, + endorsement: [] // List of endorsement_options }, customer: { address: { @@ -396,11 +398,10 @@ export const useMainStore = defineStore({ }, lossInfo: { dateOfLoss: this.order.policy.dateOfLoss, - // TODO set from store or assume based on user info? location: { - city: "Somersworth", - state: "NH", - country: "US" + city: this.order.policy.damageCity, + state: this.order.policy.damageState, + country: "US" // TODO set from store }, vehicle: { year: this.order.vehicle.year.toString(), @@ -409,7 +410,6 @@ export const useMainStore = defineStore({ vin: this.order.vehicle.vin }, }, - // TODO is damage cause sufficient? damageDescription: this.order.policy.damageCause } }); @@ -665,7 +665,7 @@ export const useMainStore = defineStore({ } }); }, - + // TODO when is this called? setVehicle() { return globalMethods .callHttpClient({ @@ -750,6 +750,7 @@ export const useMainStore = defineStore({ this.order.lineItems.vaps = partsData; }, + // TODO Where all will this be called and could it be an issue? updateVehicle(vehicle) { // Assuming that the method caller pass all the properties. // otherwise need to check for undefined for every property. @@ -765,6 +766,12 @@ export const useMainStore = defineStore({ this.order.vehicle.imageVifNumber = vehicle.imageVifNumber; this.order.vehicle.imageColor = vehicle.imageVifColor; + this.order.policy.noCoverage = vehicle.noCoverage; + this.order.policy.deductible.replace = vehicle.deductible; + this.order.policy.deductible.repair = vehicle?.repairWaived ?? false + ? 0 + : vehicle.deductible; + this.resetSupportingItemsState(); this.resetVapsState(); }, @@ -913,7 +920,7 @@ export const useMainStore = defineStore({ this.applicationUser.pageData[pageData.page] = pageData.data; }, updatePolicyData(welcomePageModel) - { + { // TODO add to this? this.order.policy.policyNumber = welcomePageModel?.policyNumber; this.order.policy.policyZipCode = welcomePageModel?.policyZipCode; this.order.policy.dateOfLoss = welcomePageModel?.dateOfLoss; @@ -923,6 +930,9 @@ export const useMainStore = defineStore({ this.order.policy.isDamageGlassOnly = welcomePageModel?.isDamageGlassOnly; this.order.customer.phoneNumber = welcomePageModel?.phoneNumber; this.order.customer.emailAddress = welcomePageModel?.email; + if (!this.issConfig.isClaimRegistrationRequired){ + this.order.insuranceCoverage.isVerified = true; + } }, updatePolicyHolderDetails(customerQuestions) { From 0b4d626d90814af3b262b9d0da9c99ab73819d94 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Wed, 21 Jun 2023 17:14:33 -0400 Subject: [PATCH 06/20] Minor adjustments --- .../policy-vehicles/policy-vehicles.vue | 35 ++++++++++--------- src/store/index.js | 8 ++--- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue index 48d585ea..c0aa9e33 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.vue +++ b/src/layouts/policy-vehicles/policy-vehicles.vue @@ -50,9 +50,11 @@ export default { name: "policy-vehicles", mixins: [BaseFormMixin], data() { - return { - selectedVehicleVin: "", - bailout: false + const policyVehicles = useMainStore().pageData(issPageValues.POLICY_VEHICLES); + return { + policyVehicles: policyVehicles, + selectedVehicleVin: policyVehicles.length == 0 ? "" : policyVehicles[0].vin, + bailout: false } }, async beforeRouteEnter(to, from, next) @@ -64,13 +66,14 @@ export default { { resultKey: "cmsContent", promise: cmsContentPromise, - },]; - //use resultMap to populate layout content. - let resultMap = await settleAllPromises(promiseResultMap); - next((vm) => { - vm.setCmsContent(resultMap.cmsContent); - }); - }, + }, + ]; + //use resultMap to populate layout content. + let resultMap = await settleAllPromises(promiseResultMap); + next((vm) => { + vm.setCmsContent(resultMap.cmsContent); + }); + }, methods: { backButtonAction() { @@ -95,6 +98,7 @@ export default { // If they go backwards select vehicle => forward => one deductible => back to vehicle selection => forward again => right info // backwards => vehicle unverified => clear coverage info // keep this in mind + console.log("Going to update vehicle"); this.mainStore.updateVehicle(this.vehicleFromLookup); } return this.navigateForward(); @@ -139,7 +143,7 @@ export default { computed:{ VehiclesForQuestions() { // Map API result data, to address-vehicles data structure - const vehicles = this.VehiclesFromApi; + const vehicles = this.policyVehicles; const mappedData = vehicles.map((v) => { const maskSymbol = "X"; const vinStart = maskSymbol.repeat(v.vin.length - 6); @@ -154,21 +158,18 @@ export default { }); return mappedData; }, - VehiclesFromApi() { - return useMainStore().pageData(issPageValues.POLICY_VEHICLES); - }, noCoverageForSelectedVehicle() { - const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); return vehicle.coverages.length == 0; }, deductibleForSelectedVehicle() { - const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); return vehicle?.coverages?.length == 0 ?? true ? 0 : vehicle.coverages[0].deductible; }, repairWaivedForSelectedVehicle() { - const vehicle = this.VehiclesFromApi.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); + const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); return vehicle.endorsements?.includes(endorsementOptions.REPAIR_WAIVED) ?? false; } }, diff --git a/src/store/index.js b/src/store/index.js index e0e18fdd..9beed8c2 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -52,7 +52,6 @@ const getDefaultState = () => { isDamageGlassOnly: null, noCoverage: null, deductible: { - // if repair waived, then 0, otherwise same as other 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, }, @@ -750,11 +749,9 @@ export const useMainStore = defineStore({ this.order.lineItems.vaps = partsData; }, - // TODO Where all will this be called and could it be an issue? updateVehicle(vehicle) { // Assuming that the method caller pass all the properties. // otherwise need to check for undefined for every property. - this.order.vehicle.carId = vehicle.carId; this.order.vehicle.category = vehicle.category; this.order.vehicle.year = vehicle.year; @@ -766,11 +763,10 @@ export const useMainStore = defineStore({ this.order.vehicle.imageVifNumber = vehicle.imageVifNumber; this.order.vehicle.imageColor = vehicle.imageVifColor; + // These could be undefined this.order.policy.noCoverage = vehicle.noCoverage; this.order.policy.deductible.replace = vehicle.deductible; - this.order.policy.deductible.repair = vehicle?.repairWaived ?? false - ? 0 - : vehicle.deductible; + this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible; this.resetSupportingItemsState(); this.resetVapsState(); From 6b76beb5cb4a74de0345468ba72ef43aa55b60ef Mon Sep 17 00:00:00 2001 From: Jason Wheeler Date: Thu, 22 Jun 2023 14:02:24 -0400 Subject: [PATCH 07/20] Cleaning up navigation references to these pages that were removed. --- src/router/router-constants/issPage-values.js | 4 -- src/router/router-constants/routing-table.js | 52 ------------------- 2 files changed, 56 deletions(-) diff --git a/src/router/router-constants/issPage-values.js b/src/router/router-constants/issPage-values.js index 763994ac..53544f51 100644 --- a/src/router/router-constants/issPage-values.js +++ b/src/router/router-constants/issPage-values.js @@ -24,11 +24,7 @@ export const issPageValues = { SCHEDULE_PAGE: 'schedule-page', VEHICLE_DAMAGE: 'vehicle-damage', VEHICLE_LOOKUP: 'vehicle-lookup', - VEHICLE_MAKE: 'vehicle-make', - VEHICLE_MODEL: 'vehicle-model', VEHICLE_PARTS: 'vehicle-parts', - VEHICLE_STYLE: 'vehicle-style', - VEHICLE_YEAR: 'vehicle-year', VEHICLE_SELECTION: 'vehicle-selection', VIN_LOOKUP: 'vin-lookup', TPA_SUBMIT: 'tpa-submit', diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 7d3945a0..bebaad84 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -17,58 +17,6 @@ const routingTable = function(store) { } ] }, - { - issPageValue: issPageValues.VEHICLE_YEAR, - maps: [ - { - scenario: navigationScenarios.CLICKED_BACK, - destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS - }, - { - scenario: navigationScenarios.SELECTED_YEAR, - destinationIssPageValue: issPageValues.VEHICLE_MAKE - } - ] - }, - { - issPageValue: issPageValues.VEHICLE_MAKE, - maps: [ - { - scenario: navigationScenarios.CLICKED_BACK, - destinationIssPageValue: issPageValues.VEHICLE_YEAR - }, - { - scenario: navigationScenarios.SELECTED_MAKE, - destinationIssPageValue: issPageValues.VEHICLE_MODEL - } - ] - }, - { - issPageValue: issPageValues.VEHICLE_MODEL, - maps: [ - { - scenario: navigationScenarios.CLICKED_BACK, - destinationIssPageValue: issPageValues.VEHICLE_MAKE - }, - { - scenario: navigationScenarios.SELECTED_MODEL, - destinationIssPageValue: issPageValues.VEHICLE_STYLE - } - ] - }, - { - issPageValue: issPageValues.VEHICLE_STYLE, - maps: [ - { - scenario: navigationScenarios.CLICKED_BACK, - destinationIssPageValue: issPageValues.VEHICLE_MODEL - }, - { - scenario: navigationScenarios.SELECTED_STYLE, - destinationIssPageValue: issPageValues.VEHICLE_DAMAGE - } - ] - }, { issPageValue: issPageValues.VEHICLE_DAMAGE, maps: [ From 662b25e8c43abbca5dc3cbe583b014d6d60a2afa Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 26 Jun 2023 13:55:06 -0400 Subject: [PATCH 08/20] Updating store tests --- src/helpers/coverage-statement-helper.js | 36 +- src/helpers/data-generation.js | 28 ++ .../policy-vehicles/policy-vehicles.vue | 18 +- src/store/index.js | 33 +- src/store/store.spec.js | 380 +++++++++++++----- 5 files changed, 348 insertions(+), 147 deletions(-) create mode 100644 src/helpers/data-generation.js diff --git a/src/helpers/coverage-statement-helper.js b/src/helpers/coverage-statement-helper.js index 187f1ea7..772f3149 100644 --- a/src/helpers/coverage-statement-helper.js +++ b/src/helpers/coverage-statement-helper.js @@ -1,37 +1,27 @@ import { useMainStore } from '@/store'; import { coverageStatuses } from '@/constants/coverage-statuses'; -// TODO description export async function getRegisterClaimResponse() { - try { - const registerClaimResponse = await useMainStore().registerClaim(); - const promiseResultMap = [ - { - resultKey: 'registerClaimResponse', - promise: registerClaimResponse - }, - ]; + const registerClaimResponse = await useMainStore().registerClaim(); + const promiseResultMap = [ + { + resultKey: 'registerClaimResponse', + promise: registerClaimResponse + }, + ]; - const resultMap = await settleAllPromises(promiseResultMap); - return resultMap.registerClaimResponse; - } - catch(responseError) { - return { - error: { - status: responseError.status - } - } - } + const resultMap = await settleAllPromises(promiseResultMap); + return resultMap.registerClaimResponse; } -// Deductible/ITAC, No Comp, and Not Verified -// Still need No Comp, ITAC, and Deductible export function setInsuranceCoverageValues(registerClaimResponse) { - const registerClaimFailed = registerClaimResponse.error; + const registerClaimFailed = registerClaimResponse.isError; if (useMainStore().isClaimRegistrationRequired) { useMainStore().payment.insuranceCoverage.isVerified = !registerClaimFailed; useMainStore().payment.insuranceCoverage.coverageStatus = registerClaimFailed ? coverageStatuses.PENDING - : coverageStatuses.VERIFIED; + : useMainStore().policy.noCoverage + ? coverageStatuses.NO_COMP + : coverageStatuses.VERIFIED; } } diff --git a/src/helpers/data-generation.js b/src/helpers/data-generation.js new file mode 100644 index 00000000..b1371713 --- /dev/null +++ b/src/helpers/data-generation.js @@ -0,0 +1,28 @@ +import { randomUUID } from "node:crypto"; + +export function getRandomString(minLength = 1, maxLength = 100) { + const length = getRandomInt(minLength, maxLength); + let result = ''; + const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + const charactersLength = characters.length; + for (let i = 0; i < length; i++) { + result += characters.charAt(Math.floor(Math.random() * charactersLength)); + } + return result; +} + +export function getRandomInt(min = 0, max = 1000) { + min = Math.ceil(min); + max = Math.floor(max); + return Math.floor(Math.random() * (max - min) + min); // The maximum is exclusive and the minimum is inclusive +} + +export function getRandomGuid() { + return randomUUID(); +} + +export function getRandomBoolean() { + const bools = [true, false]; + const index = getRandomInt(0,2); + return bools[index]; +} \ No newline at end of file diff --git a/src/layouts/policy-vehicles/policy-vehicles.vue b/src/layouts/policy-vehicles/policy-vehicles.vue index c0aa9e33..1e5c766e 100644 --- a/src/layouts/policy-vehicles/policy-vehicles.vue +++ b/src/layouts/policy-vehicles/policy-vehicles.vue @@ -98,7 +98,6 @@ export default { // If they go backwards select vehicle => forward => one deductible => back to vehicle selection => forward again => right info // backwards => vehicle unverified => clear coverage info // keep this in mind - console.log("Going to update vehicle"); this.mainStore.updateVehicle(this.vehicleFromLookup); } return this.navigateForward(); @@ -160,13 +159,20 @@ export default { }, noCoverageForSelectedVehicle() { const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); - return vehicle.coverages.length == 0; + return vehicle.coverages?.length == 0 ?? true; }, deductibleForSelectedVehicle() { - const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); - return vehicle?.coverages?.length == 0 ?? true - ? 0 - : vehicle.coverages[0].deductible; + const vehicle = this.policyVehicles.find((vehicle) => { return vehicle?.vin == this.selectedVehicleVin; }); + if (!vehicle){ + return undefined; + } + // return 0 in (vehicle.coverages ?? []) + // ? vehicle?.coverages[0].deductible + // : 0; + + return vehicle.coverages?.length ?? false + ? vehicle?.coverages[0].deductible + : 0; }, repairWaivedForSelectedVehicle() { const vehicle = this.policyVehicles.find((vehicle) => { return vehicle.vin == this.selectedVehicleVin; }); diff --git a/src/store/index.js b/src/store/index.js index 9beed8c2..4b2a0f69 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -134,6 +134,7 @@ export const useMainStore = defineStore({ damage: (state) => state.order.damage, lineItems: (state) => state.order.lineItems, payment: (state) => state.order.payment, + policy: (state) => state.order.policy, hasAnyNonWindshieldGlassParts: (state) => !state.order.policy.isDamageGlassOnly, isClaimRegistrationRequired: (state) => state.issConfig.isClaimRegistrationRequired, eventBusItem: (state) => ( eventCategory, eventSubCategory) => { @@ -414,11 +415,9 @@ export const useMainStore = defineStore({ }); return response; } catch (responseError) { - return { - error: { - status: responseError.status - } - }; + return Promise.resolve({ + isError: true + }) } }, async lookupVinByPlate(licensePlate, licenseState) { @@ -554,7 +553,7 @@ export const useMainStore = defineStore({ console.error(error); return []; }); - }, + }, async getRainDefense() { return globalMethods @@ -664,18 +663,18 @@ export const useMainStore = defineStore({ } }); }, - // TODO when is this called? + setVehicle() { return globalMethods - .callHttpClient({ - methods: endpoints.GetVehicle.method, - endpoint: `${endpoints.GetVehicle.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}/${this.order.vehicle.style}`, - payload: {} - }) - .then((response) => { - this.updateVehicle(response.data); - return response; - }); + .callHttpClient({ + methods: endpoints.GetVehicle.method, + endpoint: `${endpoints.GetVehicle.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}/${this.order.vehicle.style}`, + payload: {} + }) + .then((response) => { + this.updateVehicle(response.data); + return response; + }); }, saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { @@ -752,7 +751,7 @@ export const useMainStore = defineStore({ updateVehicle(vehicle) { // Assuming that the method caller pass all the properties. // otherwise need to check for undefined for every property. - this.order.vehicle.carId = vehicle.carId; + this.vehicle.carId = vehicle.carId; this.order.vehicle.category = vehicle.category; this.order.vehicle.year = vehicle.year; this.order.vehicle.make = vehicle.make; diff --git a/src/store/store.spec.js b/src/store/store.spec.js index e282f849..e8d9a3b2 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1,8 +1,9 @@ import { useMainStore } from '@/store'; import { createApp } from 'vue'; -import { createPinia } from "pinia"; +import { setActivePinia, createPinia } from "pinia"; import globalMethods from "@/global-methods"; import App from '@/App.vue'; +import { getRandomString, getRandomGuid, getRandomInt, getRandomBoolean } from '../helpers/data-generation'; describe("Store", () => { @@ -14,6 +15,7 @@ describe("Store", () => { vueApp.use(pinia); beforeEach(() => { + setActivePinia(createPinia()); store = useMainStore(); store.applicationUser.eventBus = []; jest.resetAllMocks(); @@ -27,31 +29,47 @@ describe("Store", () => { }); it("Should add events to the bus", () => { + // Arrange + const category = getRandomString(1, 25); + const subCategory = getRandomString(5, 20); + const isDismissible = getRandomBoolean(); + const copy = getRandomString(5, 25); + const headline = getRandomString(5, 25); + const type = getRandomString(5, 15); let event = { - category: "TestCategory", - subCategory: "TestSubCategory", + category: category, + subCategory: subCategory, eventValue: { - isDismissible: true, - messageCopy: "You can get a quote by starting on this page.", - messageHeadline: "We're sorry, something went wrong.", - type: "testType", + isDismissible: isDismissible, + messageCopy: copy, + messageHeadline: headline, + type: type, }, }; + // Act store.addEventToBus(event); + // Assert expect(store.applicationUser.eventBus[0]).toEqual(event); }); it("Should remove events from the bus", () => { + // Arrange + const category = getRandomString(1, 25); + const subCategory = getRandomString(5, 20); + const isDismissible = getRandomBoolean(); + const copy = getRandomString(5, 25); + const headline = getRandomString(5, 25); + const type = getRandomString(5, 15); let event = { - category: "TestCategory", - subCategory: "TestSubCategory", + category: category, + subCategory: subCategory, eventValue: { - isDismissible: true, - messageCopy: "You can get a quote by starting on this page.", - messageHeadline: "We're sorry, something went wrong.", - type: "testType", + isDismissible: isDismissible, + messageCopy: copy, + messageHeadline: headline, + type: type, }, }; @@ -59,164 +77,324 @@ describe("Store", () => { expect(store.applicationUser.eventBus.length).toBe(1); + // Act store.removeEventFromBus({ category: event.category, subCategory: event.subCategory }) + // Assert expect(store.applicationUser.eventBus.length).toBe(0); }); it("Should return correct event using the getter function eventBusItem", () => { + // Arrange + const category = getRandomString(1, 25); + const subCategory = getRandomString(5, 20); + const isDismissible = getRandomBoolean(); + const copy = getRandomString(5, 25); + const headline = getRandomString(5, 25); + const type = getRandomString(5, 15); let event = { - category: "TestCategory", - subCategory: "TestSubCategory", + category: category, + subCategory: subCategory, eventValue: { - isDismissible: true, - messageCopy: "You can get a quote by starting on this page.", - messageHeadline: "We're sorry, something went wrong.", - type: "testType", + isDismissible: isDismissible, + messageCopy: copy, + messageHeadline: headline, + type: type, }, }; store.addEventToBus(event); + // Act const actual = store.eventBusItem(event.category, event.subCategory) + // Assert expect(actual).toEqual(event.eventValue); }); it("UpdateVehicle should merge vehicle with response object", () => { - store.order.vehicle = { - year: 2020, - make: "Honda", - model: "Civic", - style: "4 door sedan", - carId: null, - category: null, - vin: null, - imageUrl: null, - imageVifNumber: null, - imageColor: null, + // Arrange + const carId = getRandomString(10,14); + const category = getRandomString(3,7); + const year = getRandomInt(1960, 2023); + const make = getRandomString(4,10); + const model = getRandomString(4,10); + const style = getRandomString(4,15); + const imageUrl = getRandomString(50,100); + const imageVifNumber = getRandomInt(10000,99999).toString(); + const imageColor = getRandomString(4,10); + const providedVehicle = { + carId: carId, + category: category, + year: year, + make: make, + model: model, + style: style, + imageUrl: imageUrl, + imageVifNumber: imageVifNumber, + imageVifColor: imageColor }; - const response = {data: { - "carId": "CR00069299", - "category": "CAR", - "year": 2020, - "make": "Honda", - "model": "Civic", - "style": "4 door sedan", - "imageUrl": "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13996/13996_cc0320_032_WX.jpg", - "imageVifNumber": "13996", - "imageVifColor": "white" + const expectedVehicle = { + carId: carId, + category: category, + year: year, + make: make, + model: model, + style: style, + imageUrl: imageUrl, + imageVifNumber: imageVifNumber, + imageColor: imageColor + } + + // Act + store.updateVehicle(providedVehicle); + + // Assert + expect(store.order.vehicle).toMatchObject(expectedVehicle); + }); + + it("UpdateVehicle should set policy values appropriately with repair waived", () => { + // Arrange + const noCoverage = getRandomBoolean(); + const deductible = getRandomInt(1,500); + const vehicle = { + noCoverage: noCoverage, + deductible: deductible, + repairWaived: true + }; + + const expectedPolicy = { + noCoverage: noCoverage, + deductible: { + replace: deductible, + repair: 0 } }; - store.updateVehicle(response.data); + // Act + store.updateVehicle(vehicle); - expect(store.order.vehicle.imageUrl).toEqual(response.data.imageUrl); - expect(store.order.vehicle.imageVifNumber).toEqual(response.data.imageVifNumber); - expect(store.order.vehicle.style).toEqual(response.data.style); + // Assert + expect(store.order.policy).toMatchObject(expectedPolicy); }); - it("setVehicle should call globalMethods.callHttpClient", () => { - store.order.vehicle = jest.fn(); + it("UpdateVehicle should set policy values appropriately with repair not waived", () => { + // Arrange + const noCoverage = getRandomBoolean(); + const deductible = getRandomInt(1,500); + const vehicle = { + noCoverage: noCoverage, + deductible: deductible, + repairWaived: false + }; - const response = {data: { - "carId": "CR00069299", - "category": "CAR", - "year": 2020, - "make": "Honda", - "model": "Civic", - "style": "4 door sedan", - "imageUrl": "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13996/13996_cc0320_032_WX.jpg", - "imageVifNumber": "13996", - "imageVifColor": "white" + const expectedPolicy = { + noCoverage: noCoverage, + deductible: { + replace: deductible, + repair: deductible + } + }; + + // Act + store.updateVehicle(vehicle); + + // Assert + expect(store.order.policy).toMatchObject(expectedPolicy); + }); + + // TODO update test to work also checking store values + it("setVehicle should call globalMethods.callHttpClient", () => { + // Arrange + const carId = getRandomString(10,14); + const category = getRandomString(3,7); + const year = getRandomInt(1960, 2023); + const make = getRandomString(4,10); + const model = getRandomString(4,10); + const style = getRandomString(4,15); + const imageUrl = getRandomString(50,100); + const imageVifNumber = getRandomInt(10000,99999).toString(); + const imageColor = getRandomString(4,10); + const response = { + data: { + carId: carId, + category: category, + year: year, + make: make, + model: model, + style: style, + imageUrl: imageUrl, + imageVifNumber: imageVifNumber, + imageVifColor: imageColor } }; globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response)); - - store.setVehicle(); - - expect(globalMethods.callHttpClient).toHaveBeenCalled(); - }); - - it("saveVehicleDamage, should update damage", () => { - // Arrange - store.order.damage = { - glassToReplace: [{ glassName: "Single", glassLocation: "Windshield" }], - }; // Act - store.saveVehicleDamage( false, - [{ glassName: "Rear", glassLocation: "quarter" }], - 0); + const returned = store.setVehicle(); // Assert - expect(store.order.damage.glassToReplace).toEqual([{ glassName: "Rear", glassLocation: "quarter" }]); - expect(store.order.damage.isRepair).toEqual(false); - expect(store.order.damage.numberOfChips).toEqual(null); + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(returned).resolves.toMatchObject(response); + }); + + it("saveVehicleDamage with windshield repair should update damage with number of chips not null", () => { + // Arrange + const glassName = getRandomString(4,10); + const glassLocation = getRandomString(5,15); + const isWindshieldRepair = true; + const selectedGlassToReplace = [{ + glassName: glassName, + glassLocation: glassLocation + }]; + const chipCount = getRandomInt(0,3).toString(); + + // Act + store.saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, chipCount); + + // Assert + expect(store.order.damage.glassToReplace).toEqual(selectedGlassToReplace); + expect(store.order.damage.isRepair).toEqual(isWindshieldRepair); + expect(store.order.damage.numberOfChips).toEqual(chipCount); + }); + + it("saveVehicleDamage without windshield repair should update damage with number of chips null", () => { + // Arrange + const glassName = getRandomString(4,10); + const glassLocation = getRandomString(5,15); + const isWindshieldRepair = false; + const selectedGlassToReplace = [{ + glassName: glassName, + glassLocation: glassLocation + }]; + const chipCount = getRandomInt(0,3); + + const expectedChipCount = null; + + // Act + store.saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, chipCount); + + // Assert + expect(store.order.damage.glassToReplace).toEqual(selectedGlassToReplace); + expect(store.order.damage.isRepair).toEqual(isWindshieldRepair); + expect(store.order.damage.numberOfChips).toEqual(expectedChipCount); }); it("should return registration data if available", () => { //Arrange + const streetAddress = getRandomString(5,15); + const city = getRandomString(5,15); + const state = getRandomString(5,10); + const zipCode = getRandomInt(10000,99999).toString(); + const firstName = getRandomString(5,20); + const lastName = getRandomString(5,20); const expected = { addressQuestions: { - streetAddress: "test", - city: "city", - state: "state", - zipCode: "zip", + streetAddress: streetAddress, + city: city, + state: state, + zipCode: zipCode, }, - firstName: "1stName", - lastName: "Surname", + firstName: firstName, + lastName: lastName, } store.order.vehicle.registration = { licensePlate: null, - address: "test", - city: "city", - state: "state", - zipCode: "zip", - firstName: "1stName", - lastName: "Surname", + address: streetAddress, + city: city, + state: state, + zipCode: zipCode, + firstName: firstName, + lastName: lastName, }; //Act const actual = store.customerData; - //Assert + //Assert expect(actual).toEqual(expected); }); it("should return customer data if registration data unavailable", () => { //Arrange + const address = getRandomString(1,25); + const city = getRandomString(5,20); + const state = getRandomString(4,20); + const zipCode = getRandomInt(10000, 99999).toString(); + const firstName = getRandomString(5,25); + const lastName = getRandomString(5,25); const expected = { addressQuestions: { - streetAddress: "test", - city: "city", - state: "state", - zipCode: "zip", + streetAddress: address, + city: city, + state: state, + zipCode: zipCode, }, - firstName: "1stName", - lastName: "Surname", + firstName: firstName, + lastName: lastName, } store.order.vehicle.registration.address = null; store.order.customer = { - licensePlate: null, - address: "test", - city: "city", - state: "state", - zipCode: "zip", - firstName: "1stName", - lastName: "Surname", + address: { + streetAddress: address, + city: city, + state: state, + zipCode: zipCode + }, + firstName: firstName, + lastName: lastName }; //Act const actual = store.customerData; - //Assert - expect(actual).toEqual(expected); + //Assert + expect(actual).toMatchObject(expected); }); + describe("registerClaim method", () => { + it("successful response results in expected data returned", () => { + // Arrange + const response = { + data: { + claimantId: null, + claimNumber: getRandomString(9, 9), + correlationId: getRandomGuid(), + isSuccess: true, + isError: false, + successMessage: getRandomString(9, 9), + deductible: 0 + } + }; + + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response)); + + // Act + const registerClaimPromise = store.registerClaim(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(registerClaimPromise).resolves.toMatchObject(response); + expect(registerClaimPromise).resolves.not.toHaveProperty('error'); + }); + + it("Call to client returns exception, resulting in object with error property being returned", () => { + // Arrange + globalMethods.callHttpClient = jest.fn().mockImplementation(() => { + throw new Error('Register claim call failed'); + }); + + // Act + const registerClaimPromise = store.registerClaim(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(registerClaimPromise).resolves.toHaveProperty('error'); + }); + }) }); \ No newline at end of file From 270d26dc5187c839b26b5c25cb6fb1cf73c51223 Mon Sep 17 00:00:00 2001 From: brydon1 Date: Mon, 26 Jun 2023 15:07:05 -0400 Subject: [PATCH 09/20] Moving setInsuranceCoverageValues to store --- src/store/index.js | 12 +++++++ src/store/store.spec.js | 76 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 84 insertions(+), 4 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 4b2a0f69..bf5b1d0b 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -677,6 +677,18 @@ export const useMainStore = defineStore({ }); }, + setInsuranceCoverageValues(registerClaimResponse) { + const registerClaimFailed = registerClaimResponse.isError; + if (this.issConfig.isClaimRegistrationRequired) { + this.order.payment.insuranceCoverage.isVerified = !registerClaimFailed; + this.order.payment.insuranceCoverage.coverageStatus = registerClaimFailed + ? coverageStatuses.PENDING + : useMainStore().policy.noCoverage + ? coverageStatuses.NO_COMP + : coverageStatuses.VERIFIED; + } + }, + saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount) { const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort(); const isGlassToReplaceTheSame = diff --git a/src/store/store.spec.js b/src/store/store.spec.js index e8d9a3b2..311b235d 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -4,7 +4,7 @@ import { setActivePinia, createPinia } from "pinia"; import globalMethods from "@/global-methods"; import App from '@/App.vue'; import { getRandomString, getRandomGuid, getRandomInt, getRandomBoolean } from '../helpers/data-generation'; - +import { coverageStatuses } from "@/constants/coverage-statuses.js"; describe("Store", () => { @@ -240,6 +240,74 @@ describe("Store", () => { expect(returned).resolves.toMatchObject(response); }); + describe("setInsuranceCoverageValues method", () => { + it("claim registration not required => nothing is updated", () => { + // Arrange + store.issConfig.isClaimRegistrationRequired = false; + const registerClaimResponse = { + isError: false + }; + const oldIsVerified = null; + store.payment.insuranceCoverage.isVerified = oldIsVerified; + const oldCoverageStatus = coverageStatuses.NO_COMP; + store.payment.insuranceCoverage.coverageStatus = oldCoverageStatus; + + // Act + store.setInsuranceCoverageValues(registerClaimResponse); + + // Assert + expect(store.payment.insuranceCoverage.isVerified).toBe(oldIsVerified); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(oldCoverageStatus); + }) + + it("Register Claim fails => isVerified false and coverage status pending", () =>{ + // Arrange + store.issConfig.isClaimRegistrationRequired = true; + const registerClaimResponse = { + isError: true + }; + + // Act + store.setInsuranceCoverageValues(registerClaimResponse); + + // Assert + expect(store.payment.insuranceCoverage.isVerified).toBe(false); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.PENDING); + }) + + it("Register Claim success and no coverage => isVerified true and coverage status no comp", () => { + // Arrange + store.issConfig.isClaimRegistrationRequired = true; + const registerClaimResponse = { + isError: false + }; + store.policy.noCoverage = true; + + // Act + store.setInsuranceCoverageValues(registerClaimResponse); + + // Assert + expect(store.payment.insuranceCoverage.isVerified).toBe(true); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.NO_COMP); + }) + + it("Register Claim success and coverage => isVerified true and coverage status verified", () => { + // Arrange + store.issConfig.isClaimRegistrationRequired = true; + const registerClaimResponse = { + isError: false + }; + store.policy.noCoverage = false; + + // Act + store.setInsuranceCoverageValues(registerClaimResponse); + + // Assert + expect(store.payment.insuranceCoverage.isVerified).toBe(true); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.VERIFIED); + }) + }) + it("saveVehicleDamage with windshield repair should update damage with number of chips not null", () => { // Arrange const glassName = getRandomString(4,10); @@ -249,7 +317,7 @@ describe("Store", () => { glassName: glassName, glassLocation: glassLocation }]; - const chipCount = getRandomInt(0,3).toString(); + const chipCount = getRandomInt(0,3); // Act store.saveVehicleDamage(isWindshieldRepair, selectedGlassToReplace, chipCount); @@ -380,7 +448,7 @@ describe("Store", () => { // Asserts expect(globalMethods.callHttpClient).toHaveBeenCalled(); expect(registerClaimPromise).resolves.toMatchObject(response); - expect(registerClaimPromise).resolves.not.toHaveProperty('error'); + expect(registerClaimPromise).resolves.not.toHaveProperty('isError'); }); it("Call to client returns exception, resulting in object with error property being returned", () => { @@ -394,7 +462,7 @@ describe("Store", () => { // Asserts expect(globalMethods.callHttpClient).toHaveBeenCalled(); - expect(registerClaimPromise).resolves.toHaveProperty('error'); + expect(registerClaimPromise).resolves.toHaveProperty('isError'); }); }) }); \ No newline at end of file From e9dcd9794ce83db7958c53156f78715dd97e355e Mon Sep 17 00:00:00 2001 From: Jeremy Zimmerman Date: Mon, 26 Jun 2023 16:24:41 -0400 Subject: [PATCH 10/20] Updates for the QA build. --- azure-pipelines.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c5c951a1..0453f2d9 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -175,12 +175,6 @@ stages: indexDeployVariables: __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__) __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__) - - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps - parameters: - awsCliContainer: awscli - distributionId: $(apiCfDistributionId) - paths: /* - awsProfile: $(qaDeploymentProfile) - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps parameters: awsCliContainer: awscli @@ -230,12 +224,6 @@ stages: indexDeployVariables: __VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__) __VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__) - - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps - parameters: - awsCliContainer: awscli - distributionId: $(apiCfDistributionId) - paths: /* - awsProfile: $(prodDeploymentProfile) - template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps parameters: awsCliContainer: awscli From 31b4c985f0bf599ce42514168c78d59bbb6d7e6c Mon Sep 17 00:00:00 2001 From: Jeremy Zimmerman Date: Mon, 26 Jun 2023 16:27:58 -0400 Subject: [PATCH 11/20] CF cache invalidation path update. --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0453f2d9..74a68a86 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -179,7 +179,7 @@ stages: parameters: awsCliContainer: awscli distributionId: $(cfDistributionId) - paths: /iss/* + paths: /* awsProfile: $(qaDeploymentProfile) # Prod Build/Deploy @@ -228,7 +228,7 @@ stages: parameters: awsCliContainer: awscli distributionId: $(cfDistributionId) - paths: /iss/* + paths: /* awsProfile: $(prodDeploymentProfile) - template: templates/digital/auto-tag.yml@AzureDevOps parameters: From 0b1d35eb2ae6831db1a9235027c87610a5197f22 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Tue, 27 Jun 2023 10:32:00 -0400 Subject: [PATCH 12/20] Change radio label to inline-flex to prevent 100% width. --- src/ux-components/radio/radio.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ux-components/radio/radio.vue b/src/ux-components/radio/radio.vue index af92391e..238d99f5 100644 --- a/src/ux-components/radio/radio.vue +++ b/src/ux-components/radio/radio.vue @@ -1,7 +1,7 @@