diff --git a/jest.config.js b/jest.config.js
index ded486df9..4af0d88cc 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -28,7 +28,7 @@ module.exports = {
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
coverageThreshold: {
global: {
- statements: 85,
+ statements: 80,
// Got the go ahead from Mark to temporarily lower this. Taking out initialize component made the year,make,model and style coverage drop a bit. Once unit tests for license plate lookup, vin lookup and address lookup are in the coverage should go back up to 90
},
},
diff --git a/src/App.vue b/src/App.vue
index c934ee244..d817ff749 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -11,48 +11,12 @@
diff --git a/src/common-components/base-input-button/base-input-button.spec.js b/src/common-components/base-input-button/base-input-button.spec.js
index 56a49363f..72e7e4843 100644
--- a/src/common-components/base-input-button/base-input-button.spec.js
+++ b/src/common-components/base-input-button/base-input-button.spec.js
@@ -952,13 +952,30 @@ describe.skip("baseInputButton.vue", () => {
test.only("click on both => both are selected", async () => {
// Arrange
const { wrapper } = setupBaseInputButtonWrapper({
- isMultiSelect: true
+ isMultiSelect: true,
+ value1: "value1"
})
- console.log(wrapper.html())
+
// Act
const buttonWrappers = wrapper.findAllComponents({name: "baseInputButtonWrapper"})
- await buttonWrappers[0].trigger("click")
+
+ // The two together simulate a click
+ const inputOne = buttonWrappers.at(0);
+ await inputOne.trigger("mousedown.left")
+ await inputOne.trigger("change")
+ await inputOne.trigger("click")
+
+ console.log({
+ html: wrapper.html(),
+ buttonWrapper1: inputOne,
+ a: inputOne.vm.selectedValue,
+ c: inputOne.vm.modelValue,
+ d: inputOne.modelValue,
+ e: inputOne.vm.value,
+ f: inputOne.value,
+ })
+
// Assert
expect(wrapper.vm.value).toEqual(["value1"])
@@ -1015,8 +1032,8 @@ function setupBaseInputButtonWrapper({ mockData = {} }) {
};
let parentComponentTemplate = "
"
- parentComponentTemplate += ``
- parentComponentTemplate += ``
+ parentComponentTemplate += ``
+ parentComponentTemplate += ``
parentComponentTemplate += `
`
const wrapper = mount({
data() {
diff --git a/src/common-components/base-input-button/base-input-button.vue b/src/common-components/base-input-button/base-input-button.vue
index 5c7ca21f7..162f0866f 100644
--- a/src/common-components/base-input-button/base-input-button.vue
+++ b/src/common-components/base-input-button/base-input-button.vue
@@ -26,40 +26,15 @@
import { useField } from "vee-validate";
import { toRef } from "vue";
import { queryStrings } from "@/constants/query-strings";
-import inputButtonWrapperMixin from "../../mixins/input-button-wrapper-mixin";
+import { handleInputFocus, handleInputBlur } from "@/helpers/input-button-focus-helper";
+import { inputButtonProps } from "@/common-components/base-input-button/button-functionality-props";
export default {
name: "base-input-button",
props: {
- // ...inputButtonWrapperMixin.props
- value: {
- type: [String, Number],
- required: true,
- },
- modelValue: {
- type: [Array, String, Number],
- required: true,
- },
- isMultiSelect: Boolean,
- groupName: {
- type: String,
- required: true,
- },
- validationRules: {
- type: String,
- default: "",
- },
+ ...inputButtonProps,
buttonWrapperClasses: [String, Array, Object],
inputClasses: [String, Array, Object],
- valueToLogType: String,
- selectOnKeypress: {
- type: Boolean,
- default: true,
- },
- isRequired: Boolean,
- lastValuePushedToGa: [String, Number],
- setLastValuePushedToGa: Function,
- shouldPushClickEventToGAOnMount: Boolean,
},
data() {
return {
@@ -68,15 +43,15 @@ export default {
},
mounted() {
if (this.isChecked) {
- if (this.shouldPushClickEventToGAOnMount) {
- this.handleEventAction(this.eventTypes.MOUNT)
- } else {
- this.handleChange(this.modelValue);
- }
+ this.handleChange(this.modelValue);
}
},
methods: {
handleEventAction(eventType, e) {
+ console.log("HANDLE EVENT ACTION: ", {
+ eventType,
+ e
+ })
if (this.isMultiSelect) {
switch (eventType) {
case this.eventTypes.ENTER:
@@ -92,16 +67,15 @@ export default {
case this.eventTypes.CLICK:
case this.eventTypes.ENTER:
case this.eventTypes.SPACE:
- case this.eventTypes.MOUNT:
this.handleClick(e);
this.handlePushClickEventToGACheck(
this.eventTypes.CLICK
);
break;
case this.eventTypes.CHANGE:
- this.selectOnKeypress
- ? this.handleClick(e)
- : this.handleSelectionChange(e);
+ this.selectingInitiatesLoad
+ ? this.handleSelectionChange(e)
+ : this.handleClick(e);
break;
}
}
@@ -130,12 +104,12 @@ export default {
this.$emit("update:modelValue", this.valueToEmit);
},
handleFocus() {
- this.$root.handleInputFocus({
+ handleInputFocus({
groupName: this.groupName,
});
},
handleBlur() {
- this.$root.handleInputBlur({
+ handleInputBlur({
groupName: this.groupName,
onFocusCallback: this.handlePushClickEventToGACheck,
});
@@ -146,6 +120,7 @@ export default {
this.pushClickEventToGA();
} else { // if from tabbing around
if (
+ this.valueToEmit !== null &&
!this.isValueSelectedOnClick &&
this.isChecked &&
this.lastValuePushedToGa != this.value
@@ -193,7 +168,6 @@ export default {
ENTER: "enter",
SPACE: "space",
CLICK: "click",
- MOUNT: "mount"
};
},
},
diff --git a/src/common-components/base-input-button/button-functionality-props.js b/src/common-components/base-input-button/button-functionality-props.js
new file mode 100644
index 000000000..b9a63c925
--- /dev/null
+++ b/src/common-components/base-input-button/button-functionality-props.js
@@ -0,0 +1,30 @@
+export const inputButtonProps = {
+ value: {
+ type: [String, Number],
+ required: true,
+ },
+ modelValue: {
+ type: [Array, String, Number],
+ required: true,
+ },
+ isMultiSelect: Boolean,
+ groupName: {
+ type: String,
+ required: true,
+ },
+ validationRules: {
+ type: String,
+ default: "",
+ },
+ valueToLogType: String,
+ isRequired: {
+ type: Boolean,
+ default: true,
+ },
+ lastValuePushedToGa: [String, Number],
+ setLastValuePushedToGa: Function,
+ selectingInitiatesLoad: {
+ type: Boolean,
+ default: false,
+ },
+}
\ No newline at end of file
diff --git a/src/common-components/button-question/button-question.vue b/src/common-components/button-question/button-question.vue
index eb198c93f..56ab5abd7 100644
--- a/src/common-components/button-question/button-question.vue
+++ b/src/common-components/button-question/button-question.vue
@@ -49,10 +49,8 @@
:isWide="isWide"
:validationRules="validationRules"
:textPosition="textPosition"
- :selectOnKeypress="selectOnKeypress"
:lastValuePushedToGa="lastValuePushedToGa"
:setLastValuePushedToGa="setLastValuePushedToGa"
- :shouldPushClickEventToGAOnMount="shouldPushClickEventToGAOnMount"
v-model="selectedValues"
/>
@@ -118,11 +116,6 @@ export default {
suppressError: Boolean,
useTextForValue: Boolean,
valueToLogType: String,
- selectOnKeypress: {
- type: Boolean,
- default: true,
- },
- shouldPushClickEventToGAOnMount: Boolean
},
data() {
return {
@@ -179,7 +172,6 @@ export default {
}
},
buttonsInfo() {
- // TODO KO temporary. It should always just be an array
return (Array.isArray(this.answers) ? this.answers : [])?.map(
(answer) => ({
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
diff --git a/src/helpers/analytics-helper.js b/src/helpers/analytics-helper.js
new file mode 100644
index 000000000..23b6557ed
--- /dev/null
+++ b/src/helpers/analytics-helper.js
@@ -0,0 +1,35 @@
+let lastFocusedInputGroupName = "";
+let onFocusCallback = null;
+
+// TODO KO Add tests for this file
+const handleChildFocus = (e) => {
+ const targetType = e.target.type;
+ if (targetType !== "radio" && targetType !== "checkbox") {
+ handleInputFocus({
+ groupName: null,
+ });
+ }
+}
+
+const handleInputFocus = (e) => {
+ if (
+ e &&
+ lastFocusedInputGroupName !== e.groupName &&
+ onFocusCallback
+ ) {
+ onFocusCallback();
+ }
+}
+
+const handleInputBlur = (e) => {
+ if (e) {
+ lastFocusedInputGroupName = e.groupName;
+ onFocusCallback = e.onFocusCallback;
+ }
+}
+
+export {
+ handleChildFocus,
+ handleInputFocus,
+ handleInputBlur
+}
\ No newline at end of file
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 d4da8cd1b..503c30cb8 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
@@ -25,7 +25,7 @@ export default ({
name: "replaceOptionsQuestion",
data(){
return {
- replaceOptions: [],
+ replaceOptions: this.isMultiSelect ? [] : "",
}
},
props: {
@@ -46,7 +46,7 @@ export default ({
updateSelectedValues() {
// UPDATE SELECTEDVALUES IF ONLY ONE ANSWER
if(Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1) {
- this.selectedValues = [this.answersToDisplay[0].Name];
+ this.selectedValues = this.isMultiSelect ? [this.answersToDisplay[0].Name] : this.answersToDisplay[0].Name;
}
},
},
@@ -91,7 +91,7 @@ export default ({
},
shouldDisplayReplaceOptionsQuestion(shouldDisplayReplaceOptionsQuestion) {
if (!shouldDisplayReplaceOptionsQuestion) {
- this.selectedValues = [];
+ this.selectedValues = this.isMultiSelect ? [] : "";
}
}
},
diff --git a/src/layouts/vehicle-damage/side-door-options/side-door-options.vue b/src/layouts/vehicle-damage/side-door-options/side-door-options.vue
index 9af96c117..99f644d6f 100644
--- a/src/layouts/vehicle-damage/side-door-options/side-door-options.vue
+++ b/src/layouts/vehicle-damage/side-door-options/side-door-options.vue
@@ -57,7 +57,7 @@ export default ({
name: "sideDoorOptions",
props: {
groupName: String,
- modelValue: [Array, Object], // TODO Does this take an array?
+ modelValue: Object,
selectedDamageLocations: Array,
cmsWidgetName: String,
},
diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue
index 31b008760..8081bb2b2 100644
--- a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue
+++ b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue
@@ -57,8 +57,8 @@ defineRule("windshield-replace-options-required", required(errorMessages.WINSHIE
defineRule("check-for-repair-and-replace", (selectedWindshieldDamageType, selectedDamageLocations) => {
return selectedWindshieldDamageType.toString() != damageLocationsSelected.REPAIR ||
- (!selectedDamageLocations.includes(damageLocationsSelected.WINDSHIELD) && !selectedDamageLocations[0]?.includes(damageLocationsSelected.WINDSHIELD)) ||
- (selectedDamageLocations.length === 1 && selectedDamageLocations[0].length === 1);
+ (!selectedDamageLocations.includes(damageLocationsSelected.WINDSHIELD) && !selectedDamageLocations[0]?.includes(damageLocationsSelected.WINDSHIELD)) ||
+ (selectedDamageLocations[0].length === 1);
});
defineRule("repair-only", (value) => {
return value.toString() === damageLocationsSelected.REPAIR;
@@ -83,7 +83,7 @@ export default ({
},
props: {
- modelValue: [Object, String], // TODO Does this take a string?
+ modelValue: Object,
selectedDamageLocations: Array,
hasRepairReplaceConflict: Boolean,
hasSplitSingleConflict: Boolean,
diff --git a/src/layouts/vehicle-make/make-question/make-question.vue b/src/layouts/vehicle-make/make-question/make-question.vue
index c2a7cd2d2..28246814f 100644
--- a/src/layouts/vehicle-make/make-question/make-question.vue
+++ b/src/layouts/vehicle-make/make-question/make-question.vue
@@ -8,7 +8,6 @@
groupName="ChooseVehicleMake"
textPosition="text-start"
v-model="selectedValue"
- :selectOnKeypress="false"
isRequired
/>
diff --git a/src/layouts/vehicle-model/model-question/model-question.vue b/src/layouts/vehicle-model/model-question/model-question.vue
index 393df6fc9..bc20bdc6a 100644
--- a/src/layouts/vehicle-model/model-question/model-question.vue
+++ b/src/layouts/vehicle-model/model-question/model-question.vue
@@ -8,7 +8,6 @@
groupName="ChooseVehicleModel"
textPosition="text-start"
v-model="selectedValue"
- :selectOnKeypress="false"
isRequired
/>
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 14f707818..d45c8cddb 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
@@ -27,9 +27,7 @@
isRequired
:groupName="`${glassLocation}-${glassName}-${selectedTint}`"
:validationRules="partValidationRules"
- :shouldPushClickEventToGAOnMount="
- shouldPushClickEventToGAOnMount
- " />
+ />
@@ -57,7 +55,6 @@ export default {
glassColorQuestion: "",
glassFeatureQuestion: "",
selectedTint: "",
- shouldPushClickEventToGAOnMount: true,
};
},
props: {
@@ -224,7 +221,6 @@ export default {
this.$nextTick(() => {
if (this.modelValue !== undefined) {
// Populate button-question model-value if parts data already exists in VueX
- this.shouldPushClickEventToGAOnMount = false;
this.selectedTint = this.modelValue?.color
}
});
diff --git a/src/layouts/vehicle-style/style-question/style-question.vue b/src/layouts/vehicle-style/style-question/style-question.vue
index bf8fd3d07..806f7ac41 100644
--- a/src/layouts/vehicle-style/style-question/style-question.vue
+++ b/src/layouts/vehicle-style/style-question/style-question.vue
@@ -8,7 +8,6 @@
groupName="ChooseVehicleStyle"
textPosition="text-start"
v-model="selectedValue"
- :selectOnKeypress="false"
isRequired
/>
diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue
index 06af5ce64..6851f282c 100644
--- a/src/layouts/vehicle-year/year-question/year-question.vue
+++ b/src/layouts/vehicle-year/year-question/year-question.vue
@@ -8,7 +8,6 @@
groupName="ChooseVehicleYear"
textPosition="text-start"
v-model="selectedValue"
- :selectOnKeypress="false"
isRequired
/>
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index 6eb18e462..e773c6a01 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -48,6 +48,7 @@ export default {
pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null) {
const currentPageName = getPageNameByQueryString();
const labelToLog = getValueToLog(label, valueToLogType);
+
const eventToBePushed = {
'event': GaEvents.GENERIC_EVENT,
'category': category,
@@ -140,7 +141,7 @@ export default {
noSession() {
return getSessionKeyValue() === 0 || getSessionIdValue() === '00000000-0000-0000-0000-000000000000';
- }
+ },
},
computed: {
analyticsPageEvents() {
diff --git a/src/mixins/input-button-wrapper-mixin.js b/src/mixins/input-button-wrapper-mixin.js
index eae27c2fe..866e5d1d6 100644
--- a/src/mixins/input-button-wrapper-mixin.js
+++ b/src/mixins/input-button-wrapper-mixin.js
@@ -1,9 +1,8 @@
+import { inputButtonProps } from "@/common-components/base-input-button/button-functionality-props";
+
export default {
props: {
- modelValue: [Array, String, Number],
- value: [String, Number],
- isMultiSelect: Boolean,
- groupName: String,
+ ...inputButtonProps,
buttonLabel: [Number, String],
buttonLabelSubCopy: String,
buttonImage: String,
@@ -13,16 +12,7 @@ export default {
},
textPosition: String,
screenReaderOnlyText: String,
- valueToLogType: String,
- validationRules: String,
isWide: Boolean,
- isRequired: {
- type: Boolean,
- default: true,
- },
- lastValuePushedToGa: [String, Number],
- setLastValuePushedToGa: Function,
- shouldPushClickEventToGAOnMount: Boolean,
},
computed: {
selectedValue: {
diff --git a/src/store/index.js b/src/store/index.js
index 1d6e68482..8d2f6b309 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1044,11 +1044,8 @@ export const actions = {
);
const isWindshieldRepairTheSame =
isWindshieldRepair === context.state.order.damage.isRepair;
- const isChipCountTheSame = Array.isArray(selectedWindshieldChipCount) //TODO: fix the underlying components so this is never an array
- ? selectedWindshieldChipCount[0] ===
- context.state.order.damage.numberOfChips
- : selectedWindshieldChipCount ===
- context.state.order.damage.numberOfChips;
+
+ const isChipCountTheSame = selectedWindshieldChipCount === context.state.order.damage.numberOfChips;
const isDamageChanging =
!isGlassToReplaceTheSame ||