From 11a7e78b7386cfac4fdbc69c257f6008dbb1c67b Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Tue, 25 Feb 2025 20:41:49 +0000 Subject: [PATCH] fix: parsing text input problems (#1679) * Parse incorrect answer fields in text input problems * Fix feedback order --- .../components/EditProblemView/hooks.js | 4 +- .../ProblemEditor/data/OLXParser.js | 11 ++- .../ProblemEditor/data/OLXParser.test.js | 9 +++ .../data/mockData/olxTestData.js | 80 +++++++++++++++++++ 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js index a8755c8e4..9ff1ddbd0 100644 --- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js +++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js @@ -93,7 +93,7 @@ export const checkForNoAnswers = ({ openSaveWarningModal, problem }) => { const titles = []; answers.forEach(answer => { const title = simpleTextAreaProblems.includes(problemType) ? answer.title : answerTitles[answer.id]; - if (title.length > 0) { + if (title?.length > 0) { titles.push(title); } }); @@ -108,7 +108,7 @@ export const checkForNoAnswers = ({ openSaveWarningModal, problem }) => { answers.forEach(answer => { if (answer.correct) { const title = simpleTextAreaProblems.includes(problemType) ? answer.title : answerTitles[answer.id]; - if (title.length > 0) { + if (title?.length > 0) { correctAnswer = true; } } diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.js b/src/editors/containers/ProblemEditor/data/OLXParser.js index cbdb163c5..e861b5cea 100644 --- a/src/editors/containers/ProblemEditor/data/OLXParser.js +++ b/src/editors/containers/ProblemEditor/data/OLXParser.js @@ -140,10 +140,12 @@ export class OLXParser { [correctAnswerFeedbackTag, incorrectAnswerFeedbackTag] = option; } const problemBodyArr = problemBody[problemType]; + let hasCorrectAnswerFeedback = isChoiceProblem; problemBodyArr.forEach(subtag => { const tagNames = Object.keys(subtag); if (!isChoiceProblem && tagNames.includes(correctAnswerFeedbackTag)) { preservedAnswers.unshift(subtag[correctAnswerFeedbackTag]); + hasCorrectAnswerFeedback = true; } if (problemType === ProblemTypeKeys.TEXTINPUT && tagNames.includes(incorrectAnswerFeedbackTag)) { preservedAnswers.push(subtag); @@ -157,6 +159,11 @@ export class OLXParser { }); } }); + // Since the first feedback is taken as correct answer feedback by non-choice problems, + // we insert an empty array to preserve feedback order. + if (!hasCorrectAnswerFeedback) { + preservedAnswers.unshift([]); + } return preservedAnswers; } @@ -360,7 +367,7 @@ export class OLXParser { const stringEqualHint = _.get(stringresponse, 'stringequalhint', []); if (_.isArray(stringEqualHint)) { stringEqualHint.forEach((newAnswer, indx) => { - answerFeedback = this.richTextBuilder.build(stringEqualHintFeedback[indx].stringequalhint); + answerFeedback = this.getFeedback(stringEqualHintFeedback[indx]?.stringequalhint); answers.push({ id: indexToLetterMap[answers.length], title: newAnswer['@_answer'], @@ -369,7 +376,7 @@ export class OLXParser { }); }); } else { - answerFeedback = this.richTextBuilder.build(stringEqualHintFeedback[0].stringequalhint); + answerFeedback = this.getFeedback(stringEqualHintFeedback[0]?.stringequalhint); answers.push({ id: indexToLetterMap[answers.length], title: stringEqualHint['@_answer'], diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.test.js b/src/editors/containers/ProblemEditor/data/OLXParser.test.js index b463ccf34..e71892a9c 100644 --- a/src/editors/containers/ProblemEditor/data/OLXParser.test.js +++ b/src/editors/containers/ProblemEditor/data/OLXParser.test.js @@ -4,6 +4,7 @@ import { dropdownOLXWithFeedbackAndHintsOLX, numericInputWithFeedbackAndHintsOLX, textInputWithFeedbackAndHintsOLX, + textInputWithFeedbackInIncorrectAnswerOnlyOLX, multipleChoiceWithoutAnswers, multipleChoiceSingleAnswer, multipleChoiceWithFeedbackAndHintsOLX, @@ -39,6 +40,7 @@ const multipleChoiceOlxParser = new OLXParser(multipleChoiceWithFeedbackAndHints const multipleChoiceWithoutAnswersOlxParser = new OLXParser(multipleChoiceWithoutAnswers.rawOLX); const multipleChoiceSingleAnswerOlxParser = new OLXParser(multipleChoiceSingleAnswer.rawOLX); const textInputOlxParser = new OLXParser(textInputWithFeedbackAndHintsOLX.rawOLX); +const textInputIncorrectFeedbackOlxParser = new OLXParser(textInputWithFeedbackInIncorrectAnswerOnlyOLX.rawOLX); const textInputMultipleAnswersOlxParser = new OLXParser(textInputWithFeedbackAndHintsOLXWithMultipleAnswers.rawOLX); const advancedOlxParser = new OLXParser(advancedProblemOlX.rawOLX); const multipleTextInputOlxParser = new OLXParser(multipleTextInputProblemOlX.rawOLX); @@ -286,6 +288,13 @@ describe('OLXParser', () => { expect(answers).toHaveLength(3); }); }); + describe('given text input olx with feedback for incorrect answer only and hints', () => { + const { answers } = textInputIncorrectFeedbackOlxParser.parseStringResponse(); + it('should equal an array of objects with length three', () => { + expect(answers).toEqual(textInputWithFeedbackInIncorrectAnswerOnlyOLX.data.answers); + expect(answers).toHaveLength(4); + }); + }); describe('given text input olx with feedback and hints with multiple answers', () => { const { answers } = textInputMultipleAnswersOlxParser.parseStringResponse(); it('should equal an array of objects with length four', () => { diff --git a/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js b/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js index 99e25a2b5..b729de352 100644 --- a/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js +++ b/src/editors/containers/ProblemEditor/data/mockData/olxTestData.js @@ -562,6 +562,86 @@ export const textInputWithFeedbackAndHintsOLX = { `, }; +export const textInputWithFeedbackInIncorrectAnswerOnlyOLX = { + rawOLX: ` + +

You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.

+ +You can add an optional tip or note related to the prompt like this. + +

You can specify optional feedback for none, a subset, or all of the answers.

+

You can specify feedback again.

+ +
+ +

You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.

+

If you add more than one hint, a different hint appears each time learners select the hint button.

+
+
`, + hints: [{ + id: 0, + value: '

You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.

', + }, + { + id: 1, + value: '

If you add more than one hint, a different hint appears each time learners select the hint button.

', + }, + ], + data: { + answers: [ + { + id: 'A', + title: 'the correct answer', + correct: true, + selectedFeedback: '', + }, + { + id: 'B', + title: 'optional acceptable variant of the correct answer', + correct: true, + selectedFeedback: '', + }, + { + id: 'C', + title: 'optional incorrect answer such as a frequent misconception', + correct: false, + selectedFeedback: '

You can specify optional feedback for none, a subset, or all of the answers.

', + }, + { + id: 'D', + title: 'another optional incorrect answer such as a frequent misconception', + correct: false, + selectedFeedback: '

You can specify feedback again.

', + }, + ], + additionalStringAttributes: { + type: 'ci', + textline: { + size: '20', + }, + }, + }, + question: `

You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.

+ +You can add an optional tip or note related to the prompt like this. `, + buildOLX: ` + +

You can use this template as a guide to the simple editor markdown and OLX markup to use for text input with hints and feedback problems. Edit this component to replace this template with your own assessment.

+ + You can add an optional tip or note related to the prompt like this. +

You can specify optional feedback like this, which appears after this answer is submitted.

+ +

You can specify optional feedback for none, a subset, or all of the answers.

+ +
+ +

You can add an optional hint like this. Problems that have a hint include a hint button, and this text appears the first time learners select the button.

+

If you add more than one hint, a different hint appears each time learners select the hint button.

+
+
+`, +}; + export const textInputWithFeedbackAndHintsOLXWithMultipleAnswers = { rawOLX: `