Merge pull request #3283 from Safelite/feature/CASH-3078

CASH-3078 - Fix question-chain resolving when answerResult has a part…
This commit is contained in:
mvalaiyapathi 2026-07-24 13:45:31 -04:00 committed by GitHub
commit 4175c47127
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 113 additions and 4 deletions

View file

@ -482,8 +482,85 @@ describe("Question Chain component", () => {
expect(wrapper.vm.currentQuestionNum).toBe(3); expect(wrapper.vm.currentQuestionNum).toBe(3);
expect(wrapper.vm.isQuestionVisible(wrapper.vm.questions[2])).toBe(true); expect(wrapper.vm.isQuestionVisible(wrapper.vm.questions[2])).toBe(true);
}); });
test("should resolve on Q1 Yes and not show Q2 for Honda HUD question", async () => {
const { wrapper } = setupMocks({
questionDataProp: getHondaAccordWindshieldQuestions(),
});
await nextTick();
const q1 = wrapper.vm.questions[0];
wrapper.vm.handleAnswer(q1, "1|answer|FW04796|Yes");
expect(wrapper.emitted()["update:modelValue"][0][0]).toMatchObject({
answerResult: "FW04796",
index: 0,
});
expect(wrapper.vm.currentQuestionNum).toBe(0);
expect(wrapper.vm.isQuestionVisible(wrapper.vm.questions[1])).toBe(false);
});
test("should resolve on Q3 No and not continue after remount", async () => {
const questionDataProp = getHondaAccordWindshieldQuestions();
questionDataProp[0].answerSelected = "1|nextQuestion|2|No";
questionDataProp[1].answerSelected = "2|nextQuestion|3|No";
questionDataProp[2].answerSelected = "3|answer|FW04793|No";
const { wrapper } = setupMocks({ questionDataProp });
await nextTick();
expect(wrapper.vm.currentQuestionNum).toBe(0);
expect(wrapper.vm.isQuestionVisible(wrapper.vm.questions[2])).toBe(true);
expect(
wrapper.vm.questions.filter((question) => wrapper.vm.isQuestionVisible(question))
).toHaveLength(3);
});
test("should show Q2 after answering No on Honda HUD question", async () => {
const { wrapper } = setupMocks({
questionDataProp: getHondaAccordWindshieldQuestions(),
});
await nextTick();
const q1 = wrapper.vm.questions[0];
wrapper.vm.handleAnswer(q1, "1|nextQuestion|2|No");
expect(wrapper.vm.currentQuestionNum).toBe(2);
expect(wrapper.vm.isQuestionVisible(wrapper.vm.questions[1])).toBe(true);
}); });
}); });
});
function getHondaAccordWindshieldQuestions() {
return [
{
questionSequence: 1,
questionText:
"Is your vehicle equipped with a Heads-up Display which projects vehicle information, such as speed, onto the windshield?",
answers: [
{ answerResult: "FW04796", answerText: "Yes", nextQuestionSequence: null },
{ answerResult: "", answerText: "No", nextQuestionSequence: 2 },
],
},
{
questionSequence: 2,
questionText:
"Is your vehicle equipped with an auto-dimming rearview mirror which will darken automatically when a vehicles approaches from the rear at night?",
answers: [
{ answerResult: "FW04795", answerText: "Yes", nextQuestionSequence: null },
{ answerResult: "", answerText: "No", nextQuestionSequence: 3 },
],
},
{
questionSequence: 3,
questionText: "Is your vehicle equipped with a power moonroof?",
answers: [
{ answerResult: "FW04794", answerText: "Yes", nextQuestionSequence: null },
{ answerResult: "FW04793", answerText: "No", nextQuestionSequence: null },
],
},
];
}
function getCherokeeWindshieldQuestions() { function getCherokeeWindshieldQuestions() {
return [ return [

View file

@ -20,6 +20,7 @@
import buttonQuestion from "@/digital-components/button-question/button-question"; import buttonQuestion from "@/digital-components/button-question/button-question";
import { useValidateForm } from "vee-validate"; import { useValidateForm } from "vee-validate";
import { import {
isTerminalQuestionChainAnswer,
mapQuestionAnswersForChain, mapQuestionAnswersForChain,
normalizeAnswerSelectedValue, normalizeAnswerSelectedValue,
} from "@/helpers/question-chain-helper"; } from "@/helpers/question-chain-helper";
@ -74,13 +75,18 @@ export default {
return !!question.answerSelected || this.isCurrentQuestion(question); return !!question.answerSelected || this.isCurrentQuestion(question);
}, },
initializeCurrentQuestionNum() { initializeCurrentQuestionNum() {
const pendingNextQuestion = [...this.questions] const lastAnsweredQuestion = [...this.questions]
.reverse() .reverse()
.find((question) => question.answerSelected?.includes("|nextQuestion|")); .find((question) => question.answerSelected);
if (pendingNextQuestion) { if (isTerminalQuestionChainAnswer(lastAnsweredQuestion?.answerSelected)) {
this.currentQuestionNum = 0;
return;
}
if (lastAnsweredQuestion?.answerSelected?.includes("|nextQuestion|")) {
const nextQuestionSequence = Number( const nextQuestionSequence = Number(
pendingNextQuestion.answerSelected.split("|")[2] lastAnsweredQuestion.answerSelected.split("|")[2]
); );
if ( if (

View file

@ -32,6 +32,16 @@ export function mapQuestionAnswersForChain(question) {
})); }));
} }
export function isTerminalQuestionChainAnswer(answerSelected) {
if (!answerSelected) {
return false;
}
const [, questionType, answerResult] = answerSelected.split("|");
return questionType?.toLowerCase() === "answer" && !!answerResult;
}
export function normalizeAnswerSelectedValue(answerSelected, answers) { export function normalizeAnswerSelectedValue(answerSelected, answers) {
if (!answerSelected) { if (!answerSelected) {
return ""; return "";

View file

@ -1,5 +1,6 @@
import { import {
buildQuestionChainAnswerValue, buildQuestionChainAnswerValue,
isTerminalQuestionChainAnswer,
mapQuestionAnswersForChain, mapQuestionAnswersForChain,
normalizeAnswerSelectedValue, normalizeAnswerSelectedValue,
} from "./question-chain-helper"; } from "./question-chain-helper";
@ -29,6 +30,21 @@ describe("question-chain-helper", () => {
}); });
}); });
describe("isTerminalQuestionChainAnswer", () => {
test("returns true when answer has a part number and no next question", () => {
expect(isTerminalQuestionChainAnswer("1|answer|FW04796|Yes")).toBe(true);
expect(isTerminalQuestionChainAnswer("3|answer|FW04793|No")).toBe(true);
});
test("returns false when answer continues to the next question", () => {
expect(isTerminalQuestionChainAnswer("1|nextQuestion|2|No")).toBe(false);
});
test("returns false when answer type is answer but part number is missing", () => {
expect(isTerminalQuestionChainAnswer("1|answer||No")).toBe(false);
});
});
describe("normalizeAnswerSelectedValue", () => { describe("normalizeAnswerSelectedValue", () => {
const answers = [{ value: "1|answer|DW01705|Yes" }, { value: "1|answer|DW01591|No" }]; const answers = [{ value: "1|answer|DW01705|Yes" }, { value: "1|answer|DW01591|No" }];