Merge branch 'develop' into feature/CSR-659

This commit is contained in:
Leah Schumann 2022-06-15 13:39:15 -04:00
commit 9e63cd0f9c
24 changed files with 410 additions and 466 deletions

View file

@ -23,6 +23,7 @@ module.exports = {
"!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue", "!src/layouts/address-vehicles/address-vehicles-question/address-vehicles-question.vue",
"!src/ux-components/alert/alert.vue", "!src/ux-components/alert/alert.vue",
"!src/helpers/validation-rules.js", "!src/helpers/validation-rules.js",
"!src/common-components/question-chain/question-chain",
// END // END
], // ! means exclude from coverage. ], // ! means exclude from coverage.
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"], testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],

View file

@ -112,7 +112,8 @@ describe("buttonQuestion.vue", () => {
const wrapper = shallowMount(buttonQuestion, setupMocks({})); const wrapper = shallowMount(buttonQuestion, setupMocks({}));
await wrapper.setProps({ await wrapper.setProps({
answers: ["2022", "2021", "2020"], answers: ["2022", "2021", "2020"],
isMultiSelect: false isMultiSelect: false,
modelValue: []
}); });
const val = { checkValue: true, value: "2021", } const val = { checkValue: true, value: "2021", }
wrapper.vm.handleCheckedChanged(val); wrapper.vm.handleCheckedChanged(val);

View file

@ -36,6 +36,7 @@
data-test="button" data-test="button"
:validationRules="validationRules" :validationRules="validationRules"
:class="[suppressError ? 'alertError' : '']" :class="[suppressError ? 'alertError' : '']"
:clearOnUnmount="clearOnUnmount"
/> />
</div> </div>
</fieldset> </fieldset>
@ -84,6 +85,10 @@ export default {
validationRules: String, validationRules: String,
suppressError: Boolean, suppressError: Boolean,
useTextForValue: Boolean, useTextForValue: Boolean,
clearOnUnmount: {
type: Boolean,
default: true
}
}, },
computed: { computed: {
getFieldSetClasses() { getFieldSetClasses() {
@ -133,17 +138,14 @@ export default {
return answer.Name ? answer.Name : answer; return answer.Name ? answer.Name : answer;
}, },
handleCheckedChanged(val) { handleCheckedChanged(val) {
if(this.selectingInitiatesLoad) {
if(this.isMultiSelect && this.selectedValues) { this.selectedValues = [val.value];
// Add or remove item to array of data to emit } else {
const newSelectedValues = this.selectedValues;
if(Array.isArray(this.selectedValues)) { if(Array.isArray(this.selectedValues)) {
const newSelectedValues = this.selectedValues;
val.checkValue ? newSelectedValues.push(val.value) : newSelectedValues.splice(newSelectedValues.indexOf(val.value), 1); val.checkValue ? newSelectedValues.push(val.value) : newSelectedValues.splice(newSelectedValues.indexOf(val.value), 1);
this.selectedValues = newSelectedValues; this.selectedValues = newSelectedValues;
} }
} else {
this.selectedValues = [val.value];
} }
}, },
}, },
@ -179,4 +181,22 @@ export default {
text-align: center; text-align: center;
} }
} }
.vehicle-parts {
.question-text {
span {
font-size: .875rem;
text-align: left;
margin: 0 0 .5rem 0;
}
}
.question-text {
margin: 0;
}
fieldset {
.ui-radio {
margin: 0;
}
}
}
</style> </style>

View file

@ -0,0 +1,119 @@
<template>
<div v-for="(q, i) in questions" :key="i">
<transition appear name="fade" mode="out-in">
<buttonQuestion
v-if="q.questionSequence === currentQuestion"
class="radioQuestion"
:questionText="q.questionText"
:answers="q.answers"
:groupName="`${questionData.glassName}-${questionData.glassLocation}-${i}`"
textPosition="text-start"
v-model="selectedValue"
isRequired=true
:validationRules="validationRules"
:clearOnUnmount=false
/>
</transition>
</div>
</template>
<script>
import buttonQuestion from "@/common-components/button-question/button-question";
export default {
name: "questionChain",
data() {
return {
models: Array,
currentQuestion: 1,
answeredQuestions: [],
};
},
props: {
questionData: Array,
validationRules: String,
modelValue: String,
},
computed: {
questions() {
const questions = this.questionData.partQuestions.map((q, i) => {
return {
questionText: q.questionText,
questionSequence: q.questionSequence,
answers: q.answers.map((a) => {
return {
Text: a.answerText,
// Name will either be nextQuestionSequence or answerResult
Name: a.nextQuestionSequence ? a.nextQuestionSequence : "answer-" + a.answerResult,
nextQuestionSequence: a.nextQuestionSequence,
answerResult: a.answerResult,
}
})
}
});
// add an empty item to be array[0] since we start with 1
questions.unshift({});
return questions;
},
selectedValue: {
get: function() {
return this.modelValue;
},
set: function(returnedAnswer) {
const isNewModelValueComplete = this.getNewModelValue(returnedAnswer);
if (isNewModelValueComplete) {
this.$emit("update:modelValue", isNewModelValueComplete);
}
}
}
},
methods: {
getNewModelValue(returnedAnswer) {
if (!returnedAnswer || !Array.isArray(returnedAnswer)) { return false }
const lastAnswer = returnedAnswer[returnedAnswer.length - 1];
const currentQuestion = this.questions[this.currentQuestion];
if (lastAnswer.indexOf("answer-") === 0) {
// if it is an answerResult
const finalAnswer = lastAnswer.slice(7);
const currentQuestionSelectedAnswer = currentQuestion.answers.find(
({ answerResult }) => answerResult === finalAnswer
);
// add current item to list of answered questions
this.answeredQuestions.push(
{
questionText: currentQuestion.questionText,
selectedAnswerText: currentQuestionSelectedAnswer.Text,
}
);
return {
answerResult: finalAnswer,
answeredQuestions: this.answeredQuestions,
};
} else {
const currentQuestionSelectedAnswer = currentQuestion.answers.find(
({ nextQuestionSequence }) => nextQuestionSequence === parseInt(lastAnswer)
);
// add current item to list of answered questions
this.answeredQuestions.push(
{
questionText: currentQuestion.questionText,
selectedAnswerText: currentQuestionSelectedAnswer.Text,
}
);
this.currentQuestion = parseInt(lastAnswer); // update count to display next question
return false;
}
}
},
components: {
buttonQuestion,
},
};
</script>

View file

@ -1,35 +0,0 @@
import { shallowMount } from "@vue/test-utils";
import textInput from "./text-input";
describe("text-input.vue", () => {
it("Should render a text input", async () => {
// Act
const wrapper = shallowMount(textInput, {
propsData: {
name: "test",
label: "unit test label",
},
});
// Assert
const input = wrapper.find("input");
expect(input.exists()).toBe(true);
});
it("Should return aria-required state", async () => {
// Act
const wrapper = shallowMount(textInput, {
propsData: {
name: "test",
label: "unit test label",
isRequired: true,
},
});
// Assert
const input = wrapper.find("input");
expect(input.attributes()["aria-required"]).toEqual("true");
});
});

View file

@ -1,71 +0,0 @@
<!-- Simple implementation of an input field -->
<template>
<div class="d-flex w-50 mb-2" :class="{ 'has-error': !!errorMessage }">
<input
type="text"
:name="name"
:value="inputValue"
:id="name"
:aria-required="isRequired"
@input="handleChange"
@blur="handleBlur"
:data-focus-target="name"
/>
<label
:for="name"
:aria-labelledby="name"
class="d-flex justify-content-center py-3 px-4"
>
<span class="m-0">{{ label }}</span>
</label>
</div>
<div v-show="errorMessage" class="row px-3 form-test-error">
{{ errorMessage }}
</div>
</template>
<script>
import { useField } from "vee-validate";
export default {
name: "textInput",
props: {
type: {
type: String,
default: "text",
},
value: {
type: String,
default: "",
},
name: {
type: String,
required: true,
},
label: {
type: String,
required: true,
},
isRequired: Boolean,
},
setup(props) {
const {
value: inputValue,
errorMessage,
handleBlur,
handleChange,
meta,
} = useField(props.name, undefined, {
initialValue: props.value,
});
return {
handleChange,
handleBlur,
errorMessage,
inputValue,
meta,
};
},
};
</script>

View file

@ -167,7 +167,7 @@ describe("textboxQuestion.vue", () => {
}); });
it("Should call this.handleChange with new value when this.semiAggressiveValidation = true, the value is changed, and the new value is valid", async () => { it("Should call this.handleChange with new value when the value is changed and the new value is valid", async () => {
// Arrange // Arrange
const wrapper = shallowMount(textboxQuestion, { const wrapper = shallowMount(textboxQuestion, {
global: { global: {
@ -178,7 +178,6 @@ describe("textboxQuestion.vue", () => {
propsData: { propsData: {
options: {}, options: {},
modelValue: "foo", modelValue: "foo",
semiAggressiveValidation: true,
}, },
mixins: [mockMixin] mixins: [mockMixin]
}); });

View file

@ -55,7 +55,6 @@ export default {
default: "", default: "",
}, },
validationRules: String, validationRules: String,
semiAggressiveValidation: Boolean,
cmsWidgetName: String, cmsWidgetName: String,
maxLength: String, maxLength: String,
}, },
@ -130,12 +129,10 @@ export default {
}, },
watch: { watch: {
async value(newValue) { async value(newValue) {
if (this.semiAggressiveValidation) { const result = await validate(newValue, this.validationRules); // do a test validation check, without triggering full validation
const result = await validate(newValue, this.validationRules); // do a test validation check, without triggering full validation if (result.valid) {
if (result.valid) { this.handleChange(newValue); // trigger full validation on this field only
this.handleChange(newValue); // trigger full validation on this field only }
}
}
}, },
}, },
}; };

View file

@ -9,7 +9,7 @@ const tintMap = {
{ name: "brown tint, blue shade", src: "Glass-BlueShade-BrownTint.svg" }, { name: "brown tint, blue shade", src: "Glass-BlueShade-BrownTint.svg" },
{ name: "gray tint, blue shade", src: "Glass-BlueShade-GrayTint.svg" }, { name: "gray tint, blue shade", src: "Glass-BlueShade-GrayTint.svg" },
{ name: "green tint, blue shade", src: "Glass-BlueShade-GreenTint.svg" }, { name: "green tint, blue shade", src: "Glass-BlueShade-GreenTint.svg" },
{ name: "blue shade", src: "Glass-BlueShade-NoTint.svg" }, { name: "clear, blue shade", src: "Glass-BlueShade-NoTint.svg" },
// Brown Shade // Brown Shade
{ name: "brown tint, brown shade", src: "Glass-BrownShade-BrownTint.svg" }, { name: "brown tint, brown shade", src: "Glass-BrownShade-BrownTint.svg" },
@ -26,13 +26,13 @@ const tintMap = {
{ name: "green tint, green shade", src: "Glass-GreenShade-GreenTint.svg" }, { name: "green tint, green shade", src: "Glass-GreenShade-GreenTint.svg" },
// Tints Only // Tints Only
{ name: "blue tint", src: "Glass-NoShade-BlueTint.svg" }, { name: "blue tint privacy", src: "Glass-NoShade-BlueTint.svg" },
{ name: "brown tint", src: "Glass-NoShade-BrownTint.svg" }, { name: "bronze tint", src: "Glass-NoShade-BrownTint.svg" },
{ name: "dark brown tint", src: "Glass-NoShade-DarkBrownTint.svg" }, { name: "dark brown tint", src: "Glass-NoShade-DarkBrownTint.svg" },
{ name: "dark gray tint", src: "Glass-NoShade-DarkGrayTint.svg" }, { name: "privacy, black frame", src: "Glass-NoShade-Privacy.svg" },
{ name: "gray tint", src: "Glass-NoShade-GrayTint.svg" }, { name: "gray tint", src: "Glass-NoShade-GrayTint.svg" },
{ name: "green tint", src: "Glass-NoShade-GreenTint.svg" }, { name: "green tint", src: "Glass-NoShade-GreenTint.svg" },
{ name: "gray tint privacy", src: "Glass-NoShade-Privacy.svg" }, { name: "gray tint privacy", src: "Glass-NoShade-GrayTint.svg" },
// No shade or tint // No shade or tint
{ name: "clear", src: "Glass-NoShade-NoTint.svg" } { name: "clear", src: "Glass-NoShade-NoTint.svg" }
@ -41,13 +41,13 @@ const tintMap = {
windshield: [ windshield: [
// Blue Shade // Blue Shade
{ name: "blue tint, blue shade", src: "Windshield-BlueShade-BlueTint.svg" }, { name: "blue tint, blue shade", src: "Windshield-BlueShade-BlueTint.svg" },
{ name: "brown tint, blue shade", src: "Windshield-BlueShade-BrownTint.svg" }, { name: "bronze tint, blue shade", src: "Windshield-BlueShade-BrownTint.svg" },
{ name: "gray tint, blue shade", src: "Windshield-BlueShade-GrayTint.svg" }, { name: "gray tint, blue shade", src: "Windshield-BlueShade-GrayTint.svg" },
{ name: "green tint, blue shade", src: "Windshield-BlueShade-GreenTint.svg" }, { name: "green tint, blue shade", src: "Windshield-BlueShade-GreenTint.svg" },
{ name: "blue shade", src: "Windshield-BlueShade-NoTint.svg" }, { name: "clear, blue shade", src: "Windshield-BlueShade-NoTint.svg" },
// Brown Shade // Brown Shade
{ name: "brown tint, brown shade", src: "Windshield-BrownShade-BrownTint.svg" }, { name: "bronze tint, bronze shade", src: "Windshield-BrownShade-BrownTint.svg" },
// Gray Shade // Gray Shade
{ name: "blue tint, gray shade", src: "Windshield-GrayShade-BlueTint.svg" }, { name: "blue tint, gray shade", src: "Windshield-GrayShade-BlueTint.svg" },
@ -62,12 +62,12 @@ const tintMap = {
// Tints Only // Tints Only
{ name: "blue tint", src: "Windshield-NoShade-BlueTint.svg" }, { name: "blue tint", src: "Windshield-NoShade-BlueTint.svg" },
{ name: "brown tint", src: "Windshield-NoShade-BrownTint.svg" }, { name: "bronze tint", src: "Windshield-NoShade-BrownTint.svg" },
{ name: "dark brown tint", src: "Windshield-NoShade-DarkBrownTint.svg" }, { name: "dark brown tint", src: "Windshield-NoShade-DarkBrownTint.svg" },
{ name: "dark gray tint", src: "Windshield-NoShade-DarkGrayTint.svg" }, { name: "privacy, black frame", src: "Windshield-NoShade-Privacy.svg" },
{ name: "gray tint", src: "Windshield-NoShade-GrayTint.svg" }, { name: "gray tint", src: "Windshield-NoShade-GrayTint.svg" },
{ name: "green tint", src: "Windshield-NoShade-GreenTint.svg" }, { name: "green tint", src: "Windshield-NoShade-GreenTint.svg" },
{ name: "gray tint privacy", src: "Windshield-NoShade-Privacy.svg" }, { name: "gray tint privacy", src: "Windshield-NoShade-GrayTint.svg" },
// No shade or tint // No shade or tint
{ name: "clear", src: "Windshield-NoShade-NoTint.svg" }, { name: "clear", src: "Windshield-NoShade-NoTint.svg" },

View file

@ -2,7 +2,6 @@
import addressLookup from "@/layouts/address-lookup/address-lookup.vue"; import addressLookup from "@/layouts/address-lookup/address-lookup.vue";
// Supporting Files // Supporting Files
import baseMixin from "@/mixins/base-mixin";
import { shallowMount } from "@vue/test-utils"; import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { getMountOptions } from "@/helpers/unit-test-helper.js";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
@ -32,7 +31,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: false isZipServiceable: false
}); });
@ -60,7 +59,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true
}); });
@ -88,41 +87,27 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: false,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: true
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: false,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -146,31 +131,16 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [] // Return no vehicles
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: true
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [] // Return no vehicles
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -192,7 +162,7 @@ describe("address-lookup.vue", () => {
test("if the back button is clicked, navigate back", async () => { test("if the back button is clicked, navigate back", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true
}); });
@ -213,41 +183,27 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: true
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -272,42 +228,27 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: true
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -333,42 +274,27 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID_A"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID_A");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: true
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
const carsFound = [{ const carsFound = [{
vin: "TEST_VIN", vin: "TEST_VIN",
vehicle: { vehicle: {
@ -406,42 +332,27 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: false,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.VALIDATE_ZIP) {
data = {
isServiceable: false
}
}
else if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID"
}
},
{
vin: "TEST_VIN2",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -467,31 +378,21 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true,
lookupVinbyAddressResponse: {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID2"
}
}]
}
}); });
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {};
if (actionName == storeActions.LOOKUP_VIN_BY_ADDRESS) {
data = {
isStatePermissible: true,
vinVehicles: [{
vin: "TEST_VIN",
vehicle: {
carId: "CARID2"
}
}]
}
}
return Promise.resolve({ data });
})
await wrapper.setData({ await wrapper.setData({
customerQuestions: { customerQuestions: {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
@ -590,7 +491,7 @@ describe("address-lookup.vue", () => {
// Arrange // Arrange
const commitSpy = jest.spyOn(store, "commit"); const commitSpy = jest.spyOn(store, "commit");
const dispatchSpy = jest.spyOn(store, "dispatch"); const dispatchSpy = jest.spyOn(store, "dispatch");
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true
}); });
@ -615,7 +516,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: true isZipServiceable: true
}); });
@ -645,7 +546,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: false isZipServiceable: false
}); });
@ -677,7 +578,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: false isZipServiceable: false
} }
); );
@ -709,7 +610,7 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, { const { wrapper } = setupMocks({
isZipServiceable: false isZipServiceable: false
} }
); );
@ -726,7 +627,7 @@ describe("address-lookup.vue", () => {
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
// Assert // Assert
expect(baseMixin.methods.dispatchStoreAction).not.toHaveBeenCalledWith(storeActions.UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION); expect(wrapper.vm.dispatchStoreAction).not.toHaveBeenCalledWith(storeActions.UPDATE_SERVICE_LOCATION_WITH_VEHICLE_REGISTRATION);
}); });
test("if registration address, service zip are provided, and user clicks continue => both zips are saved and are different", async () => { test("if registration address, service zip are provided, and user clicks continue => both zips are saved and are different", async () => {
@ -738,12 +639,13 @@ describe("address-lookup.vue", () => {
zipCode: "43215" zipCode: "43215"
} }
const { wrapper } = setupMocks(addressLookup, {}); const { wrapper } = setupMocks({});
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
store.commit(storeMutations.UPDATE_CAR_ID, "CARID"); store.commit(storeMutations.UPDATE_CAR_ID, "CARID");
baseMixin.methods.dispatchStoreAction = jest.fn(); wrapper.vm.dispatchStoreAction = jest.fn();
baseMixin.methods.dispatchStoreAction.mockImplementation((actionName, value) => { wrapper.vm.dispatchStoreAction.mockImplementation((actionName, value) => {
let data = {}; let data = {};
if (actionName == storeActions.VALIDATE_ZIP) { if (actionName == storeActions.VALIDATE_ZIP) {
if (value == "43215") { if (value == "43215") {
@ -777,15 +679,16 @@ describe("address-lookup.vue", () => {
addressQuestions: mockRegistrationAddress addressQuestions: mockRegistrationAddress
} }
}) })
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
await wrapper.setData({ await wrapper.setData({
serviceZipCode: "12345" serviceZipCode: "12345"
}) })
// Act // // Act
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
// Assert // // Assert
expect(store.getters.order.serviceLocation.zipCode).not.toEqual(store.getters.vehicle.registration.zipCode); expect(store.getters.order.serviceLocation.zipCode).not.toEqual(store.getters.vehicle.registration.zipCode);
expect(store.getters.vehicle.registration.zipCode).toEqual("43215"); expect(store.getters.vehicle.registration.zipCode).toEqual("43215");
expect(store.getters.order.serviceLocation.zipCode).toEqual("12345"); expect(store.getters.order.serviceLocation.zipCode).toEqual("12345");
@ -794,10 +697,9 @@ describe("address-lookup.vue", () => {
}); });
}); });
function setupMocks(mountOptions, { isZipServiceable = true, lookupVinbyAddressResponse, partsOrQuestions = [] }) { function setupMocks({ isZipServiceable = true, lookupVinbyAddressResponse, partsOrQuestions = [] }) {
store.commit(storeMutations.RESET_STATE); store.commit(storeMutations.RESET_STATE);
const wrapper = shallowMount(addressLookup, getMountOptions({ const wrapper = shallowMount(addressLookup, getMountOptions({
...mountOptions,
actionList: [ actionList: [
{ {
actionName: storeActions.VALIDATE_ZIP, actionName: storeActions.VALIDATE_ZIP,
@ -831,7 +733,7 @@ function setupMocks(mountOptions, { isZipServiceable = true, lookupVinbyAddressR
})); }));
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent; wrapper.vm.setCmsContent = jest.fn();
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
wrapper.vm.$refs.loadingModal.showModal = jest.fn(); wrapper.vm.$refs.loadingModal.showModal = jest.fn();

View file

@ -82,8 +82,6 @@ import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store"; import store from "@/store";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations"; import { storeMutations } from "@/constants/store-mutations";
import baseMixin from "@/mixins/base-mixin";
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper"; import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
import vinPagesMixin from "@/mixins/vin-pages-mixin"; import vinPagesMixin from "@/mixins/vin-pages-mixin";
@ -318,12 +316,12 @@ export default {
}, },
validateZip(zip) { validateZip(zip) {
return baseMixin.methods.dispatchStoreAction( return this.dispatchStoreAction(
storeActions.VALIDATE_ZIP, storeActions.VALIDATE_ZIP,
{ zip }); { zip });
}, },
lookupVin(lastName, streetAddress, zip, state) { lookupVin(lastName, streetAddress, zip, state) {
return baseMixin.methods.dispatchStoreAction( return this.dispatchStoreAction(
storeActions.LOOKUP_VIN_BY_ADDRESS, storeActions.LOOKUP_VIN_BY_ADDRESS,
{ {
licenseLastName: lastName, licenseLastName: lastName,

View file

@ -25,7 +25,6 @@
inputId="cbf28188fdf2436688fd735915f7ee56" inputId="cbf28188fdf2436688fd735915f7ee56"
disableAutoFill disableAutoFill
validationRules="city-required" validationRules="city-required"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>
@ -52,7 +51,6 @@
mask="#####" mask="#####"
disableAutoFill disableAutoFill
validationRules="zip-code-required|zip-code-format" validationRules="zip-code-required|zip-code-format"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>

View file

@ -33,7 +33,6 @@
inputId="00450a91b8964a768ce3992e6feb890f" inputId="00450a91b8964a768ce3992e6feb890f"
disableAutoFill disableAutoFill
validationRules="email-address-required|email-address-format" validationRules="email-address-required|email-address-format"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>

View file

@ -5,6 +5,8 @@ import addressVehicles from "@/layouts/address-vehicles/address-vehicles";
import { shallowMount } from "@vue/test-utils"; import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { getMountOptions } from "@/helpers/unit-test-helper.js";
import store from "@/store"; import store from "@/store";
import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations";
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
// Mock our module for promises. // Mock our module for promises.
@ -19,7 +21,9 @@ describe("addressVehicles.vue", () => {
test("Should return true for valid page requisites if carId / zipCode / emailAddress / pageData exists", async () => { test("Should return true for valid page requisites if carId / zipCode / emailAddress / pageData exists", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.$router.navigate = jest.fn(); store.commit(storeMutations.UPDATE_CAR_ID, "NOT NULL");
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, "12345");
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, "test@test.com");
// Act // Act
const result = wrapper.vm.arePagePrerequisitesValid(); const result = wrapper.vm.arePagePrerequisitesValid();
@ -33,10 +37,9 @@ describe("addressVehicles.vue", () => {
test("Should return false for valid page requisites if carId is missing", async () => { test("Should return false for valid page requisites if carId is missing", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.$router.navigate = jest.fn();
// Act // Act
wrapper.vm.$store.getters.order.vehicle.carId = null; store.commit(storeMutations.UPDATE_CAR_ID, null);
const result = wrapper.vm.arePagePrerequisitesValid(); const result = wrapper.vm.arePagePrerequisitesValid();
//Assert //Assert
@ -53,7 +56,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$router.navigate = jest.fn(); wrapper.vm.$router.navigate = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
}); });
wrapper.vm.backButtonAction(); wrapper.vm.backButtonAction();
@ -83,7 +86,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.navigateForward = jest.fn().mockImplementation(()=> {}); wrapper.vm.navigateForward = jest.fn().mockImplementation(()=> {});
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
}); });
@ -113,7 +116,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {}); wrapper.vm.updateCustomerInfo = jest.fn().mockImplementation(()=> {});
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
}); });
await wrapper.vm.forwardButtonAction(); await wrapper.vm.forwardButtonAction();
@ -140,7 +143,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$router.navigateAfterSave = jest.fn(); wrapper.vm.$router.navigateAfterSave = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
isSelectedGlassAvailableForVehicle: false, isSelectedGlassAvailableForVehicle: false,
isCarIdDifferent: true, isCarIdDifferent: true,
@ -148,7 +151,7 @@ describe("addressVehicles.vue", () => {
await wrapper.vm.updateCustomerInfo(wrapper.vm.selectedVehicle.vin, wrapper.vm.selectedVehicle.vehicle); await wrapper.vm.updateCustomerInfo(wrapper.vm.selectedVehicle.vin, wrapper.vm.selectedVehicle.vehicle);
//Assert //Assert
expect(store.dispatch).toBeCalledWith("resetDamageAndDependencies"); expect(wrapper.vm.dispatchStoreAction).toBeCalledWith("resetDamageAndDependencies");
wrapper.unmount(); wrapper.unmount();
}); });
@ -162,7 +165,7 @@ describe("addressVehicles.vue", () => {
await wrapper.vm.lookupVin('1234567890'); await wrapper.vm.lookupVin('1234567890');
//Assert //Assert
expect(store.dispatch).toBeCalledWith("lookupVehicleByVin", {"vin": "1234567890"}); expect(wrapper.vm.dispatchStoreAction).toBeCalledWith("lookupVehicleByVin", {"vin": "1234567890"});
wrapper.unmount(); wrapper.unmount();
}); });
@ -170,10 +173,9 @@ describe("addressVehicles.vue", () => {
test("If selectedVehicleVin changes, then should update isCarIdDifferent", async () => { test("If selectedVehicleVin changes, then should update isCarIdDifferent", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
isCarIdDifferent: false, isCarIdDifferent: false,
}); });
@ -191,7 +193,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
isCarIdDifferent: false, isCarIdDifferent: false,
}); });
@ -210,7 +212,7 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$router.navigateAfterSave = jest.fn(); wrapper.vm.$router.navigateAfterSave = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
selectedVehicleVin: ['5NMS3CADXLH233004'], selectedVehicleVin: ['5NMS3CADXLH233004'],
isSelectedGlassAvailableForVehicle: false, isSelectedGlassAvailableForVehicle: false,
isCarIdDifferent: true, isCarIdDifferent: true,
@ -229,10 +231,9 @@ describe("addressVehicles.vue", () => {
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.loadingModal.showModal = jest.fn(); wrapper.vm.$refs.loadingModal.showModal = jest.fn();
navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn(); navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn();
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
// Act // Act
wrapper.setData({ await wrapper.setData({
isCarIdDifferent: false, isCarIdDifferent: false,
}); });
await wrapper.vm.navigateForward(); await wrapper.vm.navigateForward();
@ -246,53 +247,35 @@ describe("addressVehicles.vue", () => {
function setupMocks({}) { function setupMocks({}) {
//Mock store //Mock store
store.dispatch = jest.fn(() => {}); store.commit(storeMutations.RESET_STATE);
store.getters = { store.commit(storeMutations.UPDATE_PAGE_DATA, {
pageData: jest.fn((pageName) => { page: "address-vehicles",
return [ data: [{
{
vehicle: {
"carId": "CR00069309",
"category": "SUV",
"year": 2020,
"make": "Hyundai",
"model": "Santa Fe",
"style": "4 door utility",
"imageUrl": "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg",
"imageVifNumber": "13769",
"imageVifColor": "white"
},
vin: "5NMS3CADXLH233004"
},
];
}),
order: {
vehicle: { vehicle: {
carId: "123", "carId": "CR00069309",
"category": "SUV",
"year": 2020,
"make": "Hyundai",
"model": "Santa Fe",
"style": "4 door utility",
"imageUrl": "https://dbhdyzvm8lm25.cloudfront.net/color_0320_032/MY2020/13769/13769_cc0320_032_WW8.jpg",
"imageVifNumber": "13769",
"imageVifColor": "white"
}, },
serviceLocation: { vin: "5NMS3CADXLH233004"
zipCode: "12345" }],
}, })
customer: {
emailAddress: "qw@er.ty"
}
},
damage: {
glassToReplace: "Windshield"
},
vehicle: {
carId: "456",
}
};
const mountOptions = getMountOptions({ const mountOptions = getMountOptions({
store: {
dispatch: store.dispatch,
getters: store.getters,
},
router: { router: {
navigate: jest.fn(), navigate: jest.fn(),
}, },
actionList: [
{
actionName: storeActions.LOOKUP_VEHICLE_BY_VIN,
data: {}
}
]
}); });
//Mock props //Mock props
@ -319,5 +302,8 @@ function setupMocks({}) {
const wrapper = shallowMount(addressVehicles, mountOptions); const wrapper = shallowMount(addressVehicles, mountOptions);
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.navigateForwardWithSingleCarMatch = jest.fn();
return { wrapper }; return { wrapper };
} }

View file

@ -59,14 +59,12 @@ import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store"; import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations"; import { storeMutations } from "@/constants/store-mutations";
import { fmgPageValues } from "@/router/router-constants/fmgPage-values"; import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { errorMessages } from "@/constants/error-messages"; import { errorMessages } from "@/constants/error-messages";
import { required } from "@/helpers/validation-rules"; import { required } from "@/helpers/validation-rules";
import { Form, defineRule } from "vee-validate"; import { Form, defineRule } from "vee-validate";
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { isGlassAvailableForCarId } from "@/helpers/damage-helper"; import { isGlassAvailableForCarId } from "@/helpers/damage-helper";
import { doesCopyContainRouterLink, import { doesCopyContainRouterLink,
splitCopyOnCMSPlaceHolder, splitCopyOnCMSPlaceHolder,
@ -195,7 +193,7 @@ export default {
} }
}, },
lookupVin(vin) { lookupVin(vin) {
return baseMixin.methods.dispatchStoreAction( return this.dispatchStoreAction(
storeActions.LOOKUP_VEHICLE_BY_VIN, storeActions.LOOKUP_VEHICLE_BY_VIN,
{ vin } { vin }
); );
@ -205,7 +203,7 @@ export default {
}, },
updateCustomerInfo(vin, vehicle) { updateCustomerInfo(vin, vehicle) {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); this.dispatchStoreAction(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
} }
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin); store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
store.commit(storeMutations.UPDATE_YEAR, vehicle.year); store.commit(storeMutations.UPDATE_YEAR, vehicle.year);

View file

@ -4,7 +4,6 @@ import licensePlateLookup from "@/layouts/license-plate-lookup/license-plate-loo
// Supporting Files // Supporting Files
import { settleAllPromises } from "@/helpers/layout-helper.js"; import { settleAllPromises } from "@/helpers/layout-helper.js";
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper"; import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
import baseMixin from "@/mixins/base-mixin";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { shallowMount } from "@vue/test-utils"; import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { getMountOptions } from "@/helpers/unit-test-helper.js";
@ -230,13 +229,16 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.isCarIdDifferent = true; await wrapper.setData({
wrapper.vm.isSelectedGlassAvailableForVehicle = false; isCarIdDifferent: true,
isSelectedGlassAvailableForVehicle: false
})
wrapper.vm.$router.navigateAfterSave = jest.fn(); wrapper.vm.$router.navigateAfterSave = jest.fn();
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return ''; return '';
}); });
store.dispatch = jest.fn(); wrapper.vm.dispatchStoreAction = jest.fn();
await wrapper.vm.navigateForward(); await wrapper.vm.navigateForward();
@ -250,7 +252,9 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.isCarIdDifferent = false; await wrapper.setData({
isCarIdDifferent: false
})
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return ''; return '';
}); });
@ -302,7 +306,9 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.licensePlate = "NEWPLATE"; wrapper.setData({
licensePlate: "NEWPLATE"
})
wrapper.vm.getCmsContent = jest.fn(); wrapper.vm.getCmsContent = jest.fn();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -316,7 +322,9 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.registrationZip = "55555"; await wrapper.setData({
registrationZip: "55555"
})
wrapper.vm.getCmsContent = jest.fn(); wrapper.vm.getCmsContent = jest.fn();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -330,7 +338,9 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.serviceZip = "55555"; await wrapper.setData({
serviceZip: "55555"
})
wrapper.vm.getCmsContent = jest.fn(); wrapper.vm.getCmsContent = jest.fn();
await wrapper.vm.$nextTick(); await wrapper.vm.$nextTick();
@ -502,19 +512,20 @@ describe("license-plate-lookup.vue", () => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
//Act //Act
wrapper.vm.isCarIdDifferent = true; await wrapper.setData({
wrapper.vm.isSelectedGlassAvailableForVehicle = false; isCarIdDifferent: true,
isSelectedGlassAvailableForVehicle: false
})
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => { wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
return ''; return '';
}); });
store.commit = jest.fn(); store.commit = jest.fn();
store.dispatch = jest.fn();
const vehicleInfo = { year: "2020", make: "honda", model: "civic", style: "2 door", carId: "TestId", category: "testCat", imageUrl: "image.jpg", imageVifNumber: "123", imageColor: "blue" } const vehicleInfo = { year: "2020", make: "honda", model: "civic", style: "2 door", carId: "TestId", category: "testCat", imageUrl: "image.jpg", imageVifNumber: "123", imageColor: "blue" }
await wrapper.vm.updateCustomerInfo('vin', vehicleInfo, 'registrationState'); await wrapper.vm.updateCustomerInfo('vin', vehicleInfo, 'registrationState');
//Assert //Assert
expect(store.dispatch).toHaveBeenCalled(); expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
}) })
test("dispatchStoreAction called on validate zip", async () => { test("dispatchStoreAction called on validate zip", async () => {
@ -527,7 +538,7 @@ describe("license-plate-lookup.vue", () => {
//Assert //Assert
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled(); expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
}); });
test("dispatchStoreAction called on lookup vin", async () => { test("dispatchStoreAction called on lookup vin", async () => {
@ -540,7 +551,7 @@ describe("license-plate-lookup.vue", () => {
//Assert //Assert
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled(); expect(wrapper.vm.dispatchStoreAction).toHaveBeenCalled();
}); });
}) })
}); });
@ -552,7 +563,6 @@ function setupMocks({
}) { }) {
store.commit(storeMutations.RESET_STATE); store.commit(storeMutations.RESET_STATE);
//Mock api responses //Mock api responses
baseMixin.methods.dispatchStoreAction = jest.fn();
const apiResponses = { const apiResponses = {
cmsContent: { cmsContent: {
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText, FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
@ -592,7 +602,7 @@ function setupMocks({
const wrapper = shallowMount(licensePlateLookup, mountOptions); const wrapper = shallowMount(licensePlateLookup, mountOptions);
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent; wrapper.vm.setCmsContent = jest.fn();
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => ""); wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => "");
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn(); wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn(); wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();

View file

@ -35,7 +35,6 @@
v-model="email" v-model="email"
inputId="email" inputId="email"
validationRules="email-address-required|email-address-format" validationRules="email-address-required|email-address-format"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>
@ -54,7 +53,6 @@
v-model="serviceZip" v-model="serviceZip"
inputId="serviceZip" inputId="serviceZip"
validationRules="zip-required|zip-format" validationRules="zip-required|zip-format"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>
@ -94,7 +92,6 @@ import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
import store from "@/store"; import store from "@/store";
import baseMixin from "@/mixins/base-mixin.js";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { storeMutations } from "@/constants/store-mutations"; import { storeMutations } from "@/constants/store-mutations";
import { errorMessages } from "@/constants/error-messages"; import { errorMessages } from "@/constants/error-messages";
@ -303,16 +300,16 @@ export default {
} }
}, },
validateZip(zip) { validateZip(zip) {
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, { return this.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
zip, zip,
}); });
}, },
lookupVin(plate, state) { lookupVin(plate, state) {
return baseMixin.methods.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE,{ licensePlate: plate, licenseState: state }, false); return this.dispatchStoreAction(storeActions.LOOKUP_VIN_BY_PLATE,{ licensePlate: plate, licenseState: state }, false);
}, },
updateCustomerInfo(vin, vehicleInfo, registrationState, serviceState) { updateCustomerInfo(vin, vehicleInfo, registrationState, serviceState) {
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) { if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); this.dispatchStoreAction(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
} }
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin); store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year); store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);

View file

@ -1,7 +1,7 @@
<template> <template>
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<p class="mb-0">{{ colorQuestionText }}</p> <p class="mb-0 color-question-text">{{ colorQuestionText }}</p>
</div> </div>
</div> </div>
@ -168,23 +168,25 @@ export default {
// Check if only a single part is present for the tint and set the v-model if it is. // Check if only a single part is present for the tint and set the v-model if it is.
AutoSelectIfSinglePart() { AutoSelectIfSinglePart() {
// Check if the selected tint only has a single feature // Check if the selected tint only has a single feature
Object.keys(this.PartDataFromApi.partsOrQuestions ?? {}).forEach((key) => { Object.keys(this.PartDataFromApi.partsOrQuestions ?? {}).forEach(
const currentGlassSelection = (key) => {
this.PartDataFromApi.partsOrQuestions[key]; const currentGlassSelection =
this.PartDataFromApi.partsOrQuestions[key];
if ( if (
currentGlassSelection.glassName === this.glassName && currentGlassSelection.glassName === this.glassName &&
currentGlassSelection.glassLocation === this.glassLocation currentGlassSelection.glassLocation === this.glassLocation
) { ) {
if (currentGlassSelection.parts.length === 1) { if (currentGlassSelection.parts.length === 1) {
this.selectedPart = { this.selectedPart = {
[currentGlassSelection.glassLocation]: [ [currentGlassSelection.glassLocation]: [
currentGlassSelection.parts[0].partNumber, currentGlassSelection.parts[0].partNumber,
], ],
}; };
}
} }
} }
}); );
}, },
// Loads the preselected values from the store. // Loads the preselected values from the store.
@ -227,4 +229,9 @@ export default {
font-size: 0.875rem; font-size: 0.875rem;
} }
} }
.color-question-text {
color: $black;
font-weight: $font-weight-bold;
}
</style> </style>

View file

@ -1,5 +1,5 @@
<template> <template>
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles vehicle-parts">
<funnelHeader ref="funnelHeader" cmsWidgetName="FunnelHeaderWidget" /> <funnelHeader ref="funnelHeader" cmsWidgetName="FunnelHeaderWidget" />
<vehicleBanner ref="vehicleBanner" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" /> <vehicleBanner ref="vehicleBanner" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" /> <funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />

View file

@ -57,7 +57,6 @@
isRequired isRequired
disableAutoFill disableAutoFill
validationRules="email-address-required|email-address-format" validationRules="email-address-required|email-address-format"
semiAggressiveValidation
/> />
</div> </div>
</div> </div>

View file

@ -46,6 +46,7 @@ const routes = [
// If the saved session has timed out, clear the session, execute 404 logic. // If the saved session has timed out, clear the session, execute 404 logic.
if (getFunnelCookie() !== null && !isSavedSessionStillActive()) { if (getFunnelCookie() !== null && !isSavedSessionStillActive()) {
await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE);
await GoToFunnelStartOn404(next); await GoToFunnelStartOn404(next);
} }

View file

@ -78,6 +78,10 @@ export default {
validationRules: String, validationRules: String,
selectedValues: [Array, String], selectedValues: [Array, String],
hasError: Boolean, hasError: Boolean,
clearOnUnmount: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
@ -92,9 +96,11 @@ export default {
: this.selectedValues[0]; : this.selectedValues[0];
} }
}, },
unmounted() { // needed to clear this button's selectedValues if it is removed unmounted() { // needed to clear this button's selectedValues if it is removed to keep validation in sync
this.checkValue = false; if (this.clearOnUnmount) {
this.handleCheckChange(); this.checkValue = false;
this.handleCheckChange();
}
}, },
methods: { methods: {
displayLoader() { displayLoader() {

View file

@ -78,6 +78,10 @@ export default {
validationRules: String, validationRules: String,
selectedValues: [Array, String], selectedValues: [Array, String],
hasError: Boolean, hasError: Boolean,
clearOnUnmount: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
@ -92,9 +96,11 @@ export default {
: this.selectedValues[0]; : this.selectedValues[0];
} }
}, },
unmounted() { // needed to clear this button's selectedValues if it is removed unmounted() { // needed to clear this button's selectedValues if it is removed to keep validation in sync
this.checkValue = false; if (this.clearOnUnmount) {
this.handleCheckChange(); this.checkValue = false;
this.handleCheckChange();
}
}, },
methods: { methods: {
displayLoader() { displayLoader() {

View file

@ -86,6 +86,10 @@ export default {
selectedValues: [Array, String], selectedValues: [Array, String],
modelValue: Object, modelValue: Object,
hasError: Boolean, hasError: Boolean,
clearOnUnmount: {
type: Boolean,
default: true
}
}, },
data() { data() {
return { return {
@ -99,9 +103,11 @@ export default {
: this.selectedValues[0]; : this.selectedValues[0];
} }
}, },
unmounted() { // needed to clear this button's selectedValues if it is removed unmounted() { // needed to clear this button's selectedValues if it is removed to keep validation in sync
this.checkValue = false; if (this.clearOnUnmount) {
this.handleCheckChange(); this.checkValue = false;
this.handleCheckChange();
}
}, },
computed: { computed: {
getLabelClasses() { getLabelClasses() {