feat: add check to sanitize answer ranges (#298)

This commit is contained in:
Kristin Aoki
2023-04-07 09:04:15 -04:00
committed by GitHub
parent 9a19711755
commit 284139e247
8 changed files with 98 additions and 8 deletions

View File

@@ -38,6 +38,9 @@ class ReactStateOLXParser {
addHints() {
const hintsArray = [];
const { hints } = this.editorObject;
if (hints.length < 1) {
return {};
}
hints.forEach(hint => {
if (hint.length > 0) {
const parsedHint = this.parser.parse(hint);
@@ -312,6 +315,44 @@ class ReactStateOLXParser {
answers.forEach((answer) => {
const correcthint = this.getAnswerHints(selectedFeedback?.[answer.id]);
if (this.hasAttributeWithValue(answer, 'title')) {
let { title } = answer;
if (title.startsWith('(') || title.startsWith('[')) {
const parsedRange = title.split(',');
const [rawLowerBound, rawUpperBound] = parsedRange;
let lowerBoundInt;
let lowerBoundFraction;
let upperBoundInt;
let upperBoundFraction;
if (rawLowerBound.includes('/')) {
lowerBoundFraction = rawLowerBound.replace(/[^0-9-/]/gm, '');
const [numerator, denominator] = lowerBoundFraction.split('/');
const lowerBoundFloat = Number(numerator) / Number(denominator);
lowerBoundInt = lowerBoundFloat;
} else {
// these regex replaces remove everything that is not a decimal or positive/negative numer
lowerBoundInt = Number(rawLowerBound.replace(/[^0-9-.]/gm, ''));
}
if (rawUpperBound.includes('/')) {
upperBoundFraction = rawUpperBound.replace(/[^0-9-/]/gm, '');
const [numerator, denominator] = upperBoundFraction.split('/');
const upperBoundFloat = Number(numerator) / Number(denominator);
upperBoundInt = upperBoundFloat;
} else {
// these regex replaces remove everything that is not a decimal or positive/negative numer
upperBoundInt = Number(rawUpperBound.replace(/[^0-9-.]/gm, ''));
}
if (lowerBoundInt > upperBoundInt) {
const lowerBoundChar = rawUpperBound[rawUpperBound.length - 1] === ']' ? '[' : '(';
const upperBoundChar = rawLowerBound[0] === '[' ? ']' : ')';
if (lowerBoundFraction) {
lowerBoundInt = lowerBoundFraction;
}
if (upperBoundFraction) {
upperBoundInt = upperBoundFraction;
}
title = `${lowerBoundChar}${upperBoundInt},${lowerBoundInt}${upperBoundChar}`;
}
}
if (answer.correct && !firstCorrectAnswerParsed) {
firstCorrectAnswerParsed = true;
let responseParam = {};
@@ -324,13 +365,13 @@ class ReactStateOLXParser {
};
}
answerObject = {
'@_answer': answer.title,
'@_answer': title,
...responseParam,
...correcthint,
};
} else if (answer.correct && firstCorrectAnswerParsed) {
additionalAnswers.push({
'@_answer': answer.title,
'@_answer': title,
...correcthint,
});
}

View File

@@ -3,6 +3,7 @@ import {
checkboxesOLXWithFeedbackAndHintsOLX,
dropdownOLXWithFeedbackAndHintsOLX,
numericInputWithFeedbackAndHintsOLX,
numericInputWithAnswerRangeOLX,
textInputWithFeedbackAndHintsOLX,
multipleChoiceWithFeedbackAndHintsOLX,
textInputWithFeedbackAndHintsOLXWithMultipleAnswers,
@@ -13,6 +14,7 @@ import {
textInputWithFeedbackAndHints,
multipleChoiceWithFeedbackAndHints,
numericInputWithFeedbackAndHints,
numericInputWithAnswerRange,
textInputWithFeedbackAndHintsWithMultipleAnswers,
} from './mockData/editorTestData';
import ReactStateOLXParser from './ReactStateOLXParser';
@@ -68,6 +70,17 @@ describe('Check React Sate OLXParser problem', () => {
const buildOLX = stateParser.buildOLX();
expect(buildOLX.replace(/\s/g, '')).toEqual(numericInputWithFeedbackAndHintsOLX.buildOLX.replace(/\s/g, ''));
});
test('Test numerical response with isAnswerRange true', () => {
const olxparser = new OLXParser(numericInputWithAnswerRangeOLX.rawOLX);
const problem = olxparser.getParsedOLXData();
const stateParser = new ReactStateOLXParser({
problem,
editorObject: numericInputWithAnswerRange,
});
const buildOLX = stateParser.buildOLX();
expect(buildOLX.replace(/\s/g, '')).toEqual(numericInputWithAnswerRangeOLX.buildOLX.replace(/\s/g, ''));
});
test('Test string response with feedback and hints, multiple answers', () => {
const olxparser = new OLXParser(textInputWithFeedbackAndHintsOLXWithMultipleAnswers.rawOLX);
const problem = olxparser.getParsedOLXData();

View File

@@ -82,6 +82,12 @@ export const numericInputWithFeedbackAndHints = {
question: '<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.</p><label>Add the question text, or prompt, here. This text is required.</label><em>You can add an optional tip or note related to the prompt like this.</em>',
};
export const numericInputWithAnswerRange = {
solution: '',
hints: [],
question: '<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.</p><label>Add the question text, or prompt, here. This text is required.</label><em>You can add an optional tip or note related to the prompt like this.</em>',
};
export const textInputWithFeedbackAndHints = {
solution: '',
selectedFeedback: {

View File

@@ -384,6 +384,38 @@ export const numericInputWithFeedbackAndHintsOLX = {
`,
};
export const numericInputWithAnswerRangeOLX = {
rawOLX: `<problem>
<numericalresponse answer="[3/2,-1.3)">
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<description>You can add an optional tip or note related to the prompt like this. </description>
<formulaequationinput/>\
</numericalresponse>
</problem>`,
data: {
answers: [
{
id: 'A',
title: '[32,-1.3)',
correct: true,
selectedFeedback: '<p>You can specify optional feedback like this, which appears after this answer is submitted.</p>',
isAnswerRange: true,
},
],
},
question: '<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.</p><label>Add the question text, or prompt, here. This text is required.</label><em>You can add an optional tip or note related to the prompt like this.</em>',
buildOLX: `<problem>
<p>You can use this template as a guide to the simple editor markdown and OLX markup to use for numerical input with hints and feedback problems. Edit this component to replace this template with your own assessment.</p>
<label>Add the question text, or prompt, here. This text is required.</label>
<em>You can add an optional tip or note related to the prompt like this.</em>
<numericalresponse answer="(-1.3,3/2]">
<formulaequationinput></formulaequationinput>
</numericalresponse>
</problem>
`,
};
export const textInputWithFeedbackAndHintsOLX = {
rawOLX: `<problem>
<stringresponse answer="the correct answer" type="ci">