diff --git a/azure-pipelines.yml b/azure-pipelines.yml index c5c951a1..74a68a86 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -175,17 +175,11 @@ 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 distributionId: $(cfDistributionId) - paths: /iss/* + paths: /* awsProfile: $(qaDeploymentProfile) # Prod Build/Deploy @@ -230,17 +224,11 @@ 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 distributionId: $(cfDistributionId) - paths: /iss/* + paths: /* awsProfile: $(prodDeploymentProfile) - template: templates/digital/auto-tag.yml@AzureDevOps parameters: diff --git a/package-lock.json b/package-lock.json index fee29bbe..a2a2b4e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3618,9 +3618,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.7.15", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.15.tgz", - "integrity": "sha512-XnjpaI8Bgc3eBag2Aw4t2Uj/49lLBSStHWfqKvIuXD7FIrZyMLWp8KuAFHAqxMZYTF9l08N1ctUn9YNybZJVmQ==", + "version": "20.3.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.2.tgz", + "integrity": "sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==", "dev": true }, "node_modules/@types/normalize-package-data": { 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/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/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 }; diff --git a/src/digital-components/base-input-button/base-input-button.vue b/src/digital-components/base-input-button/base-input-button.vue index 8768bb8c..0c92db50 100644 --- a/src/digital-components/base-input-button/base-input-button.vue +++ b/src/digital-components/base-input-button/base-input-button.vue @@ -121,9 +121,7 @@ export default { return this.isMultiSelect ? "checkbox" : "radio"; }, buttonId() { - return `${this.groupName?.replace(" ", "-")}-${this.value - ?.toString() - ?.replace(" ", "-")}`; + return `${this.groupName}-${this.value}`.replaceAll(" ", "-"); }, isValueSelectedOnClick() { return this.isMultiSelect || this.selectingInitiatesLoad; diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue index 5679e96c..55033df7 100644 --- a/src/digital-components/button-question/button-question.vue +++ b/src/digital-components/button-question/button-question.vue @@ -31,7 +31,7 @@
+ :key="answer.value ?? answer">
- diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue index 9b1beaec..88802069 100644 --- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue +++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.vue @@ -12,7 +12,7 @@ :isWide="true" altText="" isRequired - :groupName="`${glassLocation}-${glassName}`" + :groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}`)" :validationRules="tintValidationRules">
@@ -27,7 +27,7 @@ :loaderEnabled="false" isRequired isSmallQuestionText - :groupName="`${glassLocation}-${glassName}-${selectedTint}`" + :groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}-${selectedTint}`)" :validationRules="partValidationRules" />
@@ -181,12 +181,12 @@ export default { }, AutoSelectIfSinglePart() { - if (this.partsForSelectedTint?.length > 0) + if (this.partsForSelectedTint?.length > 0) { // Check if only a single part is present for the tint and set the v-model if it is. if (this.partsForSelectedTint?.length == 1) { this.selectedPartNumber = { value: this.partsForSelectedTint[0].partNumber }; - + // //select element with matching partNumber this.$nextTick(() => { const radioInput = document.querySelector('input[value=' + this.selectedPartNumber + ']'); @@ -199,7 +199,7 @@ export default { } } }, - + // Loads the preselected values from the store. LoadPreselectedValues() { this.$nextTick(() => { @@ -208,7 +208,11 @@ export default { { this.selectedTint = this.modelValue.color; } - }); + }); + }, + + replaceAllSpaceWithDash(str) { + return String(str).replaceAll(" ", "-"); }, }, watch: { diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue index 7bd3241c..e88c5c6d 100644 --- a/src/layouts/vehicle-parts/vehicle-parts.vue +++ b/src/layouts/vehicle-parts/vehicle-parts.vue @@ -38,6 +38,7 @@ :alreadyPopulatedPartsData="alreadyPopulatedPartsData" /> -
+
@@ -8,57 +8,59 @@
- - - - - - - - - + { + next((vm) => { vm.setCmsContent(resultMap.cmsContent); }); }, @@ -140,33 +142,28 @@ export default { watch: { selectedYear(value) { this.mainStore.updateVehicleYear(value); + this.$refs["vehicleMakeQuestion"].clearValues(); if(value) - { + { this.$refs["vehicleMakeQuestion"].getNewValues(); } - else{ - this.$refs["vehicleMakeQuestion"].clearValues(); - } }, selectedMake(value) { this.mainStore.updateVehicleMake(value); + this.$refs["vehicleModelQuestion"].clearValues(); if(value) - { + { this.$refs["vehicleModelQuestion"].getNewValues(); } - else{ - this.$refs["vehicleModelQuestion"].clearValues(); - } }, selectedModel(value) { this.mainStore.updateVehicleModel(value); + this.$refs["vehicleStyleQuestion"].clearValues(); if(value) - { + { this.$refs["vehicleStyleQuestion"].getNewValues(); } - else{ - this.$refs["vehicleStyleQuestion"].clearValues(); - } + }, selectedStyle(value) { this.mainStore.updateVehicleStyle(value); @@ -191,7 +188,7 @@ export default { this.$route ); }); - }, + }, async updateYearValues() { return await useMainStore().getVehicleYears(); }, @@ -207,7 +204,7 @@ export default { }, computed: { displayGeneric() { - return !useMainStore().order.vehicle.imageUrl || !this.selectedStyle; + return !this.selectedStyle; } }, components: { @@ -232,6 +229,6 @@ export default { .subheader-secondary { margin-top: .5rem; - padding: 0px; + padding: 0px; } diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js index 35ae1377..8c276eb7 100644 --- a/src/layouts/vin-lookup/vin-lookup.spec.js +++ b/src/layouts/vin-lookup/vin-lookup.spec.js @@ -119,6 +119,11 @@ const vehicleWithNoAdditionalPartsOrQuestionsMockResponse = { }, }; +jest.mock("bootstrap", () => ({ + getInstance: jest.fn(), + getOrCreateInstance: jest.fn(), +})); + const mockRoute = { query: { // Needed inside vehicle-questions-mixin diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 72c16127..9342d2b8 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -13,7 +13,7 @@ - +
@@ -152,7 +152,7 @@ export default { this.bailout=true } - if(this.bailout){ + if(this.bailout){ return this.$router.navigate( this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT, this.$route); @@ -188,6 +188,7 @@ export default { // navigate back to vehicle-damage if (this.isCarIdDifferentFromTheStore && !isSelectedGlassAvailableForVehicle) { this.mainStore.updateVehicle(this.vehicleFromLookup); + this.mainStore.resetDamageState(); this.$router.navigate( this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS, this.$route, diff --git a/src/layouts/welcome-page/welcome-page.vue b/src/layouts/welcome-page/welcome-page.vue index 553f6429..4be1f187 100644 --- a/src/layouts/welcome-page/welcome-page.vue +++ b/src/layouts/welcome-page/welcome-page.vue @@ -140,7 +140,8 @@
- { }); describe("navigateBack", () => { + test("current page is coverage-statement and damage is repair => go to vehicle-damage", () => { + // Arrange + const { wrapper } = setupMocks({ issPage: issPageValues.COVERAGE_STATEMENT }); + useMainStore().order.damage.isRepair = true; + + // Act + wrapper.vm.navigateBack(); + + // Assert + expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith( + navigationScenarios.CLICKED_BACK_WITH_REPAIR, + { query: { issPage: issPageValues.COVERAGE_STATEMENT } } + ); + }); + test("current page is molding questions and there are part questions, multiple parts to choose, and capability questions => go to vehicle-parts", () => { // Arrange const { wrapper } = setupMocks({ issPage: issPageValues.MOLDING_QUESTIONS }); 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/navigation-scenarios.js b/src/router/router-constants/navigation-scenarios.js index 7c9e90da..5331ac76 100644 --- a/src/router/router-constants/navigation-scenarios.js +++ b/src/router/router-constants/navigation-scenarios.js @@ -52,6 +52,9 @@ const navigationScenarios = { CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS: "CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS", CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS: "CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS", + // Coverage Statement + CLICKED_BACK_WITH_REPAIR: "CLICKED_BACK_WITH_REPAIR", + //Provider Preference CLICKED_FORWARD_WITH_SAFELITE: "CLICKED_FORWARD_WITH_SAFELITE", CLICKED_FORWARD_WITH_TPA_ENABLED: "CLICKED_FORWARD_WITH_TPA_ENABLED", diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index b2aba7a7..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: [ @@ -474,10 +422,14 @@ const routingTable = function(store) { scenario: navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS, destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS }, + { + scenario: navigationScenarios.CLICKED_BACK_WITH_REPAIR, + destinationIssPageValue: issPageValues.VEHICLE_DAMAGE + }, { scenario: navigationScenarios.CLICKED_FORWARD, destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE - } + }, ] }, { diff --git a/src/store/index.js b/src/store/index.js index 7b7d4dd0..7a58d4f3 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, + noCompensation: null, + 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, + } }, customer: { address: { @@ -79,7 +85,8 @@ const getDefaultState = () => { payment: { isInsurance: true, insuranceCoverage: { - isVerified: false + isVerified: false, + coverageStatus: coverageStatuses.PENDING } }, referralNumber: null, @@ -125,7 +132,10 @@ export const useMainStore = defineStore({ vehicle: (state) => state.order.vehicle, 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) => { const matchedEvent = state.applicationUser.eventBus.find( @@ -327,6 +337,8 @@ export const useMainStore = defineStore({ } }, getCoveragePolicyInfo({accountNumber, policyNumber, dateOfLoss, zipCode}){ + //TODO: replace place holder correlationId with the real thing + const placeHolderCorrelationId = "00000000-0000-0000-0000-000000000000"; try{ const response = globalMethods.callHttpClient({ method:endpoints.CoveragePolicyInfo.method, @@ -335,7 +347,8 @@ export const useMainStore = defineStore({ accountNumber: accountNumber, policyNumber: policyNumber, dateOfLoss: dateOfLoss, - zipCode: zipCode + zipCode: zipCode, + correlationId: placeHolderCorrelationId } }); return response; @@ -347,6 +360,69 @@ export const useMainStore = defineStore({ }; } }, + registerClaim() { + // TODO: replace place holder correlationId with the real thing + const placeHolderCorrelationId = "00000000-0000-0000-0000-000000000000"; + globalMethods.callHttpClient({ + method: endpoints.RegisterClaim.method, + endpoint: endpoints.RegisterClaim.url, + 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, + location: { + city: this.order.policy.damageCity, + state: this.order.policy.damageState, + country: "US" // TODO set from store + }, + vehicle: { + year: this.order.vehicle.year?.toString() ?? "", + make: this.order.vehicle.make, + model: this.order.vehicle.model, + vin: this.order.vehicle.vin + }, + }, + damageDescription: this.order.policy.damageCause + } + }).then((response) => { + const registerClaimFailed = response.data.isError; + this.order.payment.insuranceCoverage.isVerified = !registerClaimFailed; + this.order.payment.insuranceCoverage.coverageStatus = registerClaimFailed + ? coverageStatuses.PENDING + : this.policy.noCompensation + ? coverageStatuses.NO_COMP + : coverageStatuses.VERIFIED; + },(error) => { + this.order.payment.insuranceCoverage.isVerified = false; + this.order.payment.insuranceCoverage.coverageStatus = coverageStatuses.PENDING; + }); + }, async lookupVinByPlate(licensePlate, licenseState) { try { const response = await globalMethods.callHttpClient({ @@ -480,7 +556,7 @@ export const useMainStore = defineStore({ console.error(error); return []; }); - }, + }, async getRainDefense() { return globalMethods @@ -590,18 +666,18 @@ export const useMainStore = defineStore({ } }); }, - + 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) { @@ -678,8 +754,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; @@ -690,6 +765,11 @@ export const useMainStore = defineStore({ this.order.vehicle.imageVifNumber = vehicle.imageVifNumber; this.order.vehicle.imageColor = vehicle.imageVifColor; + // These could be undefined + this.order.policy.noCompensation = vehicle.noCoverage; + this.order.policy.deductible.replace = vehicle.deductible; + this.order.policy.deductible.repair = vehicle?.repairWaived ?? false ? 0 : vehicle.deductible; + this.resetSupportingItemsState(); this.resetVapsState(); }, @@ -907,7 +987,8 @@ export const useMainStore = defineStore({ ); if (haveMoldingQuestionAnswersChanged) { - this.resetPartsAndDependencies(); + this.updateGlassParts(null); + this.updateSupportingItems(null); this.updateCapabilityQuestionAnswers(null); this.updatePageData({ page: issPageValues.CAPABILITY_QUESTIONS, data: null }); } @@ -932,7 +1013,8 @@ export const useMainStore = defineStore({ ); if (haveCapabilityQuestionAnswersChanged) { - this.resetPartsAndDependencies(); + this.updateGlassParts(null); + this.updateSupportingItems(null); } // Save new values @@ -1155,9 +1237,7 @@ export const useMainStore = defineStore({ registrationInfo?.firstName !== this.order.vehicle.registration?.firstName || registrationInfo?.lastName !== this.order.vehicle.registration?.lastName ) - { - this.resetRegistrationAndDependencies(); - + { if (!isSelectedGlassAvailableForVehicle) { this.resetDamageState(); this.resetGlassPartsState(); @@ -1167,7 +1247,11 @@ export const useMainStore = defineStore({ this.updateRegistration(registrationInfo); }; - this.updateVehicle(vehicleInfo); + if(vehicleInfo) + { + this.updateVehicle(vehicleInfo); + } + }, saveVin({ isSelectedGlassAvailableForVehicle, vehicleInfo }) { //Reset dependent state when changing diff --git a/src/store/store.spec.js b/src/store/store.spec.js index e282f849..03b06257 100644 --- a/src/store/store.spec.js +++ b/src/store/store.spec.js @@ -1,19 +1,21 @@ 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'; +import { coverageStatuses } from "@/constants/coverage-statuses.js"; describe("Store", () => { let store; const vueApp = createApp(App); - const pinia = createPinia(); - vueApp.use(pinia); beforeEach(() => { + const pinia = createPinia(); + setActivePinia(pinia); + vueApp.use(pinia); 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,350 @@ 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 noCompensation = getRandomBoolean(); + const deductible = getRandomInt(1,500); + const vehicle = { + noCoverage: noCompensation, + deductible: deductible, + repairWaived: true + }; + + const expectedPolicy = { + noCompensation: noCompensation, + 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 noCompensation = getRandomBoolean(); + const deductible = getRandomInt(1,500); + const vehicle = { + noCoverage: noCompensation, + 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 = { + noCompensation: noCompensation, + 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); + + // 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 with no coverage => isVerified true and coverage status no comp", async () => { + // Arrange + const response = { + data: { + claimantId: null, + claimNumber: getRandomString(9, 9), + correlationId: getRandomGuid(), + isSuccess: true, + isError: false, + successMessage: getRandomString(9, 9), + deductible: 0 + } + }; + store.policy.noCompensation = true; + + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response)); + + // Act + await store.registerClaim(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(store.payment.insuranceCoverage.isVerified).toBe(true); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.NO_COMP); + }); + + it("successful response with coverage => isVerified true and coverage status verified", async () => { + // Arrange + const response = { + data: { + claimantId: null, + claimNumber: getRandomString(9, 9), + correlationId: getRandomGuid(), + isSuccess: true, + isError: false, + successMessage: getRandomString(9, 9), + deductible: 0 + } + }; + store.policy.noCompensation = false; + + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.resolve(response)); + + // Act + await store.registerClaim(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(store.payment.insuranceCoverage.isVerified).toBe(true); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.VERIFIED); + }) + + it("Call to client returns exception, resulting in object with error property being returned", async () => { + // Arrange + globalMethods.callHttpClient = jest.fn().mockReturnValue(Promise.reject()); + + // Act + await store.registerClaim(); + + // Asserts + expect(globalMethods.callHttpClient).toHaveBeenCalled(); + expect(store.payment.insuranceCoverage.isVerified).toBe(false); + expect(store.payment.insuranceCoverage.coverageStatus).toBe(coverageStatuses.PENDING); + }); + }) }); \ No newline at end of file diff --git a/src/ux-components/radio/radio.vue b/src/ux-components/radio/radio.vue index 1a0d52d7..5be0c629 100644 --- a/src/ux-components/radio/radio.vue +++ b/src/ux-components/radio/radio.vue @@ -1,139 +1,150 @@ - - - - - \ No newline at end of file +} +