Merge remote-tracking branch 'origin/develop' into feature/CSR-774

This commit is contained in:
Scott Kiener 2022-11-30 10:32:36 -05:00
commit eb60bfb618
8 changed files with 198 additions and 139 deletions

View file

@ -1,10 +1,10 @@
// Components // Components
import questionsPageLayout from "@/common-components/questions-page-layout/questions-page-layout"; import questionsPageLayout from "@/common-components/layouts/questions-page-layout/questions-page-layout";
// Supporting Files // Supporting Files
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 baseMixin from "../../mixins/base-mixin"; import baseMixin from "../../../mixins/base-mixin";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
// Mock our module for promises. // Mock our module for promises.

View file

@ -74,16 +74,7 @@ async function getLatestPageForRedirection() {
fmgPageValues.CAPABILITY_QUESTIONS fmgPageValues.CAPABILITY_QUESTIONS
); );
const vinOptionalVehiclePromise = store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE); const isVinOptionalVehicle = await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE);
const promiseResultMap = [
{
resultKey: "vinOptionalOptions",
promise: vinOptionalVehiclePromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
var isVinOptionalVehicle = resultMap.vinOptionalOptions;
if (!vehicleMakeComponent.methods.arePagePrerequisitesValid()) { if (!vehicleMakeComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_YEAR; return fmgPageValues.VEHICLE_YEAR;

View file

@ -16,7 +16,7 @@
<script> <script>
// Components // Components
import questionsPageLayout from "@/common-components/questions-page-layout/questions-page-layout"; import questionsPageLayout from "@/common-components/layouts/questions-page-layout/questions-page-layout";
// Supporting Files // Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
@ -67,38 +67,13 @@ export default {
AlertFewMoreQuestionsCopy() { AlertFewMoreQuestionsCopy() {
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText"); return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
}, },
pageData() { partsOrQuestionsData() {
return this.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS); return this.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS)
.partsOrQuestions;
}, },
}, },
mounted() { mounted() {
// are there alreadyAnsweredQuestions? this.getInitialQuestionData();
const alreadyAnsweredQuestions = store.getters.damage.capabilityQuestionAnswers;
this.questionsData = this.pageData.partsOrQuestions
.filter((x) => x.capabilityQuestions)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.capabilityQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(glass, index, alreadyAnsweredQuestions);
// Set up watch for each set of glass questions
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
}, },
methods: { methods: {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
@ -106,12 +81,46 @@ export default {
fmgPageValues.CAPABILITY_QUESTIONS fmgPageValues.CAPABILITY_QUESTIONS
); );
return ( return (
capabilityQuestionsPageData && // has capabilityQuestions array and has glassName not null
capabilityQuestionsPageData.partsOrQuestions.some( capabilityQuestionsPageData?.partsOrQuestions?.some((part) => part?.glassName) &&
(el) => el.capabilityQuestions.length > 0 capabilityQuestionsPageData?.partsOrQuestions?.some(
(part) => part?.capabilityQuestions?.length > 0
) )
); );
}, },
getInitialQuestionData() {
// get any questions that were already answered
const alreadyAnsweredQuestions = store.getters.damage.capabilityQuestionAnswers;
this.questionsData = this.partsOrQuestionsData
.filter((x) => x.capabilityQuestions)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.capabilityQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(
glass,
index,
alreadyAnsweredQuestions
);
// Set up watch for each set of glass questions
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
},
async forwardButtonAction() { async forwardButtonAction() {
const questionAnswersArray = this.questionsData.map((glass) => { const questionAnswersArray = this.questionsData.map((glass) => {
// get answerResult2 of returned answer // get answerResult2 of returned answer
@ -142,6 +151,7 @@ export default {
}); });
// save to vuex store as order.damage.capabilityQuestionAnswers (array) // save to vuex store as order.damage.capabilityQuestionAnswers (array)
// used in GET_PART_FROM_CAPABILITY_QUESTION_ANSWER call following this one
await this.dispatchStoreAction( await this.dispatchStoreAction(
this.storeActions.SAVE_CAPABILITY_QUESTION_ANSWERS, this.storeActions.SAVE_CAPABILITY_QUESTION_ANSWERS,
questionAnswersArray, questionAnswersArray,
@ -149,7 +159,7 @@ export default {
); );
// get parts from the capabilityQuestionAnswers // get parts from the capabilityQuestionAnswers
const partsOrQuestions = this.pageData.partsOrQuestions; const partsOrQuestions = this.partsOrQuestionsData;
for (let answer of questionAnswersArray) { for (let answer of questionAnswersArray) {
const partFromCapabilityQuestionAnswer = ( const partFromCapabilityQuestionAnswer = (
await this.dispatchStoreAction( await this.dispatchStoreAction(

View file

@ -132,7 +132,6 @@ export default {
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
//Call APIs //Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const vinOptionalVehiclePromise = store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE);
//Settle promises and get results //Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
@ -140,15 +139,13 @@ export default {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{
resultKey: "vinOptionalOptions",
promise: vinOptionalVehiclePromise,
},
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const isVinOptionalVehicle = await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE);
next((vm) => { next((vm) => {
vm.isVinOptionalVehicle = resultMap.vinOptionalOptions; vm.isVinOptionalVehicle = isVinOptionalVehicle;
if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) { if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) {
const forwardTextOption = const forwardTextOption =
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|"); resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|");

View file

@ -16,7 +16,7 @@
<script> <script>
// Components // Components
import questionsPageLayout from "@/common-components/questions-page-layout/questions-page-layout"; import questionsPageLayout from "@/common-components/layouts/questions-page-layout/questions-page-layout";
// Supporting Files // Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
@ -67,51 +67,59 @@ export default {
AlertFewMoreQuestionsCopy() { AlertFewMoreQuestionsCopy() {
return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText"); return this.getCmsContent("AdditionalPartsQuestionsAlert", "BodyText");
}, },
pageData() { partsOrQuestionsData() {
return this.$store.getters.pageData(fmgPageValues.MOLDING_QUESTIONS); return this.$store.getters.pageData(fmgPageValues.MOLDING_QUESTIONS).partsOrQuestions;
}, },
}, },
mounted() { mounted() {
// are there alreadyAnsweredQuestions? this.getInitialQuestionData();
const alreadyAnsweredQuestions = store.getters.damage.moldingQuestionAnswers;
this.questionsData = this.pageData.partsOrQuestions
.filter((x) => x.parts[0].childPartQuestions.length)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.parts[0].childPartQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(glass, index, alreadyAnsweredQuestions);
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
}, },
methods: { methods: {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
const moldingQuestionsFromPageData = store.getters.pageData( const moldingQuestionsFromPageData = store.getters.pageData(
fmgPageValues.MOLDING_QUESTIONS fmgPageValues.MOLDING_QUESTIONS
); );
return ( return (
moldingQuestionsFromPageData && // has childPartQuestions array and has glassName not null
moldingQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName) &&
moldingQuestionsFromPageData.partsOrQuestions.some((glass) => moldingQuestionsFromPageData.partsOrQuestions.some((glass) =>
glass.parts?.some((part) => part?.childPartQuestions.length > 0) glass.parts?.some((part) => part?.childPartQuestions?.length > 0)
) )
); );
}, },
getInitialQuestionData() {
// get any questions that were already answered
const alreadyAnsweredQuestions = store.getters.damage.moldingQuestionAnswers;
this.questionsData = this.partsOrQuestionsData
.filter((x) => x.parts[0].childPartQuestions.length)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.parts[0].childPartQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(
glass,
index,
alreadyAnsweredQuestions
);
// Set up watch for each set of glass questions
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
},
async forwardButtonAction() { async forwardButtonAction() {
const questionAnswersArray = this.questionsData.map((glass) => { const questionAnswersArray = this.questionsData.map((glass) => {
return { return {
@ -136,7 +144,7 @@ export default {
); );
// get parts from the questionAnswers // get parts from the questionAnswers
let partsOrQuestions = this.pageData.partsOrQuestions; let partsOrQuestions = this.partsOrQuestionsData;
for (let answer of questionAnswersArray) { for (let answer of questionAnswersArray) {
partsOrQuestions.find((partOrQuestion) => { partsOrQuestions.find((partOrQuestion) => {
return ( return (

View file

@ -98,14 +98,6 @@ store.getters = {
}; };
store.commit = jest.fn(); store.commit = jest.fn();
afterEach(() => {
// reset store after each test
store.getters = {
pageData: baseStoreGettersPageData,
damage: baseStoreGettersDamage,
};
});
describe("partQuestions.vue...", () => { describe("partQuestions.vue...", () => {
describe("method arePagePrerequisitesValid...", () => { describe("method arePagePrerequisitesValid...", () => {
test("Should return true for valid page requisites if pageData exists", () => { test("Should return true for valid page requisites if pageData exists", () => {
@ -162,6 +154,10 @@ describe("partQuestions.vue...", () => {
describe("watch on selectedAnswers should be set up...", () => { describe("watch on selectedAnswers should be set up...", () => {
test("Should trigger handleAnswerUpdates if watched data changes", async () => { test("Should trigger handleAnswerUpdates if watched data changes", async () => {
// Arrange // Arrange
store.getters = {
pageData: baseStoreGettersPageData,
damage: baseStoreGettersDamage,
};
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
const spy = jest.spyOn(wrapper.vm, "handleAnswerUpdates"); const spy = jest.spyOn(wrapper.vm, "handleAnswerUpdates");
@ -172,14 +168,12 @@ describe("partQuestions.vue...", () => {
answerResult: "FW04848", answerResult: "FW04848",
answeredQuestions: [ answeredQuestions: [
{ {
questionText: questionText: "One?",
"Is your vehicle equipped with the Panoramic Sunroof which can be identified by having a glass panel over the rear seats?",
selectedAnswerText: "Yes", selectedAnswerText: "Yes",
questionNum: 1, questionNum: 1,
}, },
{ {
questionText: questionText: "Two?",
"Is your vehicle equipped with a heated windshield that melts snow and ice from underneath the windshield wiper blades?",
selectedAnswerText: "Yes", selectedAnswerText: "Yes",
questionNum: 2, questionNum: 2,
}, },
@ -191,6 +185,27 @@ describe("partQuestions.vue...", () => {
await nextTick(); await nextTick();
wrapper.setData({
selectedAnswers: {
"Windshield-Single": {
answerResult: "NEW-ANSWER",
answeredQuestions: [
{
questionText: "One?",
selectedAnswerText: "Yes",
questionNum: 1,
},
{
questionText: "Two?",
selectedAnswerText: "Yes",
questionNum: 2,
},
],
index: 0,
},
},
});
//Assert //Assert
expect(spy).toHaveBeenCalled(); expect(spy).toHaveBeenCalled();
@ -199,20 +214,23 @@ describe("partQuestions.vue...", () => {
}); });
describe("forwardButtonAction", () => { describe("forwardButtonAction", () => {
test("Should clear out answerData", () => { test("Should clear out answerData", async () => {
// Arrange // Arrange
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
wrapper.vm.questionsData = [ await wrapper.setData({
{ questionsData: [
glassLocation: "Windshield", {
glassName: "Single", glassLocation: "fbfWindshield",
answerData: { glassName: "fbfSingle",
answerResult: "FW04848", answerData: {
answeredQuestions: [], answerResult: "FW04848",
answeredQuestions: [],
},
}, },
}, ],
]; });
wrapper.vm.dispatchStoreAction = jest.fn(() => { wrapper.vm.dispatchStoreAction = jest.fn(() => {
return { return {
data: { data: {
@ -224,6 +242,8 @@ describe("partQuestions.vue...", () => {
// Act // Act
wrapper.vm.forwardButtonAction(); wrapper.vm.forwardButtonAction();
await nextTick();
//Assert //Assert
expect(wrapper.vm.questionsData[0].answerData).toEqual({}); expect(wrapper.vm.questionsData[0].answerData).toEqual({});
@ -371,6 +391,28 @@ function setupMocks({
fmgPage: "part-questions", fmgPage: "part-questions",
}, },
}, },
data() {
return {
computedSwitcher: [
{
glassLocation: "Windshield",
glassName: "Single",
answerData: {
answerResult: "FW04848",
answeredQuestions: [],
},
},
],
};
},
questionsData: {
get() {
return this.computedSwitcher;
},
set(val) {
this.computedSwitcher = val;
},
},
}, },
}) { }) {
const mountOptions = getMountOptions({ const mountOptions = getMountOptions({

View file

@ -16,7 +16,7 @@
<script> <script>
// Components // Components
import questionsPageLayout from "@/common-components/questions-page-layout/questions-page-layout"; import questionsPageLayout from "@/common-components/layouts/questions-page-layout/questions-page-layout";
// Supporting Files // Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
@ -67,47 +67,57 @@ export default {
AlertFewMoreQuestionsCopy() { AlertFewMoreQuestionsCopy() {
return this.getCmsContent("AlertPartsQuestions", "BodyText"); return this.getCmsContent("AlertPartsQuestions", "BodyText");
}, },
pageData() { partsOrQuestionsData() {
return this.$store.getters.pageData(fmgPageValues.PART_QUESTIONS); return this.$store.getters.pageData(fmgPageValues.PART_QUESTIONS).partsOrQuestions;
}, },
}, },
mounted() { mounted() {
// are there alreadyAnsweredQuestions? this.getInitialQuestionData();
const alreadyAnsweredQuestions = store.getters.damage.partQuestionAnswers;
this.questionsData = this.pageData.partsOrQuestions
.filter((x) => x.partQuestions)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.partQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(glass, index, alreadyAnsweredQuestions);
// Set up watch for each set of glass questions
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
}, },
methods: { methods: {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
const partQuestionsFromPageData = store.getters.pageData(fmgPageValues.PART_QUESTIONS); const partQuestionsFromPageData = store.getters.pageData(fmgPageValues.PART_QUESTIONS);
return ( return (
partQuestionsFromPageData && // has .partQuestions array and has glassName not null
Object.keys(partQuestionsFromPageData.partsOrQuestions).length > 0 partQuestionsFromPageData?.partsOrQuestions?.some((part) => part?.glassName) &&
partQuestionsFromPageData?.partsOrQuestions?.some(
(part) => part?.partQuestions?.length > 0
)
); );
}, },
getInitialQuestionData() {
// get any questions that were already answered
const alreadyAnsweredQuestions = store.getters.damage.partQuestionAnswers;
this.questionsData = this.partsOrQuestionsData
.filter((x) => x.partQuestions)
.map((glass, index) => {
// NOTE: questions for property "questions" can differ between layouts
glass.questions = glass.partQuestions;
glass.answerKey = glass.glassLocation + "-" + glass.glassName;
// reset selectedAnswers for this glass
this.selectedAnswers[glass.answerKey] = [];
const updatedGlass = this.setupInitialData(
glass,
index,
alreadyAnsweredQuestions
);
// Set up watch for each set of glass questions
this.$watch(
"selectedAnswers." + glass.answerKey,
(newValue) => {
if (newValue && Object.keys(newValue).length > 0) {
this.handleAnswerUpdates(newValue, glass.answerKey);
}
},
{ deep: true }
);
return updatedGlass;
});
},
async forwardButtonAction() { async forwardButtonAction() {
const questionAnswersArray = this.questionsData.map((glass) => { const questionAnswersArray = this.questionsData.map((glass) => {
return { return {
@ -127,6 +137,7 @@ export default {
}); });
// save to vuex store as order.damage.partQuestionAnswers (array) // save to vuex store as order.damage.partQuestionAnswers (array)
// used in GET_PARTS call following this one
await this.dispatchStoreAction( await this.dispatchStoreAction(
this.storeActions.SAVE_PART_QUESTION_ANSWERS, this.storeActions.SAVE_PART_QUESTION_ANSWERS,
questionAnswersArray, questionAnswersArray,