diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
index f2a58b560..270295ab1 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
@@ -16,6 +16,7 @@ import { answerOptionProps } from '../../../../../data/services/cms/types';
import Checker from './components/Checker';
import { FeedbackBox } from './components/Feedback';
import * as hooks from './hooks';
+import { ProblemTypeKeys } from '../../../../../data/constants/problem';
export const AnswerOption = ({
answer,
@@ -43,6 +44,7 @@ export const AnswerOption = ({
hasSingleAnswer={hasSingleAnswer}
answer={answer}
setAnswer={setAnswer}
+ disabled={problemType === ProblemTypeKeys.NUMERIC}
/>
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
index 439c597a3..514c4e4a3 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
@@ -42,6 +42,9 @@ describe('AnswerOption', () => {
test('snapshot: renders correct option with selected unselected feedback', () => {
expect(shallow(
)).toMatchSnapshot();
});
+ test('snapshot: renders correct option with numeric input problem', () => {
+ expect(shallow(
)).toMatchSnapshot();
+ });
});
describe('mapStateToProps', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswerOption.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswerOption.test.jsx.snap
index dcf72e6e5..8c467209e 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswerOption.test.jsx.snap
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/__snapshots__/AnswerOption.test.jsx.snap
@@ -18,6 +18,7 @@ exports[`AnswerOption render snapshot: renders correct option with feedback 1`]
"title": "Answer 1",
}
}
+ disabled={false}
hasSingleAnswer={false}
setAnswer={[Function]}
/>
@@ -75,6 +76,82 @@ exports[`AnswerOption render snapshot: renders correct option with feedback 1`]
`;
+exports[`AnswerOption render snapshot: renders correct option with numeric input problem 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
exports[`AnswerOption render snapshot: renders correct option with selected unselected feedback 1`] = `
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/__snapshots__/index.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/__snapshots__/index.test.jsx.snap
index 86f530613..8dceea743 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/__snapshots__/index.test.jsx.snap
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/__snapshots__/index.test.jsx.snap
@@ -1,25 +1,55 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`Checker component with disabled 1`] = `
+
+
+
+ A
+
+
+`;
+
exports[`Checker component with multiple answers 1`] = `
-
- A
-
+
+
+
+ A
+
+
`;
exports[`Checker component with single answer 1`] = `
-
- A
-
+
+
+
+ A
+
+
`;
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
index 70813d0f2..b616207b9 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.jsx
@@ -3,24 +3,36 @@ import PropTypes from 'prop-types';
import { Form } from '@edx/paragon';
const Checker = ({
- hasSingleAnswer, answer, setAnswer,
+ hasSingleAnswer,
+ answer,
+ setAnswer,
+ disabled,
}) => {
let CheckerType = Form.Checkbox;
if (hasSingleAnswer) {
CheckerType = Form.Radio;
}
return (
-
setAnswer({ correct: e.target.checked })}
- checked={answer.correct}
- isValid={answer.correct}
- >
- {answer.id}
-
+ <>
+
setAnswer({ correct: e.target.checked })}
+ checked={answer.correct}
+ isValid={answer.correct}
+ disabled={disabled}
+ />
+
+ {answer.id}
+
+ >
);
};
+Checker.defaultProps = {
+ disabled: false,
+};
Checker.propTypes = {
hasSingleAnswer: PropTypes.bool.isRequired,
answer: PropTypes.shape({
@@ -28,6 +40,7 @@ Checker.propTypes = {
id: PropTypes.number,
}).isRequired,
setAnswer: PropTypes.func.isRequired,
+ disabled: PropTypes.bool,
};
export default Checker;
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
index 19998a536..0ecb229be 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
@@ -19,4 +19,8 @@ describe('Checker component', () => {
test('with multiple answers', () => {
expect(shallow()).toMatchSnapshot();
});
+
+ test('with disabled', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
index 5bdb368f2..65d1690f4 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
@@ -213,6 +213,11 @@ export const typeRowHooks = ({
}
});
};
+ const updateAnswersToCorrect = () => {
+ answers.forEach(answer => {
+ updateAnswer({ ...answer, correct: true });
+ });
+ };
const onClick = () => {
// Dropdown problems can only have one correct answer. When there is more than one correct answer
// from a previous problem type, the correct attribute for selected answers need to be set to false.
@@ -221,6 +226,11 @@ export const typeRowHooks = ({
clearPreviouslySelectedAnswers();
}
}
+ // Numeric input problems can only have correct answers. Switch all answers to correct when switching
+ // to numeric input.
+ if (typeKey === ProblemTypeKeys.NUMERIC) {
+ updateAnswersToCorrect();
+ }
if (blockTitle === ProblemTypes[problemType].title) {
setBlockTitle(ProblemTypes[typeKey].title);
}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
index 6caf59e1a..1b95bfdfa 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
@@ -3,6 +3,7 @@ import { MockUseState } from '../../../../../../testUtils';
import messages from './messages';
import * as hooks from './hooks';
+import { ProblemTypeKeys, ProblemTypes } from '../../../../../data/constants/problem';
jest.mock('react', () => {
const updateState = jest.fn();
@@ -249,55 +250,55 @@ describe('Problem settings hooks', () => {
});
describe('Type row hooks', () => {
- test('test onClick', () => {
- const typekey = 'optionresponse';
- const problemType = 'choiceresponse';
- const blockTitle = 'Multi-select';
- const setBlockTitle = jest.fn();
- const updateField = jest.fn();
- const updateAnswer = jest.fn();
- const answers = [{
- correct: true,
- id: 'a',
- },
- {
- correct: true,
- id: 'b',
- },
- {
- correct: false,
- id: 'c',
- }];
+ const typeRowProps = {
+ problemType: ProblemTypeKeys.MULTISELECT,
+ typeKey: ProblemTypeKeys.DROPDOWN,
+ blockTitle: ProblemTypes[ProblemTypeKeys.MULTISELECT].title,
+ setBlockTitle: jest.fn(),
+ updateField: jest.fn(),
+ updateAnswer: jest.fn(),
+ correctAnswerCount: 2,
+ answers: [
+ { correct: true, id: 'a' },
+ { correct: true, id: 'b' },
+ { correct: false, id: 'c' },
+ ],
+ };
+ beforeEach(() => {
+ jest.clearAllMocks();
+ });
+ test('test onClick Multi-select to Dropdown', () => {
+ output = hooks.typeRowHooks(typeRowProps);
+ output.onClick();
+ expect(typeRowProps.setBlockTitle).toHaveBeenCalledWith(ProblemTypes[ProblemTypeKeys.DROPDOWN].title);
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, { ...typeRowProps.answers[0], correct: false });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, { ...typeRowProps.answers[1], correct: false });
+ expect(typeRowProps.updateAnswer).not.toHaveBeenNthCalledWith(3, { ...typeRowProps.answers[2], correct: false });
+ expect(typeRowProps.updateField).toHaveBeenCalledWith({ problemType: ProblemTypeKeys.DROPDOWN });
+ });
+ test('test onClick Multi-select to Numeric', () => {
output = hooks.typeRowHooks({
- answers,
- blockTitle,
- correctAnswerCount: 2,
- problemType,
- setBlockTitle,
- typeKey: typekey,
- updateField,
- updateAnswer,
+ ...typeRowProps,
+ typeKey: ProblemTypeKeys.NUMERIC,
});
output.onClick();
- expect(setBlockTitle).toHaveBeenCalledWith('Dropdown');
- expect(updateAnswer).toHaveBeenNthCalledWith(1, { ...answers[0], correct: false });
- expect(updateAnswer).toHaveBeenNthCalledWith(2, { ...answers[1], correct: false });
- expect(updateAnswer).not.toHaveBeenNthCalledWith(3, { ...answers[2], correct: false });
- expect(updateField).toHaveBeenCalledWith({ problemType: typekey });
+ expect(typeRowProps.setBlockTitle).toHaveBeenCalledWith(ProblemTypes[ProblemTypeKeys.NUMERIC].title);
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(1, { ...typeRowProps.answers[0], correct: true });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(2, { ...typeRowProps.answers[1], correct: true });
+ expect(typeRowProps.updateAnswer).toHaveBeenNthCalledWith(3, { ...typeRowProps.answers[2], correct: true });
+ expect(typeRowProps.updateField).toHaveBeenCalledWith({ problemType: ProblemTypeKeys.NUMERIC });
});
});
- describe('Type row hooks', () => {
- test('test onClick', () => {
- const switchToAdvancedEditor = jest.fn();
- const setConfirmOpen = jest.fn();
- window.scrollTo = jest.fn();
- hooks.confirmSwitchToAdvancedEditor({
- switchToAdvancedEditor,
- setConfirmOpen,
- });
- expect(switchToAdvancedEditor).toHaveBeenCalled();
- expect(setConfirmOpen).toHaveBeenCalledWith(false);
- expect(window.scrollTo).toHaveBeenCalled();
+ test('test confirmSwitchToAdvancedEditor hook', () => {
+ const switchToAdvancedEditor = jest.fn();
+ const setConfirmOpen = jest.fn();
+ window.scrollTo = jest.fn();
+ hooks.confirmSwitchToAdvancedEditor({
+ switchToAdvancedEditor,
+ setConfirmOpen,
});
+ expect(switchToAdvancedEditor).toHaveBeenCalled();
+ expect(setConfirmOpen).toHaveBeenCalledWith(false);
+ expect(window.scrollTo).toHaveBeenCalled();
});
});
diff --git a/src/editors/data/redux/problem/reducers.js b/src/editors/data/redux/problem/reducers.js
index 262f65007..6e7628ea5 100644
--- a/src/editors/data/redux/problem/reducers.js
+++ b/src/editors/data/redux/problem/reducers.js
@@ -2,7 +2,7 @@ import _ from 'lodash-es';
import { createSlice } from '@reduxjs/toolkit';
import { indexToLetterMap } from '../../../containers/ProblemEditor/data/OLXParser';
import { StrictDict } from '../../../utils';
-import { ShowAnswerTypesKeys } from '../../constants/problem';
+import { ProblemTypeKeys, ShowAnswerTypesKeys } from '../../constants/problem';
const nextAlphaId = (lastId) => String.fromCharCode(lastId.charCodeAt(0) + 1);
const initialState = {
@@ -108,8 +108,12 @@ const problem = createSlice({
title: '',
selectedFeedback: '',
unselectedFeedback: '',
- correct: false,
+ correct: state.problemType === ProblemTypeKeys.NUMERIC,
};
+ let { correctAnswerCount } = state;
+ if (state.problemType === ProblemTypeKeys.NUMERIC) {
+ correctAnswerCount += 1;
+ }
const answers = [
...currAnswers,
@@ -117,6 +121,7 @@ const problem = createSlice({
];
return {
...state,
+ correctAnswerCount,
answers,
};
},
diff --git a/src/editors/data/redux/problem/reducers.test.js b/src/editors/data/redux/problem/reducers.test.js
index a563821ef..18176176f 100644
--- a/src/editors/data/redux/problem/reducers.test.js
+++ b/src/editors/data/redux/problem/reducers.test.js
@@ -1,4 +1,5 @@
import { initialState, actions, reducer } from './reducers';
+import { ProblemTypeKeys } from '../../constants/problem';
const testingState = {
...initialState,
@@ -71,20 +72,35 @@ describe('problem reducer', () => {
});
});
describe('addAnswer', () => {
+ const answer = {
+ id: 'A',
+ correct: false,
+ selectedFeedback: '',
+ title: '',
+ unselectedFeedback: '',
+ };
it('sets answers', () => {
- const answer = {
- id: 'A',
- correct: false,
- selectedFeedback: '',
- title: '',
- unselectedFeedback: '',
- };
expect(reducer({ ...testingState, problemType: 'choiceresponse' }, actions.addAnswer())).toEqual({
...testingState,
problemType: 'choiceresponse',
answers: [answer],
});
});
+ it('sets answers for numeric input', () => {
+ const numericTestState = {
+ ...testingState,
+ problemType: ProblemTypeKeys.NUMERIC,
+ correctAnswerCount: 0,
+ };
+ expect(reducer(numericTestState, actions.addAnswer())).toEqual({
+ ...numericTestState,
+ correctAnswerCount: 1,
+ answers: [{
+ ...answer,
+ correct: true,
+ }],
+ });
+ });
});
describe('updateAnswer', () => {
it('sets answers, as well as setting the correctAnswerCount ', () => {