From 4bff7b779261dc7d0d7b126cb7e9aa5215159216 Mon Sep 17 00:00:00 2001 From: bmauger Date: Tue, 8 Mar 2022 10:46:47 -0500 Subject: [PATCH 01/30] CSR-269 style updates. --- src/layouts/vehicle-damage/vehicle-damage.vue | 49 +++++++++++-------- .../list-button-horizontal.vue | 7 +-- src/ux-components/list-card/list-card.vue | 2 + 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 643aa0f5b..0eb11fbf0 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -8,6 +8,7 @@ @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" + class="vehicle-damage-form" > - { return glass.location === damageLocationsSelected.WINDSHIELD }) || store.getters.damage.isRepair) { glassSelections.push(damageLocationsSelected.WINDSHIELD); @@ -193,7 +194,7 @@ export default { getWindshieldOptionsFromStore() { var windShieldOptions = { selectedWindshieldDamageType: [], selectedWindshieldChipCount: [], selectedWindshieldReplaceOptions: []}; - + if (store.getters.damage.isRepair === undefined) return windshieldOptions; if (!store.getters.damage.isRepair) { @@ -222,7 +223,7 @@ export default { } return windShieldOptions; - + }, getDoorSidesFromStore() { @@ -249,7 +250,7 @@ export default { return driverSideReplaceOptions; }, - + getPassengerSideReplaceOptionsFromStore() { var passengerSideReplaceOptions = []; @@ -264,7 +265,7 @@ export default { getRearReplaceOptionsFromStore(){ var rearReplaceOptions = []; - + store.getters.damage.glassToReplace.forEach(glass => { if (glass.location === damageLocationsSelected.REAR){ rearReplaceOptions.push(glass.name); @@ -284,10 +285,10 @@ export default { } store.commit(this.storeMutations.UPDATE_GLASS_TO_REPLACE, this.selectedGlassToReplace()); - + const partsData = await baseMixin.methods.dispatchNonBlockingStoreAction(this.storeActions.GET_PARTS_OR_QUESTIONS, { carId: store.getters.vehicle.carId, glassArray: this.selectedGlassToReplace()}, false); - + this.navigateForward(partsData); }, @@ -297,7 +298,7 @@ export default { this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS, this.$route, {}, {}, partsData.data); return; } - + //found multiple parts for a single glass location (Windshield, Driver, Passenger, Rear) if (partsData.data.partsOrQuestions){ for (var i = 0; i < partsData.data.partsOrQuestions.length; i++){ @@ -312,7 +313,7 @@ export default { if (!this.isWindshieldRepair){ store.commit(this.storeMutations.UPDATE_PARTS, partsData.data.partsOrQuestions[0].parts); } - + this.$router.navigate(this.navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART, this.$route); }, @@ -341,33 +342,33 @@ export default { selectedGlassToReplace.push({ location: damageLocationsSelected.REAR, name: rearItem}); }) } - + return selectedGlassToReplace; }, }, computed: { isWindshieldDamageLocation() { - return this.selectedDamageLocations.some(selectedDamages => + return this.selectedDamageLocations.some(selectedDamages => { return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD; }); }, isSideDoorDamageLocation() { - return this.selectedDamageLocations.some(selectedDamages => + return this.selectedDamageLocations.some(selectedDamages => { return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR; }); }, isRearWindowDamageLocation() { - return this.selectedDamageLocations.some(selectedDamages => + return this.selectedDamageLocations.some(selectedDamages => { return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW; }); }, isWindshieldRepair() { if (!this.isWindshieldDamageLocation) return false; - - return this.selectedWindshieldOptions.selectedWindshieldDamageType && this.selectedWindshieldOptions.selectedWindshieldDamageType.some(selectedDamageType => + + return this.selectedWindshieldOptions.selectedWindshieldDamageType && this.selectedWindshieldOptions.selectedWindshieldDamageType.some(selectedDamageType => { return selectedDamageType.toUpperCase() === "REPAIR"; }); @@ -375,7 +376,7 @@ export default { isDriverSideReplace() { if (!this.isSideDoorDamageLocation) return false; - return this.sideDoorOptionsData.selectedDoorSides.some(selectedDriverSide => + return this.sideDoorOptionsData.selectedDoorSides.some(selectedDriverSide => { return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE; }); @@ -383,7 +384,7 @@ export default { isPassengerSideReplace() { if (!this.isSideDoorDamageLocation) return false; - return this.sideDoorOptionsData.selectedDoorSides.some(selectedPassengerSide => + return this.sideDoorOptionsData.selectedDoorSides.some(selectedPassengerSide => { return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE; }); @@ -407,3 +408,11 @@ export default { }, }; + + diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index c9f0f287c..910413ae9 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -113,9 +113,9 @@ export default { if (Array.isArray(props.selectedValues) && props.selectedValues.length == 1) { fieldOptions['initialValue'] = fieldOptions.checkedValue; } - const { - checked, - handleChange, + const { + checked, + handleChange, errors, } = useField(props.groupName, props.validationRules, fieldOptions); @@ -135,6 +135,7 @@ export default { opacity: 0; width: 0; height: 0; + position: absolute; &:focus-visible + label { box-shadow: 0 0 0 2px $blue; z-index: 2; diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue index e57fb861f..b2f12b4a5 100644 --- a/src/ux-components/list-card/list-card.vue +++ b/src/ux-components/list-card/list-card.vue @@ -183,6 +183,7 @@ export default { opacity: 0; width: 0; height: 0; + position: absolute; + label { display: block; @@ -262,6 +263,7 @@ export default { height: 6px; width: 11px; transform: rotate(-45deg); + z-index: 1; } } From d95e6c10dd07f5d6d2e8cb908d13a629dba1f47f Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Tue, 8 Mar 2022 12:26:35 -0500 Subject: [PATCH 02/30] CSR-319: fix event triggers for radio buttons --- .../list-button-horizontal/list-button-horizontal.vue | 3 ++- src/ux-components/list-button/list-button.vue | 3 ++- src/ux-components/list-card/list-card.vue | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index c9f0f287c..0475a0e35 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -2,6 +2,8 @@
diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 0115564ef..3a8e65fc0 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -2,6 +2,8 @@
diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue index e57fb861f..0a143aa05 100644 --- a/src/ux-components/list-card/list-card.vue +++ b/src/ux-components/list-card/list-card.vue @@ -7,6 +7,8 @@ errors.length > 0 ? 'has-error' : '', hasError ? 'has-error' : '', ]" + @mouseup="handleChange(value)" + @keyup.space="handleChange(value)" > From 7ae4baaa4d713e91a255a08d85554700befb4016 Mon Sep 17 00:00:00 2001 From: bmauger Date: Tue, 8 Mar 2022 14:43:01 -0500 Subject: [PATCH 03/30] Footer adjustments to better accommodate variable width button and link.. --- .../funnel-footer/funnel-footer.vue | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/common-components/funnel-footer/funnel-footer.vue b/src/common-components/funnel-footer/funnel-footer.vue index 062a3574a..44afa5364 100644 --- a/src/common-components/funnel-footer/funnel-footer.vue +++ b/src/common-components/funnel-footer/funnel-footer.vue @@ -16,7 +16,7 @@
-
+
- -
- +
+
@@ -133,6 +133,7 @@ export default { if(this.isMultiSelect && this.selectedValues) { // Add or remove item to array of data to emit const newSelectedValues = this.selectedValues; + if(Array.isArray(this.selectedValues)) { val.checkValue ? newSelectedValues.push(val.value) : newSelectedValues.splice(newSelectedValues.indexOf(val.value), 1); this.selectedValues = newSelectedValues; diff --git a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue index cdbb0c48d..fe43419e8 100644 --- a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue +++ b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue @@ -10,6 +10,7 @@ buttonType="listCard" v-model="selectedValues" :validationRules="validationRules" + :suppressError="suppressError" />
@@ -35,6 +36,7 @@ export default ({ modelValue: Array, isMultiSelect: Boolean, validationRules: String, + suppressError: Boolean, }, methods: { initializeComponent(cmsContent, replaceOptions){ diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 0eb11fbf0..20c498198 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -19,6 +19,7 @@ ref="windshieldOptions" v-model="selectedWindshieldOptions" :hasRepairReplaceConflict="hasRepairReplaceConflict" + :hasSplitSingleConflict="hasSplitSingleConflict" :selectedDamageLocations="selectedDamageLocations" /> 1 && this.isWindshieldRepair; }, + hasSplitSingleConflict() { + if (!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(); + }) + ); + }, }, components: { diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue index c1539e91a..21f4e6f33 100644 --- a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue +++ b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue @@ -2,14 +2,17 @@
+ isSplitWindshieldOption: {{isSplitWindshieldOption}} +
+ isWindshieldReplaceAvailable: {{isWindshieldReplaceAvailable}} +
@@ -53,17 +65,25 @@ defineRule("checkForRepairAndReplace", (value, [otherFieldValue]) => { Array.isArray(otherFieldValue) && otherFieldValue.length > 1) { - return "checkForRepairAndReplace error" + return false; } return true; }); - defineRule("repairOnly", (value) => { if (value.toString().toUpperCase() === damageLocationsSelected.REPAIR.toUpperCase()) { return true; } return false; }); +defineRule("preventSplitAndSingleTogether", (value) => { + if (value.toString().toUpperCase().includes(damageLocationsSelected.SINGLE.toUpperCase()) && + (value.toString().toUpperCase().includes(damageLocationsSelected.DRIVER.toUpperCase()) || + value.toString().toUpperCase().includes(damageLocationsSelected.PASSENGER.toUpperCase()))) + { + return false; + } + return true; +}); export default ({ name: "windshieldOptions", @@ -77,7 +97,8 @@ export default ({ props: { modelValue: Array, selectedDamageLocations: Array, - hasRepairReplaceConflict: Boolean + hasRepairReplaceConflict: Boolean, + hasSplitSingleConflict: Boolean, }, methods: { @@ -151,12 +172,28 @@ export default ({ isWindshieldReplaceAvailable() { return !(Array.isArray(this.windshieldAvailableReplacementOptions) && this.windshieldAvailableReplacementOptions.length < 1); }, - showNoReplaceAvailableError() { + isSplitWindshieldOption() { + const options = this.windshieldAvailableReplacementOptions.toString().toUpperCase(); + if (options.includes('DRIVER') && options.includes('PASSENGER')) { + return true; + } + return false; + }, + showNoReplacementAvailableError() { if (this.isReplaceOptionSelected && !this.isWindshieldReplaceAvailable) { return true; } return false; }, + windshieldDamageTypeQuestionValidationRules() { + // Note: the validation rules string is not dynamic (it cannot be changed once component has been created) + let validationRules = "windshield-damage-type-required|checkForRepairAndReplace:@DamageLocationQuestion"; + // if vehicle has no windshield replacement option + if (!this.isWindshieldReplaceAvailable) { + validationRules = validationRules.concat('|repairOnly'); + } + return validationRules; + } }, components: { windshieldDamageTypeQuestion, From c4707fd6af9f2a0e8b90d31abe51425e5bd25f2d Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Thu, 10 Mar 2022 16:42:24 -0500 Subject: [PATCH 21/30] CSR-319: clean up output on page --- .../vehicle-damage/windshield-options/windshield-options.vue | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue index 21f4e6f33..30f8c15d7 100644 --- a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue +++ b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue @@ -7,9 +7,6 @@ v-model="selectedWindshieldDamageTypeValues" :validationRules="windshieldDamageTypeQuestionValidationRules" /> - isSplitWindshieldOption: {{isSplitWindshieldOption}} -
- isWindshieldReplaceAvailable: {{isWindshieldReplaceAvailable}} Date: Fri, 11 Mar 2022 10:10:46 -0500 Subject: [PATCH 22/30] CSR-319: rearrange form markup location / move submit fns into mixin --- .../vehicle-damage/vehicle-damage.spec.js | 35 ------------------- src/layouts/vehicle-damage/vehicle-damage.vue | 33 ++++++----------- src/mixins/base-mixin.js | 21 ++++++++++- src/mixins/base-mixin.spec.js | 32 +++++++++++++++++ 4 files changed, 62 insertions(+), 59 deletions(-) diff --git a/src/layouts/vehicle-damage/vehicle-damage.spec.js b/src/layouts/vehicle-damage/vehicle-damage.spec.js index 348da20ad..e6ce4e85d 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.spec.js +++ b/src/layouts/vehicle-damage/vehicle-damage.spec.js @@ -782,41 +782,6 @@ describe("vehicle-damage.vue", () => { }); }); -describe("vehicle-damage.vue", () => { - test("when onInvalidSubmit is triggered with errors focus will be put on the first element with an error", async () => { - - //Arrange - const { wrapper } = setupMocks({}); - const mockedValidationPayload = { - values: {}, - errors: { - driverSideOptions: 'Please select window', - passengerSideOptions: 'Please select window' - }, - results: {}, - } - const newObj = document.createElement('input'); - newObj.setAttribute("id", "testInput"); - newObj.setAttribute("data-focus-target", "driverSideOptions"); - document.body.appendChild(newObj); - const testInputElement = document.getElementById("testInput"); - - //Act - vehicleDamage.beforeRouteEnter.call( - wrapper.vm, - { query: { fmgPage: "vehicle-damage" } }, - undefined, - (c) => c(wrapper.vm) - ); - wrapper.vm.onInvalidSubmit(mockedValidationPayload); - await nextTick(); - const focusedEl = document.activeElement; - - //Assert - expect(testInputElement).toBe(focusedEl); - }); -}); - // THE FOLLOWING TEST IS NOT NECESSARILY REQUIRED FOR COVERAGE // BUT KEEP FOR AN EXAMPLE OF A VALIDATION TEST // diff --git a/src/layouts/vehicle-damage/vehicle-damage.vue b/src/layouts/vehicle-damage/vehicle-damage.vue index 20c498198..3c02b44bf 100644 --- a/src/layouts/vehicle-damage/vehicle-damage.vue +++ b/src/layouts/vehicle-damage/vehicle-damage.vue @@ -1,15 +1,15 @@ - - From 0bcd842affb608284c3151e15ed868ec12459b71 Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Fri, 11 Mar 2022 10:40:50 -0500 Subject: [PATCH 24/30] CSR-319: remove console logs / comments --- src/mixins/base-mixin.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js index 451738c37..f54909d06 100644 --- a/src/mixins/base-mixin.js +++ b/src/mixins/base-mixin.js @@ -23,20 +23,13 @@ export default { }, onSubmit() {}, // DO NOT REMOVE; needed to prevent default form submit behavior onInvalidSubmit({ values, errors, results }) { - console.log('errors: ', errors) - // {DamageLocationQuestion: 'Please select damage location'} - // {driverSideOptions: 'Please select window', passengerSideOptions: 'Please select window'} - - // identify the first error field and put focus on it // get error names array const errorNames = errors ? Object.keys(errors) : []; const firstErrorEl = errorNames[0]; if (firstErrorEl) { - console.log('firstErrorEl: ', firstErrorEl) const qsString = "[data-focus-target='" + firstErrorEl + "']"; const el = document.querySelector(qsString); - console.log('el is: ', el) el && el.focus(); } }, From 2ffc311f22d01bf3b1cb3b36aa041d1b402901c3 Mon Sep 17 00:00:00 2001 From: bmauger Date: Fri, 11 Mar 2022 16:03:38 -0500 Subject: [PATCH 25/30] Update vin-lookup page. --- src/layouts/vin-lookup/vin-lookup.vue | 17 +++++++++ src/router/router-constants/routing-table.js | 13 +++++++ src/store/index.js | 38 +++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index aa179439a..635f0aef5 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -33,6 +33,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; import { storeActions } from "@/constants/store-actions"; import store from "@/store"; +import { storeMutations } from "@/constants/store-mutations"; import baseMixin from "@/mixins/base-mixin"; import { Form, defineRule } from "vee-validate"; import { required } from "@/helpers/validation-rules"; @@ -86,6 +87,22 @@ export default { arePagePrerequisitesValid() { return true; }, + resetDependentState() { + store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null); + store.commit(storeMutations.UPDATE_REGISTRATION_CITY, null); + store.commit(storeMutations.UPDATE_REGISTRATION_STATE, null); + store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, null); + store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, null); + store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null); + store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, null); + }, + backButtonAction() { + // route to move backwards + this.$router.navigate( + this.navigationScenarios.CLICKED_BACK, + this.$route + ); + }, }, components: { funnelHeader, diff --git a/src/router/router-constants/routing-table.js b/src/router/router-constants/routing-table.js index 3bd937c41..584796a61 100644 --- a/src/router/router-constants/routing-table.js +++ b/src/router/router-constants/routing-table.js @@ -97,6 +97,19 @@ const routingTable = [ }, ], }, + { + fmgPageValue: fmgPageValues.VIN_LOOKUP, + maps: [ + { + scenario: navigationScenarios.CLICKED_BACK, + destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE, + }, + { + scenario: navigationScenarios.VIN_LOOKUP, + destinationFmgPageValue: fmgPageValues.PART_QUESTIONS, + }, + ], + }, ]; export { routingTable }; diff --git a/src/store/index.js b/src/store/index.js index a00f550be..5ffdc168a 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -19,6 +19,15 @@ export const state = { imageUrl: null, imageVifNumber: null, imageColor: null, + registration: { + licensePlate: null, + address: null, + city: null, + state: null, + zipCode: null, + firstName: null, + lastName: null, + }, }, damage: { isRepair: null, @@ -81,6 +90,33 @@ export const mutations = { updatePageData(state, pageData){ state.applicationUser.pageData[pageData.page] = pageData.data; }, + updateRegistrationAddress(state, registrationAddress){ + state.order.vehicle.registration.address = registrationAddress; + }, + updateRegistrationCity(state, registrationCity){ + state.order.vehicle.registration.city = registrationCity; + }, + updateRegistrationState(state, registrationState){ + state.order.vehicle.registration.state = registrationState; + }, + updateRegistrationZipCode(state, registrationZipCode){ + state.order.vehicle.registration.zipCode = registrationZipCode; + }, + updateRegistrationFirstName(state, registrationFirstName){ + state.order.vehicle.registration.firstName = registrationFirstName; + }, + updateRegistrationLastName(state, registrationLastName){ + state.order.vehicle.registration.lastName = registrationLastName; + }, + updateRegistrationLicensePlate(state, registrationLicensePlate){ + state.order.vehicle.registration.licensePlate = registrationLicensePlate; + }, + updateServiceLocationZip(state, ServiceLocationZip){ + state.order.vehicle.serviceLocation.zip = ServiceLocationZip; + }, + updateCustomerEmailAddress(state, CustomerEmailAddress){ + state.order.vehicle.customer.emailAddress = CustomerEmailAddress; + }, // EVENT BUS MUTATIONS addEventToBus(state, event) { @@ -288,4 +324,4 @@ export default createStore({ mutations, getters, actions, -}); \ No newline at end of file +}); From 21597f3f750114806856fe23afa32fffa34cb4e7 Mon Sep 17 00:00:00 2001 From: bmauger Date: Fri, 11 Mar 2022 16:12:21 -0500 Subject: [PATCH 26/30] Change to camelCase. --- src/store/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 5ffdc168a..2eead09e1 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -112,10 +112,10 @@ export const mutations = { state.order.vehicle.registration.licensePlate = registrationLicensePlate; }, updateServiceLocationZip(state, ServiceLocationZip){ - state.order.vehicle.serviceLocation.zip = ServiceLocationZip; + state.order.vehicle.serviceLocation.zip = serviceLocationZip; }, updateCustomerEmailAddress(state, CustomerEmailAddress){ - state.order.vehicle.customer.emailAddress = CustomerEmailAddress; + state.order.vehicle.customer.emailAddress = customerEmailAddress; }, // EVENT BUS MUTATIONS From 4a32ca1f981ffb14af7f4cf128348cc51e0ff5d8 Mon Sep 17 00:00:00 2001 From: bmauger Date: Mon, 14 Mar 2022 13:55:46 -0400 Subject: [PATCH 27/30] Update unit test. --- src/layouts/vin-lookup/vin-lookup.spec.js | 168 +++++++++++++++++++++- src/layouts/vin-lookup/vin-lookup.vue | 26 ++-- src/store/index.js | 8 +- 3 files changed, 184 insertions(+), 18 deletions(-) diff --git a/src/layouts/vin-lookup/vin-lookup.spec.js b/src/layouts/vin-lookup/vin-lookup.spec.js index 3d0843e10..1db5c18a6 100644 --- a/src/layouts/vin-lookup/vin-lookup.spec.js +++ b/src/layouts/vin-lookup/vin-lookup.spec.js @@ -1 +1,167 @@ -test.todo("some test to be written in the future"); +// Components +import vinLookup from "@/layouts/vin-lookup/vin-lookup.vue"; +import vehicleDamage from "@/layouts/vehicle-damage/vehicle-damage.vue"; +import funnelHeader from "@/common-components/funnel-header/funnel-header"; +import funnelFooter from "@/common-components/funnel-footer/funnel-footer"; +import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; +import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; +import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options"; +import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question"; +import windshieldOptions from "@/layouts/vehicle-damage/windshield-options/windshield-options"; +import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question"; + +// Supporting Files +import { settleAllPromises } from "@/helpers/layout-helper.js"; +import baseMixin from "@/mixins/base-mixin"; +import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; +import { mount, flushPromises } from "@vue/test-utils"; +import { getMountOptions } from "@/helpers/unit-test-helper.js"; +import { nextTick } from "vue"; +import { storeActions } from "@/constants/store-actions"; +import { storeMutations } from "@/constants/store-mutations"; +import store from "@/store"; +import { validate } from "vee-validate"; +import { damageLocationsSelected } from "@/constants/damage-locations-selected.js"; + +// Mock our module for promises. +jest.mock("@/helpers/layout-helper.js", () => ({ + settleAllPromises: jest.fn(), +})); + +// Mock fetchCmsContentForPage +jest.mock("@/helpers/cms-content-helper", () => ({ + fetchCmsContentForPage: jest.fn(), +})); + +// Mock Store +jest.mock("@/store", () => ({ + commit: jest.fn(), + dispatch: jest.fn(), + getters: { + vehicle: { + carId: "C00000000", + image: "test.jpg", + }, + eventBusItem: jest.fn(), + damage: { + glassToReplace: [] + }, + }, +})); + +describe("vin-lookup.vue", () => { + + test("Call resetDependentState", async() => { + const {wrapper} = setupMocks({}); + wrapper.vm.resetDependentState(); + expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); + }); + +}); + +// TEMP +function setupMocks({ + pageHeaderWidgetHeaderText = {}, + mountOptionsMockData = { + router: { + navigate: jest.fn(), + }, + store: { + getters: { + vehicle: {}, + }, + }, + }, +}) { + //Mock api responses + baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn(); + const apiResponses = { + cmsContent: { + FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, + VehicleBannerWidget: { + GenericVehicleImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3", + }, + FunnelHeaderWidget: { + LogoImage: + "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3", + }, + }, + damageOptions: { + driverSideOptions: { + availableReplacementOptions: ["Front", "Back", "Side"], + }, + passengerSideOptions: { + availableReplacementOptions: ["Front", "Back", "Side"], + }, + windshieldOptions: { + availableReplacementOptions: ["Single", "Driver", "Passenger"], + }, + backGlassOptions: { + availableReplacementOptions: ["Front", "Back", "Side"], + }, + }, + }; + + const apiPromise = Promise.resolve(apiResponses); + + settleAllPromises.mockImplementation(() => apiPromise); + fetchCmsContentForPage.mockImplementation(() => Promise.resolve()); + + //Mock damage initialize methods + funnelHeader.methods = { + initializeComponent: jest.fn(), + }; + + vehicleBanner.methods = { + initializeComponent: jest.fn(), + }; + + funnelSubHeader.methods = { + initializeComponent: jest.fn(), + }; + + damageLocationQuestion.methods = { + initializeComponent: jest.fn(), + }; + + sideDoorOptions.methods = { + initializeComponent: jest.fn(), + }; + + windshieldOptions.methods = { + initializeComponent: jest.fn(), + }; + + replaceOptionsQuestion.methods = { + initializeComponent: jest.fn(), + updateSelectedValues: jest.fn(), + }; + + funnelFooter.methods = { + initializeComponent: jest.fn(), + } + + const mountOptions = getMountOptions(mountOptionsMockData); + mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods + + const wrapper = mount(vinLookup, mountOptions); + + const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" }); + funnelHeaderWrapper.vm.initializeComponent = + funnelHeader.methods.initializeComponent; + + const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" }); + vehicleBannerWrapper.vm.initializeComponent = + vehicleBanner.methods.initializeComponent; + + const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader" }); + funnelSubHeaderWrapper.vm.initializeComponent = + funnelSubHeader.methods.initializeComponent; + + const funnelFooterWrapper = wrapper.findComponent({ name: "funnelFooter" }); + funnelFooterWrapper.vm.initializeComponent = + funnelFooter.methods.initializeComponent; + + return { wrapper, apiPromise }; +} diff --git a/src/layouts/vin-lookup/vin-lookup.vue b/src/layouts/vin-lookup/vin-lookup.vue index 635f0aef5..8dbb6cdc9 100644 --- a/src/layouts/vin-lookup/vin-lookup.vue +++ b/src/layouts/vin-lookup/vin-lookup.vue @@ -5,17 +5,17 @@

VIN Lookup Placeholder Page

@@ -88,13 +88,7 @@ export default { return true; }, resetDependentState() { - store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null); - store.commit(storeMutations.UPDATE_REGISTRATION_CITY, null); - store.commit(storeMutations.UPDATE_REGISTRATION_STATE, null); - store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, null); - store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, null); - store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null); - store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, null); + store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES); }, backButtonAction() { // route to move backwards diff --git a/src/store/index.js b/src/store/index.js index 2eead09e1..65e5a06c7 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -151,7 +151,13 @@ export const mutations = { state.order.damage.glassToReplace = null; }, resetRegistrationState(state) { - + state.order.vehicle.registration.licensePlate = null; + state.order.vehicle.registration.address = null; + state.order.vehicle.registration.city = null; + state.order.vehicle.registration.state = null; + state.order.vehicle.registration.zipCode = null; + state.order.vehicle.registration.firstName = null; + state.order.vehicle.registration.lastName = null; }, resetPartsState(state) { state.order.lineItems.glassParts = null; From 735902c4fa9b07013a8459d5937eaaa29bc76796 Mon Sep 17 00:00:00 2001 From: bmauger Date: Mon, 14 Mar 2022 15:33:40 -0400 Subject: [PATCH 28/30] Fix error. --- src/store/index.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/store/index.js b/src/store/index.js index 65e5a06c7..53e977114 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -29,6 +29,12 @@ export const state = { lastName: null, }, }, + serviceLocation: { + zip: null, + }, + customer: { + emailAddress: null, + }, damage: { isRepair: null, numberOfChips: null, @@ -111,10 +117,10 @@ export const mutations = { updateRegistrationLicensePlate(state, registrationLicensePlate){ state.order.vehicle.registration.licensePlate = registrationLicensePlate; }, - updateServiceLocationZip(state, ServiceLocationZip){ + updateServiceLocationZip(state, serviceLocationZip){ state.order.vehicle.serviceLocation.zip = serviceLocationZip; }, - updateCustomerEmailAddress(state, CustomerEmailAddress){ + updateCustomerEmailAddress(state, customerEmailAddress){ state.order.vehicle.customer.emailAddress = customerEmailAddress; }, From acc9518675b0e50e4c23ce60a6cb48ff8421112c Mon Sep 17 00:00:00 2001 From: Adam Caouette Date: Tue, 15 Mar 2022 13:21:42 -0400 Subject: [PATCH 29/30] CSR-319: fix syncing error between selectedValues and validation values --- .../list-button-horizontal.vue | 9 +++++++-- .../list-button/list-button.spec.js | 7 ++++++- src/ux-components/list-button/list-button.vue | 18 +++++++++++++++--- src/ux-components/list-card/list-card.spec.js | 15 +++++++++++++++ src/ux-components/list-card/list-card.vue | 11 ++++++++--- 5 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.vue b/src/ux-components/list-button-horizontal/list-button-horizontal.vue index 8ef069c2b..68aceec51 100644 --- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue +++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue @@ -109,11 +109,15 @@ export default { const fieldOptions = { type: inputType, checkedValue: props.value, + potentialInitialValue: props.selectedValues, }; - if (Array.isArray(props.selectedValues) && props.selectedValues.length == 1) { - fieldOptions['initialValue'] = fieldOptions.checkedValue; + // Set initialValue for validation setup if pre-selected + // NOTE: props.selectedValues could be an array of strings, or an array of integers... + if (props.selectedValues && (props.selectedValues.includes(props.value) || props.selectedValues.includes(parseInt(props.value)))) { + fieldOptions['initialValue'] = fieldOptions.potentialInitialValue; } + const { checked, handleChange, @@ -124,6 +128,7 @@ export default { checked, handleChange, errors, + fieldOptions, // only need to expose this for unit test purposes }; }, }; diff --git a/src/ux-components/list-button/list-button.spec.js b/src/ux-components/list-button/list-button.spec.js index 18707e45f..7cc885b49 100644 --- a/src/ux-components/list-button/list-button.spec.js +++ b/src/ux-components/list-button/list-button.spec.js @@ -166,11 +166,15 @@ describe("list-button.vue", () => { isRequired: true, isWide: false, modelValue: ["List Card Checkbox"], + buttonID: 'list-card-id' }, }); + wrapper.vm.handleCheckChange(); + // Assert - expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: Boolean}]); + expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: Boolean, buttonId: 'list-card-id'}]); + }); it("Should set checkValue data if selectedButtonIDs has value(s)", async () => { @@ -192,4 +196,5 @@ describe("list-button.vue", () => { // Assert expect(wrapper.componentVM.checkValue).toEqual("Car-Front"); }); + }); diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue index 3a8e65fc0..caef528de 100644 --- a/src/ux-components/list-button/list-button.vue +++ b/src/ux-components/list-button/list-button.vue @@ -100,7 +100,13 @@ export default { handleCheckChange(newValue, oldValue){ const isInitialization = typeof(oldValue) === 'function'; if (!isInitialization) { - this.$emit('isCheckedChanged', { checkValue: this.checkValue, value: this.value.toString() }); + const emitEvent = { + checkValue: this.checkValue, + value: this.value.toString(), + buttonId: this.buttonID.toString(), + }; + this.$emit('isCheckedChanged', emitEvent); + this.$emit("update:modelValue", emitEvent); } }, }, @@ -109,14 +115,19 @@ export default { }, setup(props) { const inputType = props.isMultiSelect ? "checkbox" : "radio"; + const fieldOptions = { type: inputType, checkedValue: props.value, + potentialInitialValue: props.selectedValues, }; - if (Array.isArray(props.selectedValues) && props.selectedValues.length == 1) { - fieldOptions['initialValue'] = fieldOptions.checkedValue; + // Set initialValue for validation setup if pre-selected + // NOTE: props.selectedValues could be an array of strings, or an array of integers... + if (props.selectedValues && (props.selectedValues.includes(props.value) || props.selectedValues.includes(parseInt(props.value)))) { + fieldOptions['initialValue'] = fieldOptions.potentialInitialValue; } + const { checked, handleChange, @@ -127,6 +138,7 @@ export default { checked, handleChange, errors, + fieldOptions, // only need to expose this for unit test purposes }; }, }; diff --git a/src/ux-components/list-card/list-card.spec.js b/src/ux-components/list-card/list-card.spec.js index 743392ee8..11f24abbb 100644 --- a/src/ux-components/list-card/list-card.spec.js +++ b/src/ux-components/list-card/list-card.spec.js @@ -232,5 +232,20 @@ describe("list-card.vue", () => { expect(wrapper.componentVM.checkValue).toEqual("Car-Front"); }); + it("Should set an initial value for validation if selectedValues include the value", async () => { + // Arrange + const wrapper = shallowMount(listCard, { + propsData: { + value: "Windshield", + groupName: "radio 1", + modelValue: ["Windshield"], + selectedValues: ["Windshield"], + }, + }); + + // Assert + expect(wrapper.vm.fieldOptions.initialValue).toEqual([ 'Windshield' ]); + }); + }); diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue index 8e88c4b68..d3a1fc712 100644 --- a/src/ux-components/list-card/list-card.vue +++ b/src/ux-components/list-card/list-card.vue @@ -58,6 +58,7 @@