+
+ isRequired
+ />
+ }
+})
+
\ No newline at end of file
diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-options.vue b/src/layouts/vehicle-damage/windshield-options/windshield-options.vue
index f22370d69..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.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: 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 4b783f2c5..28246814f 100644
--- a/src/layouts/vehicle-make/make-question/make-question.vue
+++ b/src/layouts/vehicle-make/make-question/make-question.vue
@@ -1,15 +1,15 @@
-
+
diff --git a/src/layouts/vehicle-model/model-question/model-question.vue b/src/layouts/vehicle-model/model-question/model-question.vue
index a302a80f1..bc20bdc6a 100644
--- a/src/layouts/vehicle-model/model-question/model-question.vue
+++ b/src/layouts/vehicle-model/model-question/model-question.vue
@@ -7,8 +7,7 @@
:answers="models"
groupName="ChooseVehicleModel"
textPosition="text-start"
- v-model="selectedModel"
- :selectOnKeypress="false"
+ v-model="selectedValue"
isRequired
/>
@@ -19,15 +18,12 @@ import buttonQuestion from "@/common-components/button-question/button-question"
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
-import buttonQuestionWrapperMixin from "@/mixins/button-question-wrapper-mixin";
export default {
name: "model-question",
- mixins: [buttonQuestionWrapperMixin],
data() {
return {
models: [],
- selectedModel: ""
};
},
props: {
@@ -38,6 +34,14 @@ export default {
questionText(){
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
},
+ selectedValue: {
+ get: function() {
+ return this.modelValue
+ },
+ set: function(newValue) {
+ this.$emit("update:modelValue", newValue);
+ }
+ }
},
components: {
buttonQuestion,
@@ -53,10 +57,5 @@ export default {
this.models = initialData;
},
},
- watch: {
- selectedModel(selectedModel) {
- this.$emit("update:modelValue", selectedModel);
- }
- }
};
diff --git a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js
index 6c0ac1e4b..6f8c063fb 100644
--- a/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js
+++ b/src/layouts/vehicle-parts/glass-part-question/glass-part-question.spec.js
@@ -18,9 +18,7 @@ const featureListData = {
modelValueProp: {}
}
-// TODO KO
-describe.skip("glass-part-question.vue", () => {
-
+describe("glass-part-question.vue", () => {
test("Part data passed in, should map data for ButtonQuestion (radio type)", async () => {
//Arrange
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 158c7642e..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
@@ -13,8 +13,7 @@
altText=""
isRequired
:groupName="`${glassLocation}-${glassName}`"
- :validationRules="tintValidationRules"
- >
+ :validationRules="tintValidationRules">
@@ -63,7 +62,10 @@ export default {
glassLocation: String,
colorAnswers: Array,
modelValue: Object,
- alreadyPopulatedPartsData: Array
+ alreadyPopulatedPartsData: {
+ type: Array,
+ default: () => [],
+ },
},
mounted() {
this.LoadPreselectedValues();
@@ -74,12 +76,18 @@ export default {
computed: {
tintValidationRules() {
const validationRuleName = `${this.glassLocation}-${this.glassName}-tint-required`;
- defineRule(validationRuleName, required(errorMessages.OPTION_REQUIRED));
+ defineRule(
+ validationRuleName,
+ required(errorMessages.OPTION_REQUIRED)
+ );
return validationRuleName;
},
partValidationRules() {
const validationRuleName = `${this.glassLocation}-${this.glassName}-part-required`;
- defineRule(validationRuleName, required(errorMessages.OPTION_REQUIRED));
+ defineRule(
+ validationRuleName,
+ required(errorMessages.OPTION_REQUIRED)
+ );
return validationRuleName;
},
colorQuestionText() {
@@ -110,16 +118,29 @@ export default {
return this.modelValue?.partNumber;
},
set(newValue) {
- this.$emit("update:modelValue", this.partsForSelectedTint.filter(part => part.partNumber == newValue)[0]);
+ this.$emit(
+ "update:modelValue",
+ this.partsForSelectedTint.filter(
+ (part) => part.partNumber == newValue
+ )[0]
+ );
},
},
partsForSelectedTint() {
- const matchingGlass = this.PartDataFromApi.partsOrQuestions?.filter(dataForGlassLocationAndName =>
- dataForGlassLocationAndName.glassName == this.glassName &&
- dataForGlassLocationAndName.glassLocation == this.glassLocation);
- const matchingGlassParts = matchingGlass?.length == 1 ? matchingGlass[0].parts : [];
- return matchingGlassParts.filter(part => part.color == this.selectedTint) ?? [];
+ const matchingGlass = this.PartDataFromApi.partsOrQuestions?.filter(
+ (dataForGlassLocationAndName) =>
+ dataForGlassLocationAndName.glassName == this.glassName &&
+ dataForGlassLocationAndName.glassLocation ==
+ this.glassLocation
+ );
+ const matchingGlassParts =
+ matchingGlass?.length == 1 ? matchingGlass[0].parts : [];
+ return (
+ matchingGlassParts.filter(
+ (part) => part.color == this.selectedTint
+ ) ?? []
+ );
},
// Creates a map of the feature list data in the correct Name/Value
@@ -151,7 +172,9 @@ export default {
},
PartDataFromApi() {
- return this.$store.getters.pageData(this.$route.query.fmgPage) ?? {};
+ return (
+ this.$store.getters.pageData(this.$route.query.fmgPage) ?? {}
+ );
},
},
methods: {
@@ -188,7 +211,8 @@ export default {
// Check if only a single part is present for the tint and set the v-model if it is.
AutoSelectIfSinglePart() {
if (this.partsForSelectedTint?.length == 1) {
- this.selectedPartNumber = this.partsForSelectedTint[0].partNumber;
+ this.selectedPartNumber =
+ this.partsForSelectedTint[0].partNumber;
}
},
@@ -197,7 +221,7 @@ export default {
this.$nextTick(() => {
if (this.modelValue !== undefined) {
// Populate button-question model-value if parts data already exists in VueX
- this.selectedTint = this.alreadyPopulatedPartsData.filter(part => part.partNumber === this.selectedPartNumber)[0]?.color;
+ this.selectedTint = this.modelValue?.color
}
});
},
@@ -205,8 +229,8 @@ export default {
watch: {
selectedTint() {
this.AutoSelectIfSinglePart();
- }
- }
+ },
+ },
};
diff --git a/src/layouts/vehicle-parts/vehicle-parts.spec.js b/src/layouts/vehicle-parts/vehicle-parts.spec.js
index 2fce952c2..7e6fe9130 100644
--- a/src/layouts/vehicle-parts/vehicle-parts.spec.js
+++ b/src/layouts/vehicle-parts/vehicle-parts.spec.js
@@ -148,7 +148,7 @@ describe("vehicle-parts.vue", () => {
expect(arePagePrerequisitesValid).toBe(true);
});
- test("Initial data, should populate this.selectedGlassParts", async () => {
+ test.only("Initial data, should populate this.selectedGlassParts", async () => {
//Arrange
store.getters.pageData.mockReturnValue(basePartResponse);
@@ -183,7 +183,16 @@ describe("vehicle-parts.vue", () => {
await nextTick();
//Assert
- expect(wrapper.vm.selectedGlassParts).toEqual({ "Rear-Stationary": { "Rear": ['DB12209YPYNOEM'] } });
+ expect(wrapper.vm.selectedGlassParts).toEqual({
+ "Rear-Stationary": {
+ partNumber: "DB12209YPYNOEM",
+ description: "heated glass, solar, 1 hole",
+ color: "Gray Tint Privacy",
+ requiresRecalibration: false,
+ requiresCapabilityQuestions: false,
+ childParts: null
+ }
+ });
});
test("User had part questions > BackButtonAction triggers a router.navigateWithoutSaving change with correct scenario", async () => {
@@ -509,6 +518,8 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
+ // wrapper.vm.$refs.onSubmit = jest.fn();
+ // wrapper.vm.$refs.onInvalidSubmit = jest.fn();
return { wrapper, apiPromise };
}
diff --git a/src/layouts/vehicle-parts/vehicle-parts.vue b/src/layouts/vehicle-parts/vehicle-parts.vue
index 43a20244d..52e1b2a08 100644
--- a/src/layouts/vehicle-parts/vehicle-parts.vue
+++ b/src/layouts/vehicle-parts/vehicle-parts.vue
@@ -204,9 +204,7 @@ export default {
const partNumber = this.alreadyPopulatedPartsData[key].partNumber;
g.parts.forEach((p) => {
if (p.partNumber === partNumber) {
- this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = {
- [g.glassLocation]: [partNumber],
- };
+ this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = p;
}
});
});
diff --git a/src/layouts/vehicle-style/style-question/style-question.vue b/src/layouts/vehicle-style/style-question/style-question.vue
index 039530f81..806f7ac41 100644
--- a/src/layouts/vehicle-style/style-question/style-question.vue
+++ b/src/layouts/vehicle-style/style-question/style-question.vue
@@ -7,8 +7,7 @@
:answers="styles"
groupName="ChooseVehicleStyle"
textPosition="text-start"
- v-model="selectedStyle"
- :selectOnKeypress="false"
+ v-model="selectedValue"
isRequired
/>
@@ -19,24 +18,30 @@ import buttonQuestion from "@/common-components/button-question/button-question"
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
-// import buttonQuestionWrapperMixin from "@/mixins/button-question-wrapper-mixin";
export default {
name: "style-question",
- // mixins: [buttonQuestionWrapperMixin],
data() {
return {
styles: [],
- selectedStyle: ""
};
},
props: {
+ modelValue: String,
cmsWidgetName: String,
},
computed: {
questionText(){
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
},
+ selectedValue: {
+ get: function() {
+ return this.modelValue
+ },
+ set: function(newValue) {
+ this.$emit("update:modelValue", newValue);
+ }
+ }
},
components: {
buttonQuestion,
@@ -56,10 +61,5 @@ export default {
this.styles = initialData;
},
},
- watch: {
- selectedStyle(selectedStyle) {
- this.$emit("update:modelValue", selectedStyle);
- }
- }
};
diff --git a/src/layouts/vehicle-year/year-question/year-question.vue b/src/layouts/vehicle-year/year-question/year-question.vue
index 694a81cd9..6851f282c 100644
--- a/src/layouts/vehicle-year/year-question/year-question.vue
+++ b/src/layouts/vehicle-year/year-question/year-question.vue
@@ -1,18 +1,15 @@
-
-
-
+
diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js
index 556ca509e..e773c6a01 100644
--- a/src/mixins/analytics-mixin.js
+++ b/src/mixins/analytics-mixin.js
@@ -29,8 +29,6 @@ export default {
logCustomEvent(category, action, label, value) {
const currentPageName = getPageNameByQueryString();
- console.log("PUSHING: ", label)
-
var payload = {
userId: getDeviceIdValue(),
sessionKey: getSessionKeyValue(),
@@ -50,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,
@@ -142,7 +141,7 @@ export default {
noSession() {
return getSessionKeyValue() === 0 || getSessionIdValue() === '00000000-0000-0000-0000-000000000000';
- }
+ },
},
computed: {
analyticsPageEvents() {
diff --git a/src/mixins/base-mixin.js b/src/mixins/base-mixin.js
index d42845e33..f7d046bf7 100644
--- a/src/mixins/base-mixin.js
+++ b/src/mixins/base-mixin.js
@@ -6,12 +6,11 @@ import { vehicleCategories } from "@/constants/vehicle-categories.js";
import { routerParams } from "@/router/router-constants/router-params";
import { queryStrings } from "@/constants/query-strings";
import { dynamicStrings } from "@/constants/dynamic-strings";
-import { settleAllPromises } from "@/helpers/layout-helper";
export default {
data() {
return {
- cmsContentByWidget: {}
+ cmsContentByWidget: {},
};
},
methods: {
@@ -19,7 +18,9 @@ export default {
this.$root.cmsContentByWidget = cmsContent;
},
getCmsContent(widgetName, fieldName) {
- return this.$root.cmsContentByWidget?.[widgetName]?.[fieldName] ? this.$root.cmsContentByWidget[widgetName][fieldName] : '';
+ return this.$root.cmsContentByWidget?.[widgetName]?.[fieldName]
+ ? this.$root.cmsContentByWidget[widgetName][fieldName]
+ : "";
},
dispatchStoreAction(type, payload, encodePayload = true) {
// Encode the payload if required
@@ -32,7 +33,7 @@ export default {
savePageDataToStore(page, data) {
store.commit(storeMutations.UPDATE_PAGE_DATA, { page: page, data: data });
},
- onSubmit() { }, // DO NOT REMOVE; needed to prevent default form submit behavior. Cannot use .prevent modifier for vee-validate Form
+ onSubmit() {}, // DO NOT REMOVE; needed to prevent default form submit behavior. Cannot use .prevent modifier for vee-validate Form
onInvalidSubmit({ values, errors, results }) {
// identify the first error field and put focus on it
// get error names array
@@ -49,12 +50,15 @@ export default {
return footerInfoBox ? footerInfoBox.offsetHeight : 0;
},
async getZipCodeData(zipCode) {
- const serviceZipValidationResponse = await this.dispatchStoreAction(storeActions.VALIDATE_ZIP, { zip: zipCode });
-
- return {
- isValid: serviceZipValidationResponse.data.isValid,
+ const serviceZipValidationResponse = await this.dispatchStoreAction(
+ storeActions.VALIDATE_ZIP,
+ { zip: zipCode }
+ );
+
+ return {
+ isValid: serviceZipValidationResponse.data.isValid,
isServiceable: serviceZipValidationResponse.data.isServiceable,
- state: serviceZipValidationResponse.data.state
+ state: serviceZipValidationResponse.data.state,
};
},
getEconomyPackagePrice(lineItems) {
@@ -82,13 +86,13 @@ export default {
routerParams() {
return routerParams;
},
- queryStrings(){
+ queryStrings() {
return queryStrings;
},
- dynamicStrings(){
+ dynamicStrings() {
return dynamicStrings;
},
- cssClassNameForCmsWidget(){
+ cssClassNameForCmsWidget() {
return "widget-name-" + this.cmsWidgetName;
},
},
diff --git a/src/mixins/button-question-wrapper-mixin.js b/src/mixins/button-question-wrapper-mixin.js
deleted file mode 100644
index df31218fc..000000000
--- a/src/mixins/button-question-wrapper-mixin.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { ref, isRef } from "vue";
-
-export default {
- props: {
- modelValue: [Array, String, Number],
- // modelValueName: {
- // type: String,
- // required: true,
- // },
- },
- data() {
- return {
- selectedValue: null,
- };
- },
- created() {
- this.selectedValue = this.modelValue;
-
- console.log("Created: ", {
- selectedValue: this.selectedValue,
- // modelValue: this.modelValue,
- // modelValueName: this.modelValueName
- })
- if (this.modelValueName) {
- this[this.modelValueName] = this.selectedValue;
- // this.$on("update:modelValue", (dynamicModelValue) => {
- // console.log("ON HIT", {
- // dynamicModelValue: dynamicModelValue
- // })
- // this.selectedValue = dynamicModelValue;
- // this.$emit("update:modelValue", dynamicModelValue)
- // })
- }
- },
-};
diff --git a/src/mixins/input-button-wrapper-mixin.js b/src/mixins/input-button-wrapper-mixin.js
index c8424504f..ddc7c4583 100644
--- a/src/mixins/input-button-wrapper-mixin.js
+++ b/src/mixins/input-button-wrapper-mixin.js
@@ -1,43 +1,36 @@
+import { inputButtonProps } from "@/common-components/base-input-button/button-functionality-props";
+
export default {
+ model: {
+ prop: "modelValue",
+ event: "change",
+ },
props: {
- modelValue: [Array, String, Number],
- value: [String, Number],
- isMultiSelect: Boolean,
- groupName: String,
+ ...inputButtonProps,
buttonLabel: [Number, String],
buttonLabelSubCopy: String,
buttonImage: String,
altText: {
type: String,
- default: ""
+ default: "",
},
textPosition: String,
screenReaderOnlyText: String,
- valueToLogType: String,
- validationRules: String,
isWide: Boolean,
- isRequired: Boolean,
additionalData: null,
},
- data() {
- return {
- selectedValue: null,
- };
- },
- mounted() {
- this.selectedValue = this.modelValue;
- },
- methods: {
- handleAnswerChange(e) {
- if (this.preHandleAnswerChange) {
- this.preHandleAnswerChange(e)
- }
- this.$emit("change", e);
+ computed: {
+ selectedValue: {
+ get() {
+ return this.modelValue;
+ },
+ set(e) {
+ if (this.preHandleAnswerChange) {
+ this.preHandleAnswerChange(e);
+ }
+
+ this.$emit("update:modelValue", e);
+ },
},
},
- watch: {
- selectedValue(selectedValue) {
- this.$emit("update:modelValue", selectedValue);
- },
- },
-};
+};
\ No newline at end of file
diff --git a/src/mixins/input-button-wrapper-mixin.spec.js b/src/mixins/input-button-wrapper-mixin.spec.js
new file mode 100644
index 000000000..8f03de0aa
--- /dev/null
+++ b/src/mixins/input-button-wrapper-mixin.spec.js
@@ -0,0 +1,81 @@
+describe("input-button-wrapper-mixin", () => {
+ describe("mouse clicks", () => {
+ describe("checkbox", () => {
+ test.todo("clicking once checks the baseInputButton");
+
+ test.todo("clicking twice unchecks the baseInputButton");
+
+ test.todo(
+ "is initially checked => checking unchecks the baseInputButton"
+ );
+
+ test.todo("clicked => correct event and value are emitted");
+ });
+
+ describe("radio", () => {
+ test.todo("clicking once selects the baseInputButton");
+
+ test.todo("clicking twice keeps the baseInputButton selected");
+
+ test.todo(
+ "is initially selected => click keeps the baseInputButton selected"
+ );
+
+ test.todo("clicked => correct event and value are emitted");
+ });
+ });
+
+ describe("keyboard navigation and", () => {
+ describe("checkbox", () => {
+ test.todo(
+ "focus on a checkbox => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "blur from a checkbox => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "focus and click space on a checkbox => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click space on a checkbox that is already checked => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click enter on a checkbox => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click enter on a checkbox that is already checked => inputButtonClicked is emitted with correct value"
+ );
+ });
+
+ describe("radio", () => {
+ test.todo(
+ "focus on a radio button => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "blur from a radio button => inputButtonClicked is not emitted"
+ );
+
+ test.todo(
+ "focus and click space on a radio button => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click space on a radio button that is already selected => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click enter on a radio button => inputButtonClicked is emitted with correct value"
+ );
+
+ test.todo(
+ "focus and click enter on a radio button that is already selected => inputButtonClicked is emitted with correct value"
+ );
+ });
+ });
+});
diff --git a/src/mixins/vehicle-questions-mixin.js b/src/mixins/vehicle-questions-mixin.js
index a6fe31196..89ae063e2 100644
--- a/src/mixins/vehicle-questions-mixin.js
+++ b/src/mixins/vehicle-questions-mixin.js
@@ -136,9 +136,6 @@ export default {
const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions);
const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions);
- console.log({
- hasGlassLocationWithMultipleParts: hasGlassLocationWithMultipleParts
- })
if (hasPartQuestions && this.currentPageComesBeforePage(currentPage, fmgPageValues.PART_QUESTIONS)) {
self.$router.navigateWithSaving(self.navigationScenarios.HAS_PART_QUESTIONS, self.$route, {}, {}, { partsOrQuestions: partsOrQuestions });
}
diff --git a/src/router/index.js b/src/router/index.js
index 79d62873d..c9e0a4a52 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -239,8 +239,6 @@ function navigateToUrl(url, optionalQuery = {}) {
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
}
- externalUrl.searchParams.append("experiments", "ConceptFunnel=ConceptFunnel_V1=ConceptFunnel_TEST=true");
-
window.location.assign(externalUrl);
}
diff --git a/src/store/index.js b/src/store/index.js
index 9d5b014be..43d6fe7b0 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -1,4 +1,4 @@
-import { createStore } from "vuex";
+import { createStore, Store } from "vuex";
import { endpoints } from "@/constants/endpoints.js";
import { storeMutations } from "@/constants/store-mutations";
import { getDateForSavedSessionTimeout } from "@/helpers/heritage-integration/session-helper";
@@ -53,19 +53,19 @@ const getDefaultState = () => {
capabilityQuestionAnswers: null,
},
lineItems: {
- glassParts: null
+ glassParts: null,
},
payment: {
isInsurance: null,
insuranceCoverage: {
- isVerified: null
- }
+ isVerified: null,
+ },
},
referralNumber: null,
referralDate: null,
referralCorrelationId: null,
accountNumber: 0,
- eon: null
+ eon: null,
},
applicationUser: {
eventBus: [],
@@ -76,9 +76,15 @@ const getDefaultState = () => {
crmCustomerId: null,
lastPageVisited: null,
experiments: [],
- triggeredSiteEntry: false
+ triggeredSiteEntry: false,
},
- }
+ // gaClickInformation: {
+ // currentlySelectedValues: {},
+ // firedGaClickEventValues: {},
+ // lastFocusedInputGroup: "",
+ // wasLastFocusedInputMultiselect: undefined,
+ // },
+ };
};
export const state = getDefaultState();
@@ -195,7 +201,6 @@ export const mutations = {
state.order.customer.emailAddress = customerEmailAddress;
},
updateVehicle(state, vehicleInfo) {
-
state.order.vehicle.year = vehicleInfo.year;
state.order.vehicle.make = vehicleInfo.make;
state.order.vehicle.model = vehicleInfo.model;
@@ -209,7 +214,8 @@ export const mutations = {
state.order.vehicle.imageColor = vehicleInfo.imageVifColor;
},
updateRegistration(state, registrationInfo) {
- state.order.vehicle.registration.licensePlate = registrationInfo?.licensePlate;
+ state.order.vehicle.registration.licensePlate =
+ registrationInfo?.licensePlate;
state.order.vehicle.registration.address = registrationInfo?.address;
state.order.vehicle.registration.city = registrationInfo?.city;
state.order.vehicle.registration.state = registrationInfo?.state;
@@ -235,7 +241,7 @@ export const mutations = {
state.applicationUser.crmCustomerId = crmCustomerId;
},
updateLastPageVisited(state, lastPageVisited) {
- state.applicationUser.lastPageVisited = lastPageVisited
+ state.applicationUser.lastPageVisited = lastPageVisited;
},
// EVENT BUS MUTATIONS
addEventToBus(state, event) {
@@ -244,8 +250,7 @@ export const mutations = {
removeEventFromBus(state, eventData) {
const matchedEvent = state.applicationUser.eventBus.find(
({ category, subCategory }) =>
- category === eventData.category &&
- subCategory === eventData.subCategory
+ category === eventData.category && subCategory === eventData.subCategory
);
const itemIndex = state.applicationUser.eventBus.indexOf(matchedEvent);
@@ -331,7 +336,7 @@ export const mutations = {
state: orderInformation.vehicle.registration.state,
zipCode: orderInformation.vehicle.registration.zipCode,
licensePlate: orderInformation.vehicle.registration.licensePlateNumber,
- }
+ },
});
state.order.damage.glassToReplace = orderInformation.damage.glassToReplace;
@@ -340,13 +345,18 @@ export const mutations = {
state.order.lineItems.glassParts = orderInformation.parts;
state.order.accountNumber = orderInformation.accountNumber;
- state.order.serviceLocation.address = orderInformation.serviceLocation.streetAddress,
- state.order.serviceLocation.city = orderInformation.serviceLocation.city,
- state.order.serviceLocation.state = orderInformation.serviceLocation.state,
- state.order.serviceLocation.zipCode = orderInformation.serviceLocation.zipCode;
+ (state.order.serviceLocation.address =
+ orderInformation.serviceLocation.streetAddress),
+ (state.order.serviceLocation.city =
+ orderInformation.serviceLocation.city),
+ (state.order.serviceLocation.state =
+ orderInformation.serviceLocation.state),
+ (state.order.serviceLocation.zipCode =
+ orderInformation.serviceLocation.zipCode);
state.order.payment.isInsurance = orderInformation.IsInsuranceOrder;
- state.order.payment.insuranceCoverage.isVerified = orderInformation?.insuranceInfo.coverageVerified;
+ state.order.payment.insuranceCoverage.isVerified =
+ orderInformation?.insuranceInfo.coverageVerified;
state.order.customer.emailAddress = orderInformation.customer.emailAddress;
state.applicationUser.experiments = orderInformation.experiments;
@@ -356,8 +366,23 @@ export const mutations = {
},
updateTriggeredSiteEntry(state, wasSiteEntryTriggered) {
state.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered;
- }
-}
+ },
+ // START GA click event mutations
+ // updateCurrentlySelectedValues(state, groupName, value) {
+ // state.gaClickInformation.currentlySelectedValues[groupName] = value;
+ // },
+ // updateFiredGaClickEventValues(state, groupName, value) {
+ // state.gaClickInformation.firedGaClickEventValues[groupName] = value;
+ // },
+ // updateLastFocusedInputGroup(state, groupName) {
+ // state.gaClickInformation.lastFocusedInputGroup = groupName;
+ // },
+ // updateWasLastFocusedInputMultiselect(state, wasLastFocusedInputMultiselect) {
+ // state.gaClickInformation.wasLastFocusedInputMultiselect =
+ // wasLastFocusedInputMultiselect;
+ // },
+ // END GA click event mutations
+};
// Export Getters
export const getters = {
@@ -377,7 +402,9 @@ export const getters = {
return !!nonWindshieldItems.length;
},
lineItems: (state) => state.order.lineItems,
- pageData: (state) => (page) => { return state.applicationUser.pageData[page]; },
+ pageData: (state) => (page) => {
+ return state.applicationUser.pageData[page];
+ },
applicationUser: (state) => state.applicationUser,
order: (state) => state.order,
payment: (state) => state.order.payment,
@@ -394,7 +421,8 @@ export const getters = {
funnelServiceState: state.order.serviceLocation.state,
funnelServiceZipCode: state.order.serviceLocation.zipCode,
funnelParentAccountNumber: state.order.accountNumber,
- funnelIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified,
+ funnelIsCoverageVerified:
+ state.order.payment.insuranceCoverage.isVerified,
funnelHasRecalibrationPart: getHasRecalibrationPart(state),
funnelSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1,
funnelSelectedWindshieldGlass: getNonFalseValuesOfPropertyInArrayOfObjects(state.order.damage.glassToReplace, "glassLocation").includes(damageLocationsSelected.WINDSHIELD),
@@ -407,8 +435,12 @@ export const getters = {
funnelOrderPartTypes: [...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.glassParts, "recalibrationType"), ...getNonFalseValuesOfPropertyInArrayOfObjects(state.order.lineItems.otherParts, "recalibrationType")],
}
},
- experimentSettings: (state) => state.applicationUser.experiments.map(x => x.settings).reduce((r, c) => Object.assign(r, c), {}) ?? {}
-}
+ experimentSettings: (state) =>
+ state.applicationUser.experiments
+ .map((x) => x.settings)
+ .reduce((r, c) => Object.assign(r, c), {}) ?? {},
+ // gaClickInformation: (state) => state.gaClickInformation,
+};
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
return (array ?? []).map(x => x[propertyName]).filter(x => x);
@@ -416,7 +448,6 @@ function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
// Export Actions
export const actions = {
-
// Vehicle API Actions
getVehicleYears(context) {
return globalMethods.callHttpClient({
@@ -447,11 +478,14 @@ export const actions = {
endpoint: endpoints.LookupVinByPlate.url,
payload: {
licensePlate: licensePlate,
- licenseState: licenseState
+ licenseState: licenseState,
},
});
},
- lookupVinByAddress(context, { licenseLastName, licenseStreetAddress, licenseZip, licenseState }) {
+ lookupVinByAddress(
+ context,
+ { licenseLastName, licenseStreetAddress, licenseZip, licenseState }
+ ) {
return globalMethods.callHttpClient({
method: endpoints.LookupVinByAddress.method,
endpoint: endpoints.LookupVinByAddress.url,
@@ -459,7 +493,7 @@ export const actions = {
licenseLastName: licenseLastName,
licenseStreetAddress: licenseStreetAddress,
licenseZip: licenseZip,
- licenseState: licenseState
+ licenseState: licenseState,
},
});
},
@@ -493,10 +527,22 @@ export const actions = {
})
.then((response) => {
context.commit(storeMutations.UPDATE_CAR_ID, response.data.carId);
- context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, response.data.category);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, response.data.imageUrl);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, response.data.imageVifNumber);
- context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, response.data.imageVifColor);
+ context.commit(
+ storeMutations.UPDATE_VEHICLE_CATEGORY,
+ response.data.category
+ );
+ context.commit(
+ storeMutations.UPDATE_VEHICLE_IMAGE_URL,
+ response.data.imageUrl
+ );
+ context.commit(
+ storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER,
+ response.data.imageVifNumber
+ );
+ context.commit(
+ storeMutations.UPDATE_VEHICLE_IMAGE_COLOR,
+ response.data.imageVifColor
+ );
return response;
});
},
@@ -510,8 +556,8 @@ export const actions = {
validateZip(context, { zip }) {
return globalMethods.callHttpClient({
methods: endpoints.ValidateZip.method,
- endpoint: `${endpoints.ValidateZip.url}/${zip}`
- })
+ endpoint: `${endpoints.ValidateZip.url}/${zip}`,
+ });
},
// Dependency Actions
@@ -526,7 +572,7 @@ export const actions = {
},
resetRegistrationAndDependencies(context) {
context.commit(storeMutations.RESET_REGISTRATION_STATE);
- context.commit(storeMutations.RESET_GLASS_PARTS_STATE)
+ context.commit(storeMutations.RESET_GLASS_PARTS_STATE);
},
resetPartsAndDependencies(context) {
context.commit(storeMutations.RESET_GLASS_PARTS_STATE);
@@ -582,8 +628,8 @@ export const actions = {
assignmentId: experiment.assignmentId,
sessionKey: sessionKey,
pageName: pageName,
- }
- }
+ },
+ },
});
},
@@ -591,13 +637,28 @@ export const actions = {
updateStoreWithSaveSessionResponse(context, { referralNumber, referralDate, referralCorrelationId, eon, accountNumber, savedSessionId, crmCustomerId }) {
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
- context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
+ context.commit(
+ storeMutations.UPDATE_REFERRAL_CORRELATION_ID,
+ referralCorrelationId
+ );
context.commit(storeMutations.UPDATE_EON, eon);
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, accountNumber);
context.commit(storeMutations.UPDATE_SAVED_SESSION_ID, savedSessionId);
context.commit(storeMutations.UPDATE_CRM_CUSTOMER_ID, crmCustomerId);
},
- logPageView(context, { userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId, experimentsForUser }) {
+ logPageView(
+ context,
+ {
+ userId,
+ sessionKey,
+ pageName,
+ sessionId,
+ action,
+ event,
+ shouldUseSessionId,
+ experimentsForUser,
+ }
+ ) {
var payload = {
userId: userId,
sessionKey: sessionKey,
@@ -607,17 +668,31 @@ export const actions = {
action: action,
event: event,
shouldUseSessionId: shouldUseSessionId,
- experimentsForUser: experimentsForUser
+ experimentsForUser: experimentsForUser,
};
return globalMethods.callHttpClient({
method: endpoints.LogPageView.method,
endpoint: endpoints.LogPageView.url,
payload: payload,
- logApiCall: false
+ logApiCall: false,
});
},
- logCustomEvent(context, { userId, sessionKey, pageName, sessionId, category, action, label, value, shouldUseSessionId, experimentsForUser }) {
+ logCustomEvent(
+ context,
+ {
+ userId,
+ sessionKey,
+ pageName,
+ sessionId,
+ category,
+ action,
+ label,
+ value,
+ shouldUseSessionId,
+ experimentsForUser,
+ }
+ ) {
var payload = {
userId: userId,
sessionKey: sessionKey,
@@ -629,14 +704,14 @@ export const actions = {
label: label,
value: value,
shouldUseSessionId: shouldUseSessionId,
- experimentsForUser: experimentsForUser
+ experimentsForUser: experimentsForUser,
};
return globalMethods.callHttpClient({
method: endpoints.LogCustomEvent.method,
endpoint: endpoints.LogCustomEvent.url,
payload: payload,
- logApiCall: false
+ logApiCall: false,
});
},
initializeSession(context, { userId, sessionId, userAgent, referrer }) {
@@ -648,22 +723,28 @@ export const actions = {
userAgent: userAgent,
operatorId: "WEB",
userName: "SafeliteConceptFunnel",
- referrer: referrer
+ referrer: referrer,
};
return globalMethods.callHttpClient({
method: endpoints.InitializeSession.method,
endpoint: endpoints.InitializeSession.url,
payload: payload,
- logApiCall: false
+ logApiCall: false,
});
},
// Misc Actions
- setReferralInformation(context, { referralNumber, referralDate, referralCorrelationId, eon }) {
+ setReferralInformation(
+ context,
+ { referralNumber, referralDate, referralCorrelationId, eon }
+ ) {
context.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber);
context.commit(storeMutations.UPDATE_REFERRAL_DATE, referralDate);
- context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId);
+ context.commit(
+ storeMutations.UPDATE_REFERRAL_CORRELATION_ID,
+ referralCorrelationId
+ );
context.commit(storeMutations.UPDATE_EON, eon);
},
@@ -671,11 +752,14 @@ export const actions = {
return globalMethods.callHttpClient({
method: endpoints.GetExperimentsByUser.method,
endpoint: `${endpoints.GetExperimentsByUser.url}/${userId}`,
- payload: {}
+ payload: {},
});
},
- async runExperimentsForTrigger(context, { userId, triggerEvent, triggerValue }) {
+ async runExperimentsForTrigger(
+ context,
+ { userId, triggerEvent, triggerValue }
+ ) {
if (triggerEvent == experimentTriggers.SITE_ENTRY) {
context.commit(storeMutations.UPDATE_TRIGGERED_SITE_ENTRY, true);
}
@@ -685,7 +769,7 @@ export const actions = {
userId: userId,
triggerEvent: triggerEvent,
triggerValue: triggerValue,
- experimentOrder: context.getters.experimentOrder
+ experimentOrder: context.getters.experimentOrder,
};
const response = await globalMethods.callHttpClient({
@@ -694,7 +778,10 @@ export const actions = {
payload: payload,
});
- context.commit(storeMutations.UPDATE_EXPERIMENTS, response.data.experiments);
+ context.commit(
+ storeMutations.UPDATE_EXPERIMENTS,
+ response.data.experiments
+ );
},
getEvoxImage(context, { relativeUrl }) {
@@ -723,7 +810,7 @@ export const actions = {
carId: carId,
glass: glassArray ?? [],
zip: zipCode,
- vin: vin
+ vin: vin,
},
});
},
@@ -748,7 +835,7 @@ export const actions = {
glass: glassArray,
answerResults: resultsArray,
zip: zipCode,
- vin: vin
+ vin: vin,
},
});
},
@@ -757,24 +844,31 @@ export const actions = {
return globalMethods.callHttpClient({
method: endpoints.GetCapabilityQuestions.method,
endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`,
- })
+ });
},
getPartFromCapabilityQuestionAnswer(context, glassLocation) {
- const pageData = context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS);
+ const pageData = context.getters.pageData(
+ fmgPageValues.CAPABILITY_QUESTIONS
+ );
- const part = pageData.partsOrQuestions.find(x => x.glassLocation === glassLocation).parts[0];
- const capabilityQuestionAnswers = context.getters.damage.capabilityQuestionAnswers;
- const capabilityQuestionAnswersForPart = capabilityQuestionAnswers.find(x => x.glassLocation === glassLocation);
+ const part = pageData.partsOrQuestions.find(
+ (x) => x.glassLocation === glassLocation
+ ).parts[0];
+ const capabilityQuestionAnswers =
+ context.getters.damage.capabilityQuestionAnswers;
+ const capabilityQuestionAnswersForPart = capabilityQuestionAnswers.find(
+ (x) => x.glassLocation === glassLocation
+ );
return globalMethods.callHttpClient({
method: endpoints.GetPartFromCapabilityAnswer.method,
endpoint: endpoints.GetPartFromCapabilityAnswer.url,
payload: {
part,
- capabilityAnswerResults: capabilityQuestionAnswersForPart
- }
- })
+ capabilityAnswerResults: capabilityQuestionAnswersForPart,
+ },
+ });
},
// Session API Actions
@@ -809,21 +903,21 @@ export const actions = {
damage: {
numberOfChips: damage.numberOfChips,
glassToReplace: damage.glassToReplace,
- isRepair: damage.isRepair
+ isRepair: damage.isRepair,
},
customer: {
emailAddress: order.customer.emailAddress,
},
lineItems: {
- glassParts: lineItems.glassParts
+ glassParts: lineItems.glassParts,
},
serviceLocation: {
streetAddress: order.serviceLocation.address,
city: order.serviceLocation.city,
state: order.serviceLocation.state,
- zipCode: order.serviceLocation.zipCode
+ zipCode: order.serviceLocation.zipCode,
},
- referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
+ referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
referralDate: order.referralDate,
accountNumber: order.accountNumber?.toString(),
existingPromoCode: null,
@@ -858,8 +952,7 @@ export const actions = {
// Vehicle
saveVehicleYear(context, year) {
-
- //Reset dependent state when changing
+ //Reset dependent state when changing
if (context.state.order.vehicle.year !== year) {
context.commit(storeMutations.UPDATE_MAKE, null);
context.commit(storeMutations.UPDATE_MODEL, null);
@@ -880,7 +973,6 @@ export const actions = {
}
},
saveVehicleMake(context, make) {
-
//Reset dependent state when changing
if (context.state.order.vehicle.make !== make) {
context.commit(storeMutations.UPDATE_MODEL, null);
@@ -901,8 +993,7 @@ export const actions = {
}
},
saveVehicleModel(context, model) {
-
- //Reset dependent state when changing
+ //Reset dependent state when changing
if (context.state.order.vehicle.model !== model) {
context.commit(storeMutations.UPDATE_STYLE, null);
context.commit(storeMutations.UPDATE_CAR_ID, null);
@@ -921,7 +1012,7 @@ export const actions = {
}
},
saveVehicleStyle(context, style) {
- //Reset dependent state when changing
+ //Reset dependent state when changing
if (context.state.order.vehicle.style !== style) {
context.commit(storeMutations.UPDATE_CAR_ID, null);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
@@ -938,20 +1029,32 @@ export const actions = {
context.commit(storeMutations.UPDATE_STYLE, style);
}
},
- saveVehicleDamage(context, { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }) {
-
+ saveVehicleDamage(
+ context,
+ { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }
+ ) {
const selectedGlassPassedInSorted = selectedGlassToReplace.slice().sort();
- const isGlassToReplaceTheSame = (context.state.order.damage.glassToReplace?.length === selectedGlassToReplace.length)
- && context.state.order.damage.glassToReplace
+ const isGlassToReplaceTheSame =
+ context.state.order.damage.glassToReplace?.length ===
+ selectedGlassToReplace.length &&
+ context.state.order.damage.glassToReplace
.slice()
.sort()
- .every((obj, index) => obj.glassLocation === selectedGlassPassedInSorted[index].glassLocation && obj.glassName === selectedGlassPassedInSorted[index].glassName);
- 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;
+ .every(
+ (obj, index) =>
+ obj.glassLocation ===
+ selectedGlassPassedInSorted[index].glassLocation &&
+ obj.glassName === selectedGlassPassedInSorted[index].glassName
+ );
+ const isWindshieldRepairTheSame =
+ isWindshieldRepair === context.state.order.damage.isRepair;
- const isDamageChanging = !isGlassToReplaceTheSame || !isWindshieldRepairTheSame || (isWindshieldRepair && !isChipCountTheSame);
+ const isChipCountTheSame = selectedWindshieldChipCount === context.state.order.damage.numberOfChips;
+
+ const isDamageChanging =
+ !isGlassToReplaceTheSame ||
+ !isWindshieldRepairTheSame ||
+ (isWindshieldRepair && !isChipCountTheSame);
if (isDamageChanging) {
//Reset dependent state when changing
@@ -959,14 +1062,23 @@ export const actions = {
// Save new values
context.commit(storeMutations.UPDATE_IS_REPAIR, isWindshieldRepair);
- context.commit(storeMutations.UPDATE_NUMBER_OF_CHIPS, isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null);
- context.commit(storeMutations.UPDATE_GLASS_TO_REPLACE, selectedGlassToReplace);
+ context.commit(
+ storeMutations.UPDATE_NUMBER_OF_CHIPS,
+ isWindshieldRepair ? parseInt(selectedWindshieldChipCount) : null
+ );
+ context.commit(
+ storeMutations.UPDATE_GLASS_TO_REPLACE,
+ selectedGlassToReplace
+ );
}
},
// Vin lookup
- saveVinLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
- //Reset dependent state when changing
+ saveVinLookup(
+ context,
+ { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
+ ) {
+ //Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
@@ -980,10 +1092,15 @@ export const actions = {
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
}
},
- saveRegistrationLicensePlateLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
- //Reset dependent state when changing
- if (registrationInfo?.licensePlate !== context.state.order.vehicle.registration?.licensePlate) {
-
+ saveRegistrationLicensePlateLookup(
+ context,
+ { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
+ ) {
+ //Reset dependent state when changing
+ if (
+ registrationInfo?.licensePlate !==
+ context.state.order.vehicle.registration?.licensePlate
+ ) {
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
if (!isSelectedGlassAvailableForVehicle) {
@@ -996,10 +1113,25 @@ export const actions = {
context.commit(storeMutations.UPDATE_REGISTRATION, registrationInfo);
}
},
- saveRegistrationAddressLookup(context, { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }) {
- //Reset dependent state when changing
- if (registrationInfo?.address !== context.state.order.vehicle.registration?.address || registrationInfo?.city !== context.state.order.vehicle.registration?.city || registrationInfo?.state !== context.state.order.vehicle.registration?.state || registrationInfo?.zipCode !== context.state.order.vehicle.registration?.zipCode || registrationInfo?.firstName !== context.state.order.vehicle.registration?.firstName || registrationInfo?.lastName !== context.state.order.vehicle.registration?.lastName) {
-
+ saveRegistrationAddressLookup(
+ context,
+ { isSelectedGlassAvailableForVehicle, vehicleInfo, registrationInfo }
+ ) {
+ //Reset dependent state when changing
+ if (
+ registrationInfo?.address !==
+ context.state.order.vehicle.registration?.address ||
+ registrationInfo?.city !==
+ context.state.order.vehicle.registration?.city ||
+ registrationInfo?.state !==
+ context.state.order.vehicle.registration?.state ||
+ registrationInfo?.zipCode !==
+ context.state.order.vehicle.registration?.zipCode ||
+ registrationInfo?.firstName !==
+ context.state.order.vehicle.registration?.firstName ||
+ registrationInfo?.lastName !==
+ context.state.order.vehicle.registration?.lastName
+ ) {
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
if (!isSelectedGlassAvailableForVehicle) {
@@ -1014,72 +1146,141 @@ export const actions = {
},
savePartQuestionAnswers(context, partQuestionAnswersArray) {
// if part question answers have changed, reset subsequent question answers
- const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.partQuestionAnswers, "result");
- const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(partQuestionAnswersArray, "result")
- const havePartQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedPartQuestionAnswersArray.length ||
- !sortedPreviousResultsArray?.every((x, i) => x.result === sortedPartQuestionAnswersArray[i].result);
+ const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
+ context.getters.damage.partQuestionAnswers,
+ "result"
+ );
+ const sortedPartQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(
+ partQuestionAnswersArray,
+ "result"
+ );
+ const havePartQuestionAnswersChanged =
+ sortedPreviousResultsArray?.length !==
+ sortedPartQuestionAnswersArray.length ||
+ !sortedPreviousResultsArray?.every(
+ (x, i) => x.result === sortedPartQuestionAnswersArray[i].result
+ );
if (havePartQuestionAnswersChanged) {
context.commit(storeMutations.UPDATE_GLASS_PARTS, null);
context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.VEHICLE_PARTS, data: null });
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.MOLDING_QUESTIONS, data: null });
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.VEHICLE_PARTS,
+ data: null,
+ });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.MOLDING_QUESTIONS,
+ data: null,
+ });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.CAPABILITY_QUESTIONS,
+ data: null,
+ });
}
//Save new values
- context.commit(storeMutations.UPDATE_PART_QUESTION_ANSWERS, partQuestionAnswersArray);
+ context.commit(
+ storeMutations.UPDATE_PART_QUESTION_ANSWERS,
+ partQuestionAnswersArray
+ );
},
resetMoldingAndCapabilityQuestionAnswersIfNeeded(context, matchedParts) {
- const partsOrQuestionsDataToCompareWith = context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS)?.partsOrQuestions ?? context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)?.partsOrQuestions ?? [];
+ const partsOrQuestionsDataToCompareWith =
+ context.getters.pageData(fmgPageValues.MOLDING_QUESTIONS)
+ ?.partsOrQuestions ??
+ context.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)
+ ?.partsOrQuestions ??
+ [];
function getAllPartNumbers(partsOrQuestions) {
return partsOrQuestions[0]?.parts
- ? [...partsOrQuestions].map(glass => glass.parts).flat().map(part => part.partNumber).filter(partNumber => !partNumber.toUpperCase().includes("FEE")).sort().join(",")
- : []
+ ? [...partsOrQuestions]
+ .map((glass) => glass.parts)
+ .flat()
+ .map((part) => part.partNumber)
+ .filter((partNumber) => !partNumber.toUpperCase().includes("FEE"))
+ .sort()
+ .join(",")
+ : [];
}
- const previouslySelectedPartNumbers = getAllPartNumbers(partsOrQuestionsDataToCompareWith);
+ const previouslySelectedPartNumbers = getAllPartNumbers(
+ partsOrQuestionsDataToCompareWith
+ );
const currentlySelectedPartNumbers = getAllPartNumbers(matchedParts);
- const haveSelectedVehiclePartsChanged = previouslySelectedPartNumbers !== currentlySelectedPartNumbers;
+ const haveSelectedVehiclePartsChanged =
+ previouslySelectedPartNumbers !== currentlySelectedPartNumbers;
if (haveSelectedVehiclePartsChanged) {
context.commit(storeMutations.UPDATE_GLASS_PARTS, null);
context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.MOLDING_QUESTIONS, data: null });
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.MOLDING_QUESTIONS,
+ data: null,
+ });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.CAPABILITY_QUESTIONS,
+ data: null,
+ });
}
},
saveMoldingQuestionAnswers(context, moldingQuestionAnswers) {
- const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.moldingQuestionAnswers, "partNum");
- const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(moldingQuestionAnswers, "partNum");
- const haveMoldingQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedMoldingQuestionAnswersArray.length ||
- !sortedPreviousResultsArray?.every((x, i) => x.partNum === sortedMoldingQuestionAnswersArray[i].partNum);
+ const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
+ context.getters.damage.moldingQuestionAnswers,
+ "partNum"
+ );
+ const sortedMoldingQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(
+ moldingQuestionAnswers,
+ "partNum"
+ );
+ const haveMoldingQuestionAnswersChanged =
+ sortedPreviousResultsArray?.length !==
+ sortedMoldingQuestionAnswersArray.length ||
+ !sortedPreviousResultsArray?.every(
+ (x, i) => x.partNum === sortedMoldingQuestionAnswersArray[i].partNum
+ );
if (haveMoldingQuestionAnswersChanged) {
context.commit(storeMutations.UPDATE_GLASS_PARTS, null);
context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, null);
- context.commit(storeMutations.UPDATE_PAGE_DATA, { page: fmgPageValues.CAPABILITY_QUESTIONS, data: null });
+ context.commit(storeMutations.UPDATE_PAGE_DATA, {
+ page: fmgPageValues.CAPABILITY_QUESTIONS,
+ data: null,
+ });
}
//Save new values
- context.commit(storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS, moldingQuestionAnswers);
+ context.commit(
+ storeMutations.UPDATE_MOLDING_QUESTION_ANSWERS,
+ moldingQuestionAnswers
+ );
},
saveCapabilityQuestionAnswers(context, capabilityQuestionAnswers) {
- const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(context.getters.damage.capabilityQuestionAnswers, "result");
- const sortedCapabilityQuestionAnswersArray = sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswers, "result");
- const haveCapabilityQuestionAnswersChanged = sortedPreviousResultsArray?.length !== sortedCapabilityQuestionAnswersArray.length ||
- !sortedPreviousResultsArray?.every((x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result);
+ const sortedPreviousResultsArray = sortArrayOfObjectsByPropertyValue(
+ context.getters.damage.capabilityQuestionAnswers,
+ "result"
+ );
+ const sortedCapabilityQuestionAnswersArray =
+ sortArrayOfObjectsByPropertyValue(capabilityQuestionAnswers, "result");
+ const haveCapabilityQuestionAnswersChanged =
+ sortedPreviousResultsArray?.length !==
+ sortedCapabilityQuestionAnswersArray.length ||
+ !sortedPreviousResultsArray?.every(
+ (x, i) => x.result === sortedCapabilityQuestionAnswersArray[i].result
+ );
if (haveCapabilityQuestionAnswersChanged) {
context.commit(storeMutations.UPDATE_GLASS_PARTS, null);
}
//Save new values
- context.commit(storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS, capabilityQuestionAnswers);
+ context.commit(
+ storeMutations.UPDATE_CAPABILITY_QUESTION_ANSWERS,
+ capabilityQuestionAnswers
+ );
},
// Misc order actions
saveServiceLocation(context, serviceLocationInfo) {
@@ -1091,7 +1292,6 @@ export const actions = {
saveVin(context, { isSelectedGlassAvailableForVehicle, vehicleInfo }) {
//Reset dependent state when changing
if (vehicleInfo.vin !== context.state.order.vehicle.vin) {
-
if (!isSelectedGlassAvailableForVehicle) {
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
@@ -1106,12 +1306,11 @@ export const actions = {
},
clearVin(context) {
context.commit(storeMutations.UPDATE_VEHICLE_VIN, null);
- }
-}
+ },
+};
export default createStore({
plugins: [createPersistedState()],
-
// IMPORTANT: Be VERY careful when modifying these fields for at least a few reasons:
// * The CMS can reference the fields by name
// * Return users may have a previous "version" of the model, and we don't want
@@ -1134,7 +1333,8 @@ function getHasRecalibrationPart(state) {
} else { // Has 'requiresRecalibration' but no 'recalibrationType' at all
return true;
}
- } else { // Does not have 'requiresRecalibration'
+ } else {
+ // Does not have 'requiresRecalibration'
return false;
}
}
@@ -1143,11 +1343,8 @@ function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
if (!arrayOfObjects) return null;
return arrayOfObjects.sort((a, b) => {
- if (a[propertyName] < b[propertyName])
- return -1;
- else if (a[propertyName] > b[propertyName])
- return 1;
- else
- return 0;
- })
-}
\ No newline at end of file
+ if (a[propertyName] < b[propertyName]) return -1;
+ else if (a[propertyName] > b[propertyName]) return 1;
+ else return 0;
+ });
+}
diff --git a/src/styles/common-error-styles.scss b/src/styles/common-error-styles.scss
index 2018cdd64..ea39df63c 100644
--- a/src/styles/common-error-styles.scss
+++ b/src/styles/common-error-styles.scss
@@ -3,7 +3,6 @@ html {
&.list-button,
&.list-card,
&.list-card.list-button {
- // border: none;
color: $red;
input[type=checkbox]:focus + label,
input[type=radio]:focus + label {
@@ -39,6 +38,17 @@ html {
box-shadow: 0 0 1px $red;
}
}
+ &.grid-item {
+ input[type="radio"] {
+ + label {
+ border: 1px solid $red;
+ &:hover {
+ background-color: $blue-100;
+ box-shadow: 0px 0px 0px 4px $red-200;
+ }
+ }
+ }
+ }
&.ui-radio,
&.ui-checkbox {
input[type=checkbox],
diff --git a/src/ux-components/button-main/button-main.vue b/src/ux-components/button-main/button-main.vue
index 37f0f768b..4342c18b1 100644
--- a/src/ux-components/button-main/button-main.vue
+++ b/src/ux-components/button-main/button-main.vue
@@ -2,15 +2,17 @@
@@ -33,11 +35,16 @@ export default {
};
},
methods: {
- removeLoader(){
+ removeLoader() {
this.isLoaderDisplayed = false;
},
clicked() {
- this.pushEventToGA(this.$route.query[this.queryStrings.FMG_PAGE], this.GaActions.CLICKED, this.buttonText, true);
+ this.pushEventToGA(
+ this.$route.query[this.queryStrings.FMG_PAGE],
+ this.GaActions.CLICKED,
+ this.buttonText,
+ true
+ );
if (!this.isDisabled) {
this.isLoaderDisplayed = true;
this.$emit("click-event");
@@ -98,7 +105,8 @@ export default {
background: $blue-700;
box-shadow: 0 0 0 3px, 0 0 0 5.5px $blue-700;
}
- &.delay {// fixes flicker while transitioning between states
+ &.delay {
+ // fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;
}
}
@@ -137,7 +145,8 @@ export default {
color: $white;
@include blue-gradient;
}
- &.delay {// fixes flicker while transitioning between states
+ &.delay {
+ // fixes flicker while transitioning between states
transition: background 0s 0s ease-in-out;
}
}
diff --git a/src/ux-components/list-button-horizontal/list-button-horizontal.spec.js b/src/ux-components/list-button-horizontal/list-button-horizontal.spec.js
index ef7236a56..6817ec8c5 100644
--- a/src/ux-components/list-button-horizontal/list-button-horizontal.spec.js
+++ b/src/ux-components/list-button-horizontal/list-button-horizontal.spec.js
@@ -1,272 +1,202 @@
-import { shallowMount } from "@vue/test-utils";
+import { shallowMount, mount } from "@vue/test-utils";
import listButtonHorizontal from "./list-button-horizontal";
import { nextTick } from "vue";
import { GaActions } from "@/constants/analytics";
+import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
-// TODO KO
-describe.skip("list-button-horizontal.vue", () => {
- it("Should return input type checkbox if isMultiSelect is true", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isMultiSelect: true,
- },
+describe("list-button-horizontal.vue", () => {
+ // TODO KO Have this moved out to somewhere shared
+ describe("Shared baseInputButton checks", () => {
+ it("Should return input type checkbox if isMultiSelect is true", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ },
+ },
+ });
+
+ // Assert
+ const input = wrapper.find("input");
+ expect(input.attributes().type).toEqual("checkbox");
});
- // Assert
- const input = wrapper.find("input");
+ it("Should return input type radio if isMultiSelect is false or not specified", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ },
+ },
+ });
- expect(input.attributes().type).toEqual("checkbox");
- });
-
- it("Should return input type radio if isMultiSelect is false or not specified", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isMultiSelect: false,
- },
+ // Assert
+ const input = wrapper.find("input");
+ expect(input.attributes().type).toEqual("radio");
});
- // Assert
- const input = wrapper.find("input");
+ // TODO KO
+ it.skip("Should emit button value on click", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ value: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: false,
+ modelValue: ["List Card Checkbox"],
+ buttonID: "list-card-id",
+ },
+ },
+ });
- expect(input.attributes().type).toEqual("radio");
+ // Act
+ wrapper.vm.handleAnswerChange("test");
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.emitted()["change"][0]).toEqual(["test"]);
+ });
});
- it("Should return primary label text (buttonID)", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- buttonID: "List Card Checkbox",
- },
+ describe("styling/UI", () => {
+ it("Should return screen reader text", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ screenReaderOnlyText: "Screen Reader Only Text",
+ },
+ },
+ });
+
+ // Assert
+ const paragraph = wrapper.find("span.sr-only");
+
+ expect(paragraph.text()).toEqual("Screen Reader Only Text");
});
- // Assert
- const label = wrapper.find("label");
+ it("Should return text alignment class", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ textPosition: "text-center",
+ },
+ },
+ });
- expect(label.attributes().for).toEqual("List Card Checkbox");
- });
+ // Assert
+ const paragraph = wrapper.find("span.m-0");
- it("Should return screen reader text", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- screenReaderOnlyText: "Screen Reader Only Text",
- },
+ expect(paragraph.attributes("class")).toContain("text-center");
});
- // Assert
- const paragraph = wrapper.find("span.sr-only");
+ it("Should return aria-required state", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isRequired: true,
+ },
+ },
+ });
- expect(paragraph.text()).toEqual("Screen Reader Only Text");
- });
+ // Assert
+ const input = wrapper.find("input");
- it("Should return text alignment class", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- textPosition: "text-center",
- },
+ expect(input.attributes()["aria-required"]).toEqual("true");
});
- // Assert
- const paragraph = wrapper.find("span.m-0");
+ it("is cash or insurance button => has 'radio-fancy' class", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isCashOrInsurance: true,
+ },
+ },
+ });
- expect(paragraph.attributes("class")).toContain("text-center");
- });
+ // Assert
+ const label = wrapper.find("label");
- it("Should return aria-required state", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isRequired: true,
- },
+ expect(label.classes()).toContain("radio-fancy");
});
- // Assert
- const input = wrapper.find("input");
+ test("has buttonLabel => displays buttonLabel", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ },
+ },
+ });
- expect(input.attributes()["aria-required"]).toEqual("true");
- });
-
- it("Should return loader enabled true", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- selectingInitiatesLoad: true,
- },
+ // Assert
+ const content = wrapper.find(".list-button-horizontal-content");
+ expect(content.isVisible()).toBe(true);
+ expect(content.text()).toContain("Surprise!");
});
- // Assert
+ test("has buttonLabelSubCopy => displays buttonLabelSubCopy", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ buttonLabelSubCopy: "Super duper surprise :)",
+ },
+ },
+ });
- const label = wrapper.find("label");
-
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
-
- await nextTick();
-
- const loader = wrapper.find("loader-stub");
-
- expect(loader.exists()).toBe(true);
- });
-
- it("Should return loader color", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- loaderColor: "blue",
- selectingInitiatesLoad: true,
- },
+ // Assert
+ const content = wrapper.find(".list-button-horizontal-content");
+ expect(content.isVisible()).toBe(true);
+ expect(content.text()).toContain("Super duper surprise :)");
});
- // Assert
+ test("has screenReaderOnlyText => displays screenReaderOnlyText", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ buttonLabelSubCopy: "Super duper surprise :)",
+ screenReaderOnlyText: "Tests are fun!"
+ },
+ },
+ });
- const label = wrapper.find("label");
-
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
-
- await nextTick();
-
- const loader = wrapper.find("loader-stub");
-
- expect(loader.attributes("class")).toContain("blue");
- });
-
- it("Should return loader position", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- loaderPosition: "right",
- selectingInitiatesLoad: true,
- },
+ // Assert
+ const content = wrapper.find(".list-button-horizontal-content");
+ const screenReaderOnlyText = wrapper.find(".sr-only");
+ expect(content.isVisible()).toBe(true);
+ expect(screenReaderOnlyText.exists()).toBe(true);
+ expect(screenReaderOnlyText.text()).toContain("Tests are fun!");
});
-
- // Assert
-
- const label = wrapper.find("label");
-
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
-
- await nextTick();
-
- const loader = wrapper.find("loader-stub");
-
- expect(loader.attributes("class")).toContain("right");
});
-
- it("Should emit button value on click", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isRadioHorizontal: true,
- buttonLabel: "Windshield",
- value: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg",
- isRequired: true,
- isWide: false,
- modelValue: ["List Card Checkbox"],
- },
- });
- wrapper.vm.handleCheckChange();
- // Assert
- expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: Boolean, buttonId: undefined, checkValue: false}]);
- });
-
- it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isRadioHorizontal: true,
- buttonLabel: "Windshield",
- buttonID: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg",
- isRequired: true,
- isWide: false,
- modelValue: ["List Card Checkbox"],
- isMultiSelect: false,
- value: "Car-Front",
- selectedValues: ["Car-Front"]
- },
- });
- // Assert
- expect(wrapper.vm.checkValue).toEqual(true);
- });
-
- it("Should run handleCheckChange if selectingInitiatesLoad is false and handleInputChange is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- selectingInitiatesLoad: false,
- },
- });
-
- // Assert
- wrapper.vm.handleInputChange();
-
- await nextTick();
-
- expect(wrapper.vm.handleCheckChange).toBeCalled;
- });
-
- it("Should do nothing if isMultiSelect is true and handleKeyupArrow is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- isMultiSelect: true,
- },
- });
-
- // Assert
- wrapper.vm.handleKeyupArrow();
-
- await nextTick();
-
- expect(wrapper.vm.handleKeyupArrow).toHaveReturned;
- });
-
- it("Should run handleCheckChange if selectingInitiatesLoad is false and handleKeyupArrow is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButtonHorizontal, {
- propsData: {
- selectingInitiatesLoad: false,
- isMultiSelect: false,
- },
- });
-
- // Assert
- wrapper.vm.handleKeyupArrow();
-
- await nextTick();
-
- expect(wrapper.vm.handleCheckChange).toBeCalled;
- });
-
});
+
+function setupMocks({ mockData }) {
+ const wrapper = mount(listButtonHorizontal, {
+ ...mockData,
+ propsData: {
+ ...mockData.propsData,
+ groupName: "my-group",
+ modelValue: mockData.propsData?.isMultiSelect ? ["5"] : "5",
+ value: mockData.propsData?.isMultiSelect ? ["4"] : "4"
+ },
+ mixins: [inputButtonWrapperMixin],
+ });
+
+ return { wrapper };
+}
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 9f6084047..70e018bfa 100644
--- a/src/ux-components/list-button-horizontal/list-button-horizontal.vue
+++ b/src/ux-components/list-button-horizontal/list-button-horizontal.vue
@@ -5,7 +5,7 @@
'list-group list-button-horizontal d-flex flex-column w-100',
{ 'radio-fancy': additionalData?.isCashOrInsurance },
]"
- @buttonClicked="handleAnswerChange">
+ v-model="selectedValue">
diff --git a/src/ux-components/list-button/list-button.spec.js b/src/ux-components/list-button/list-button.spec.js
index 95b3cb523..21c1a37b4 100644
--- a/src/ux-components/list-button/list-button.spec.js
+++ b/src/ux-components/list-button/list-button.spec.js
@@ -1,264 +1,262 @@
-import { shallowMount } from "@vue/test-utils";
+import { shallowMount, mount } from "@vue/test-utils";
import listButton from "./list-button";
import { nextTick } from "vue";
import { GaActions } from "@/constants/analytics";
+import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
// TODO KO
describe.skip("list-button.vue", () => {
- it("Should return input type checkbox if isMultiSelect is true", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isMultiSelect: true,
- },
+ describe("loader", () => {
+ it("selectingInitiatesLoad is true and answer is changed => show the loader", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ global: {
+ mocks: {
+ $route: { query: { fmgPage: "page-name" } },
+ GaActions: GaActions,
+ pushEventToGA: jest.fn(),
+ },
+ },
+ propsData: {
+ selectingInitiatesLoad: true,
+ },
+ },
+ });
+
+ // Act
+ wrapper.vm.handleAnswerChange("something");
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ const loader = wrapper.findComponent({ name: "loader" });
+ expect(loader.exists()).toBe(true);
});
- // Assert
- const input = wrapper.find("input");
+ it("Should return loader color", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ global: {
+ mocks: {
+ $route: { query: { fmgPage: "page-name" } },
+ GaActions: GaActions,
+ pushEventToGA: jest.fn(),
+ },
+ },
+ propsData: {
+ loaderColor: "blue",
+ selectingInitiatesLoad: true,
+ },
+ },
+ });
- expect(input.attributes().type).toEqual("checkbox");
- });
+ // Act
+ wrapper.vm.handleAnswerChange("something");
+ await nextTick();
- it("Should return input type radio if isMultiSelect is false or not specified", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isMultiSelect: false,
- },
+ // Assert
+ const loader = wrapper.findComponent({ name: "loader" });
+ expect(loader.attributes("class")).toContain("blue");
});
- // Assert
- const input = wrapper.find("input");
+ it("Should return loader position", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ global: {
+ mocks: {
+ $route: { query: { fmgPage: "page-name" } },
+ GaActions: GaActions,
+ pushEventToGA: jest.fn(),
+ },
+ },
+ propsData: {
+ loaderPosition: "right",
+ selectingInitiatesLoad: true,
+ },
+ },
+ });
- expect(input.attributes().type).toEqual("radio");
+ // Act
+ wrapper.vm.handleAnswerChange("test");
+ await nextTick();
+
+ // Assert
+ const loader = wrapper.findComponent({ name: "loader" });
+ expect(loader.attributes("class")).toContain("right");
+ });
});
- it("Should return primary label text (buttonID)", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- buttonID: "List Card Checkbox",
- },
+ describe("baseInputButton checks", () => {
+ it("Should return input type checkbox if isMultiSelect is true", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: true,
+ },
+ },
+ });
+
+ // Assert
+ const input = wrapper.find("input");
+
+ expect(input.attributes().type).toEqual("checkbox");
});
- // Assert
- const label = wrapper.find("label");
+ it("Should return input type radio if isMultiSelect is false or not specified", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isMultiSelect: false,
+ },
+ },
+ });
- expect(label.attributes().for).toEqual("List Card Checkbox");
- });
-
- it("Should return screen reader text", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- screenReaderOnlyText: "Screen Reader Only Text",
- },
+ // Assert
+ const input = wrapper.find("input");
+ expect(input.attributes().type).toEqual("radio");
});
- // Assert
- const paragraph = wrapper.find("span.sr-only");
+ it("Should emit button value on click", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isRadioHorizontal: true,
+ buttonLabel: "Windshield",
+ value: "List Card Checkbox",
+ groupID: "radio-demo-1",
+ groupName: "radio 1",
+ buttonImage: "windshield-damage.svg",
+ isRequired: true,
+ isWide: false,
+ modelValue: ["List Card Checkbox"],
+ buttonID: "list-card-id",
+ },
+ },
+ });
- expect(paragraph.text()).toEqual("Screen Reader Only Text");
+ // Act
+ wrapper.vm.handleAnswerChange("test");
+ await wrapper.vm.$nextTick();
+
+ // Assert
+ expect(wrapper.emitted()["change"][0]).toEqual(["test"]);
+ });
});
- it("Should return text alignment class", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- textPosition: "text-center",
- },
+ describe("styling/UI", () => {
+ test("has buttonLabel => displays buttonLabel", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ },
+ },
+ });
+
+ // Assert
+ const content = wrapper.find(".list-button-content");
+ expect(content.isVisible()).toBe(true);
+ expect(content.text()).toContain("Surprise!");
});
- // Assert
- const paragraph = wrapper.find("span.m-0");
+ test("has buttonLabelSubCopy => displays buttonLabelSubCopy", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ buttonLabelSubCopy: "Super duper surprise :)",
+ },
+ },
+ });
- expect(paragraph.attributes("class")).toContain("text-center");
- });
-
- it("Should return aria-required state", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isRequired: true,
- },
+ // Assert
+ const content = wrapper.find(".list-button-content");
+ expect(content.isVisible()).toBe(true);
+ expect(content.text()).toContain("Super duper surprise :)");
});
- // Assert
- const input = wrapper.find("input");
+ test("has screenReaderOnlyText => displays screenReaderOnlyText", () => {
+ // Arrange/Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ buttonLabel: "Surprise!",
+ buttonLabelSubCopy: "Super duper surprise :)",
+ screenReaderOnlyText: "Tests are fun!",
+ },
+ },
+ });
- expect(input.attributes()["aria-required"]).toEqual("true");
- });
-
- it("Should return loader enabled true", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- selectingInitiatesLoad: true,
- },
+ // Assert
+ const content = wrapper.find(".list-button-content");
+ const screenReaderOnlyText = wrapper.find(".sr-only");
+ expect(content.isVisible()).toBe(true);
+ expect(screenReaderOnlyText.exists()).toBe(true);
+ expect(screenReaderOnlyText.text()).toContain("Tests are fun!");
});
- // Assert
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
+ it("Should return screen reader text", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ screenReaderOnlyText: "Screen Reader Only Text",
+ },
+ },
+ });
- await nextTick();
+ // Assert
+ const paragraph = wrapper.find("span.sr-only");
- const loader = wrapper.find("loader-stub");
-
- expect(loader.exists()).toBe(true);
- });
-
- it("Should return loader color", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- loaderColor: "blue",
- selectingInitiatesLoad: true,
- },
+ expect(paragraph.text()).toEqual("Screen Reader Only Text");
});
- // Assert
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
- await nextTick();
+ it("Should return text alignment class", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ textPosition: "text-center",
+ },
+ },
+ });
- const loader = wrapper.find("loader-stub");
+ // Assert
+ const paragraph = wrapper.find("span.m-0");
- expect(loader.attributes("class")).toContain("blue");
- });
-
- it("Should return loader position", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- global: {
- mocks: {
- '$route': { query: { fmgPage: 'page-name' } },
- GaActions: GaActions,
- pushEventToGA: jest.fn(),
- }
- },
- propsData: {
- loaderPosition: "right",
- selectingInitiatesLoad: true,
- },
+ expect(paragraph.attributes("class")).toContain("text-center");
});
- // Assert
- wrapper.vm.handleCheckChange = jest.fn();
- wrapper.vm.triggerButton();
+ it("Should return aria-required state", async () => {
+ // Act
+ const { wrapper } = setupMocks({
+ mockData: {
+ propsData: {
+ isRequired: true,
+ },
+ },
+ });
- await nextTick();
+ // Assert
+ const input = wrapper.find("input");
- const loader = wrapper.find("loader-stub");
-
- expect(loader.attributes("class")).toContain("right");
- });
-
- it("Should emit button value on click", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isRadioHorizontal: true,
- buttonLabel: "Windshield",
- value: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg",
- isRequired: true,
- isWide: false,
- modelValue: ["List Card Checkbox"],
- buttonID: 'list-card-id'
- },
+ expect(input.attributes()["aria-required"]).toEqual("true");
});
-
- wrapper.vm.handleCheckChange();
-
- // Assert
- expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: false, buttonId: 'list-card-id'}]);
-
});
-
- it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isRadioHorizontal: true,
- buttonLabel: "Windshield",
- buttonID: "List Card Checkbox",
- groupID: "radio-demo-1",
- groupName: "radio 1",
- buttonImage: "windshield-damage.svg",
- isRequired: true,
- isWide: false,
- modelValue: ["List Card Checkbox"],
- selectedValues: "Car-Front"
- },
- });
- // Assert
- expect(wrapper.componentVM.checkValue).toEqual(false);
- });
-
- it("Should run handleCheckChange if selectingInitiatesLoad is false and handleInputChange is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- selectingInitiatesLoad: false,
- },
- });
-
- // Assert
- wrapper.vm.handleInputChange();
-
- await nextTick();
-
- expect(wrapper.vm.handleCheckChange).toBeCalled;
- });
-
- it("Should do nothing if isMultiSelect is true and handleKeyupArrow is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- isMultiSelect: true,
- },
- });
-
- // Assert
- wrapper.vm.handleKeyupArrow();
-
- await nextTick();
-
- expect(wrapper.vm.handleKeyupArrow).toHaveReturned;
- });
-
- it("Should run handleCheckChange if selectingInitiatesLoad is false and handleKeyupArrow is triggered", async () => {
- // Act
- const wrapper = shallowMount(listButton, {
- propsData: {
- selectingInitiatesLoad: false,
- isMultiSelect: false,
- },
- });
-
- // Assert
- wrapper.vm.handleKeyupArrow();
-
- await nextTick();
-
- expect(wrapper.vm.handleCheckChange).toBeCalled;
- });
-
});
+
+function setupMocks({ mockData }) {
+ const wrapper = mount(listButton, {
+ ...mockData,
+ mixins: [inputButtonWrapperMixin],
+ });
+
+ return { wrapper };
+}
diff --git a/src/ux-components/list-button/list-button.vue b/src/ux-components/list-button/list-button.vue
index f1f07932d..54ef98b35 100644
--- a/src/ux-components/list-button/list-button.vue
+++ b/src/ux-components/list-button/list-button.vue
@@ -2,7 +2,7 @@
+ v-model="selectedValue">
diff --git a/src/ux-components/list-card/list-card.spec.js b/src/ux-components/list-card/list-card.spec.js
index 19c5d01c2..41d3555e2 100644
--- a/src/ux-components/list-card/list-card.spec.js
+++ b/src/ux-components/list-card/list-card.spec.js
@@ -14,6 +14,7 @@ describe("list-card.vue", () => {
groupID: "checkbox-demo-1",
groupName: "Checkbox 1",
buttonImage: "windshield-damage.svg",
+ value: "test value",
},
});
@@ -32,6 +33,7 @@ describe("list-card.vue", () => {
groupID: "radio-demo-1",
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
+ value: "test value",
},
});
@@ -51,6 +53,7 @@ describe("list-card.vue", () => {
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
buttonLabelSubCopy: "Test",
+ value: "test value",
},
});
@@ -70,6 +73,7 @@ describe("list-card.vue", () => {
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
buttonLabelSubCopy: "Test",
+ value: "test value",
},
});
@@ -89,6 +93,7 @@ describe("list-card.vue", () => {
groupName: "radio 1",
buttonImage: "windshield-damage.svg",
isRequired: true,
+ value: "test value",
},
});
@@ -110,6 +115,7 @@ describe("list-card.vue", () => {
isRequired: true,
isWide: true,
buttonLabelSubCopy: "",
+ value: "test value",
},
});
@@ -134,6 +140,7 @@ describe("list-card.vue", () => {
isRequired: true,
isWide: true,
buttonLabelSubCopy: "Button Subcopy",
+ value: "test value",
},
});
@@ -159,6 +166,7 @@ describe("list-card.vue", () => {
buttonImage: "windshield-damage.svg",
isRequired: true,
isWide: false,
+ value: "test value",
},
});
diff --git a/src/ux-components/list-card/list-card.vue b/src/ux-components/list-card/list-card.vue
index deac697df..7e27a6476 100644
--- a/src/ux-components/list-card/list-card.vue
+++ b/src/ux-components/list-card/list-card.vue
@@ -5,7 +5,7 @@
'list-card w-100 rounded-3 d-flex align-items-center h-100',
{ horizontal: isWide },
]"
- @buttonClicked="handleAnswerChange">
+ v-model="selectedValue">
diff --git a/src/ux-components/radio/radio.spec.js b/src/ux-components/radio/radio.spec.js
index 520fd9daf..83cc22b5a 100644
--- a/src/ux-components/radio/radio.spec.js
+++ b/src/ux-components/radio/radio.spec.js
@@ -6,12 +6,16 @@ import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
describe("radio.vue", () => {
it("Should have correct group name", async () => {
// Arrange
- let { wrapper } = setupMocks({});
+ let { wrapper } = setupMocks({
+ mountOptionsMockData: {
+ propsData: {
+ groupName: "radio-button-test",
+ value: "test value",
+ },
+ },
+ });
// Act
- await wrapper.setProps({
- groupName: "radio-button-test",
- });
const input = wrapper.find("input");
// Assert
@@ -20,12 +24,16 @@ describe("radio.vue", () => {
it("Should have correct label text", async () => {
// Act
- let { wrapper } = setupMocks({});
+ let { wrapper } = setupMocks({
+ mountOptionsMockData: {
+ propsData: {
+ buttonLabel: "label text",
+ value: "test value",
+ },
+ },
+ });
// Arrange
- await wrapper.setProps({
- buttonLabel: "label text",
- });
const paragraph = wrapper.find("p");
// Assert
@@ -39,6 +47,7 @@ describe("radio.vue", () => {
// Arrange
await wrapper.setProps({
screenReaderOnlyText: "screenreader text",
+ value: "test value",
});
const paragraph = wrapper.find(".sr-only");
@@ -48,13 +57,10 @@ describe("radio.vue", () => {
});
function setupMocks({ mountOptionsMockData = {} }) {
- const wrapper = mount(
- radio,
- getMountOptions({
- ...mountOptionsMockData,
- mixins: [inputButtonWrapperMixin],
- })
- );
+ const wrapper = mount(radio, {
+ ...mountOptionsMockData,
+ mixins: [inputButtonWrapperMixin],
+ });
return { wrapper };
}
diff --git a/src/ux-components/radio/radio.vue b/src/ux-components/radio/radio.vue
index 40b1e3b31..0d120de39 100644
--- a/src/ux-components/radio/radio.vue
+++ b/src/ux-components/radio/radio.vue
@@ -3,7 +3,7 @@
v-bind="$props"
buttonWrapperClasses="ui-radio form-check"
inputClasses="form-check-input"
- @buttonClicked="handleAnswerChange">
+ v-model="selectedValue">