fix: delete answers without changing expandable (#328)
This commit is contained in:
@@ -7,6 +7,7 @@ import { AnswerOption, mapStateToProps } from './AnswerOption';
|
||||
jest.mock('../../../../../data/redux', () => ({
|
||||
selectors: {
|
||||
problem: {
|
||||
answers: jest.fn(state => ({ answers: state })),
|
||||
problemType: jest.fn(state => ({ problemType: state })),
|
||||
},
|
||||
},
|
||||
|
||||
@@ -9,8 +9,15 @@ export const state = StrictDict({
|
||||
isFeedbackVisible: (val) => useState(val),
|
||||
});
|
||||
|
||||
export const removeAnswer = ({ answer, dispatch }) => () => {
|
||||
dispatch(actions.problem.deleteAnswer({ id: answer.id, correct: answer.correct }));
|
||||
export const removeAnswer = ({
|
||||
answer,
|
||||
dispatch,
|
||||
}) => () => {
|
||||
dispatch(actions.problem.deleteAnswer({
|
||||
id: answer.id,
|
||||
correct: answer.correct,
|
||||
editorState: fetchEditorContent({ format: '' }),
|
||||
}));
|
||||
};
|
||||
|
||||
export const setAnswer = ({ answer, hasSingleAnswer, dispatch }) => (payload) => {
|
||||
@@ -52,7 +59,7 @@ export const useFeedback = (answer) => {
|
||||
// Show feedback fields if feedback is present
|
||||
const isVisible = !!answer.selectedFeedback || !!answer.unselectedFeedback;
|
||||
setIsFeedbackVisible(isVisible);
|
||||
}, []);
|
||||
}, [answer]);
|
||||
|
||||
const toggleFeedback = (open) => {
|
||||
// Do not allow to hide if feedback is added
|
||||
|
||||
@@ -13,11 +13,9 @@ jest.mock('react', () => {
|
||||
useState: jest.fn(val => ([{ state: val }, (newVal) => updateState({ val, newVal })])),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('@edx/frontend-platform/i18n', () => ({
|
||||
defineMessages: m => m,
|
||||
}));
|
||||
|
||||
jest.mock('../../../../../data/redux', () => ({
|
||||
actions: {
|
||||
problem: {
|
||||
@@ -36,20 +34,37 @@ const answerWithOnlyFeedback = {
|
||||
correct: true,
|
||||
selectedFeedback: 'some feedback',
|
||||
};
|
||||
let windowSpy;
|
||||
|
||||
describe('Answer Options Hooks', () => {
|
||||
beforeEach(() => { jest.clearAllMocks(); });
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('state hooks', () => {
|
||||
state.testGetter(state.keys.isFeedbackVisible);
|
||||
});
|
||||
describe('removeAnswer', () => {
|
||||
test('it dispatches actions.problem.deleteAnswer', () => {
|
||||
const answer = { id: 'A', correct: false };
|
||||
const dispatch = useDispatch();
|
||||
module.removeAnswer({ answer, dispatch })();
|
||||
beforeEach(() => {
|
||||
windowSpy = jest.spyOn(window, 'window', 'get');
|
||||
});
|
||||
afterEach(() => {
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
const answer = { id: 'A', correct: false };
|
||||
const dispatch = useDispatch();
|
||||
it('dispatches actions.problem.deleteAnswer', () => {
|
||||
windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'answer-A': { getContent: () => 'string' } } } }));
|
||||
module.removeAnswer({
|
||||
answer,
|
||||
dispatch,
|
||||
})();
|
||||
expect(dispatch).toHaveBeenCalledWith(actions.problem.deleteAnswer({
|
||||
id: answer.id,
|
||||
correct: answer.correct,
|
||||
editorState: {
|
||||
answers: { A: 'string' },
|
||||
hints: [],
|
||||
},
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -134,9 +149,15 @@ describe('Answer Options Hooks', () => {
|
||||
});
|
||||
});
|
||||
describe('useFeedback hook', () => {
|
||||
beforeEach(() => { state.mock(); });
|
||||
afterEach(() => { state.restore(); });
|
||||
test('test default state is false', () => {
|
||||
beforeEach(() => {
|
||||
state.mock();
|
||||
windowSpy = jest.spyOn(window, 'window', 'get');
|
||||
});
|
||||
afterEach(() => {
|
||||
state.restore();
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
test('default state is false', () => {
|
||||
output = module.useFeedback(answerWithOnlyFeedback);
|
||||
expect(output.isFeedbackVisible).toBeFalsy();
|
||||
});
|
||||
@@ -148,24 +169,24 @@ describe('Answer Options Hooks', () => {
|
||||
cb();
|
||||
expect(state.setState[key]).toHaveBeenCalledWith(true);
|
||||
});
|
||||
test('test toggleFeedback with selected feedback', () => {
|
||||
test('toggleFeedback with selected feedback', () => {
|
||||
const key = state.keys.isFeedbackVisible;
|
||||
output = module.useFeedback(answerWithOnlyFeedback);
|
||||
window.tinymce.editors = { 'selectedFeedback-A': { getContent: () => 'string' } };
|
||||
windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'selectedFeedback-A': { getContent: () => 'string' } } } }));
|
||||
output.toggleFeedback(false);
|
||||
expect(state.setState[key]).toHaveBeenCalledWith(true);
|
||||
});
|
||||
test('test toggleFeedback with unselected feedback', () => {
|
||||
test('toggleFeedback with unselected feedback', () => {
|
||||
const key = state.keys.isFeedbackVisible;
|
||||
output = module.useFeedback(answerWithOnlyFeedback);
|
||||
window.tinymce.editors = { 'unselectedFeedback-A': { getContent: () => 'string' } };
|
||||
windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'unselectedFeedback-A': { getContent: () => 'string' } } } }));
|
||||
output.toggleFeedback(false);
|
||||
expect(state.setState[key]).toHaveBeenCalledWith(true);
|
||||
});
|
||||
test('test toggleFeedback with unselected feedback', () => {
|
||||
test('toggleFeedback with unselected feedback', () => {
|
||||
const key = state.keys.isFeedbackVisible;
|
||||
output = module.useFeedback(answerWithOnlyFeedback);
|
||||
window.tinymce.editors = { 'answer-A': { getContent: () => 'string' } };
|
||||
windowSpy.mockImplementation(() => ({ tinymce: { editors: { 'answer-A': { getContent: () => 'string' } } } }));
|
||||
output.toggleFeedback(false);
|
||||
expect(state.setState[key]).toHaveBeenCalledWith(false);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,12 @@ import { useState, useEffect } from 'react';
|
||||
import _ from 'lodash-es';
|
||||
import * as module from './hooks';
|
||||
import messages from './messages';
|
||||
import { ProblemTypeKeys, ProblemTypes, ShowAnswerTypesKeys } from '../../../../../data/constants/problem';
|
||||
import {
|
||||
ProblemTypeKeys,
|
||||
ProblemTypes,
|
||||
RichTextProblems,
|
||||
ShowAnswerTypesKeys,
|
||||
} from '../../../../../data/constants/problem';
|
||||
import { fetchEditorContent } from '../hooks';
|
||||
|
||||
export const state = {
|
||||
@@ -214,11 +219,9 @@ export const typeRowHooks = ({
|
||||
updateField,
|
||||
updateAnswer,
|
||||
}) => {
|
||||
const richTextProblems = [ProblemTypeKeys.SINGLESELECT, ProblemTypeKeys.MULTISELECT];
|
||||
|
||||
const clearPreviouslySelectedAnswers = () => {
|
||||
let currentAnswerTitles;
|
||||
if (richTextProblems.includes(problemType)) {
|
||||
if (RichTextProblems.includes(problemType)) {
|
||||
currentAnswerTitles = fetchEditorContent({ format: 'text' }).answers;
|
||||
}
|
||||
answers.forEach(answer => {
|
||||
@@ -233,7 +236,7 @@ export const typeRowHooks = ({
|
||||
|
||||
const updateAnswersToCorrect = () => {
|
||||
let currentAnswerTitles;
|
||||
if (richTextProblems.includes(problemType)) {
|
||||
if (RichTextProblems.includes(problemType)) {
|
||||
currentAnswerTitles = fetchEditorContent({ format: 'text' }).answers;
|
||||
}
|
||||
answers.forEach(answer => {
|
||||
@@ -252,7 +255,7 @@ export const typeRowHooks = ({
|
||||
const onClick = () => {
|
||||
// Numeric, text, and dropdowns cannot render HTML as answer values, so if switching from a single select
|
||||
// or multi-select problem the rich text needs to covert to plain text
|
||||
if (typeKey === ProblemTypeKeys.TEXTINPUT && richTextProblems.includes(problemType)) {
|
||||
if (typeKey === ProblemTypeKeys.TEXTINPUT && RichTextProblems.includes(problemType)) {
|
||||
convertToPlainText();
|
||||
}
|
||||
// Dropdown problems can only have one correct answer. When there is more than one correct answer
|
||||
@@ -260,7 +263,7 @@ export const typeRowHooks = ({
|
||||
if (typeKey === ProblemTypeKeys.DROPDOWN) {
|
||||
if (correctAnswerCount > 1) {
|
||||
clearPreviouslySelectedAnswers();
|
||||
} else if (richTextProblems.includes(problemType)) {
|
||||
} else if (RichTextProblems.includes(problemType)) {
|
||||
convertToPlainText();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -630,6 +630,8 @@ export class OLXParser {
|
||||
} else {
|
||||
settings.tolerance = { value: parseInt(toleranceValue), type: 'Number' };
|
||||
}
|
||||
} else {
|
||||
settings.tolerance = { value: null, type: 'None' };
|
||||
}
|
||||
if (solutionExplanation) { settings.solutionExplanation = solutionExplanation; }
|
||||
|
||||
|
||||
@@ -196,17 +196,16 @@ export const RandomizationTypesKeys = StrictDict({
|
||||
ONRESET: 'on_reset',
|
||||
PERSTUDENT: 'per_student',
|
||||
});
|
||||
|
||||
export const RandomizationTypes = StrictDict({
|
||||
[RandomizationTypesKeys.ALWAYS]:
|
||||
{
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.always',
|
||||
defaultMessage: 'Always',
|
||||
},
|
||||
[RandomizationTypesKeys.NEVER]:
|
||||
{
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.never',
|
||||
defaultMessage: 'Never',
|
||||
},
|
||||
[RandomizationTypesKeys.ALWAYS]: {
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.always',
|
||||
defaultMessage: 'Always',
|
||||
},
|
||||
[RandomizationTypesKeys.NEVER]: {
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.never',
|
||||
defaultMessage: 'Never',
|
||||
},
|
||||
[RandomizationTypesKeys.ONRESET]: {
|
||||
id: 'authoring.problemeditor.settings.RandomizationTypes.onreset',
|
||||
defaultMessage: 'On Reset',
|
||||
@@ -216,3 +215,5 @@ export const RandomizationTypes = StrictDict({
|
||||
defaultMessage: 'Per Student',
|
||||
},
|
||||
});
|
||||
|
||||
export const RichTextProblems = [ProblemTypeKeys.SINGLESELECT, ProblemTypeKeys.MULTISELECT];
|
||||
|
||||
@@ -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 { ProblemTypeKeys, ShowAnswerTypesKeys } from '../../constants/problem';
|
||||
import { ProblemTypeKeys, RichTextProblems, ShowAnswerTypesKeys } from '../../constants/problem';
|
||||
import { ToleranceTypes } from '../../../containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/constants';
|
||||
|
||||
const nextAlphaId = (lastId) => String.fromCharCode(lastId.charCodeAt(0) + 1);
|
||||
@@ -82,41 +82,66 @@ const problem = createSlice({
|
||||
};
|
||||
},
|
||||
deleteAnswer: (state, { payload }) => {
|
||||
const { id, correct } = payload;
|
||||
if (state.answers.length <= 1) {
|
||||
if (state.answers.length > 0 && state.answers[0].isAnswerRange) {
|
||||
return {
|
||||
...state,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
title: '',
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
correct: state.problemType === ProblemTypeKeys.NUMERIC,
|
||||
isAnswerRange: false,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
let { correctAnswerCount } = state;
|
||||
if (correct) {
|
||||
correctAnswerCount -= 1;
|
||||
const { id, correct, editorState } = payload;
|
||||
const EditorsArray = window.tinymce.editors;
|
||||
if (state.answers.length === 1) {
|
||||
return {
|
||||
...state,
|
||||
correctAnswerCount: state.problemType === ProblemTypeKeys.NUMERIC ? 1 : 0,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
title: '',
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
correct: state.problemType === ProblemTypeKeys.NUMERIC,
|
||||
isAnswerRange: false,
|
||||
}],
|
||||
};
|
||||
}
|
||||
const answers = state.answers.filter(obj => obj.id !== id).map((answer, index) => {
|
||||
const newId = indexToLetterMap[index];
|
||||
if (answer.id === newId) {
|
||||
return answer;
|
||||
}
|
||||
return { ...answer, id: newId };
|
||||
let newAnswer = {
|
||||
...answer,
|
||||
id: newId,
|
||||
selectedFeedback: editorState.selectedFeedback ? editorState.selectedFeedback[answer.id] : '',
|
||||
unselectedFeedback: editorState.unselectedFeedback ? editorState.unselectedFeedback[answer.id] : '',
|
||||
};
|
||||
if (RichTextProblems.includes(state.problemType)) {
|
||||
newAnswer = {
|
||||
...newAnswer,
|
||||
title: editorState.answers[answer.id],
|
||||
};
|
||||
if (EditorsArray[`answer-${newId}`]) {
|
||||
EditorsArray[`answer-${newId}`].setContent(newAnswer.title ?? '');
|
||||
}
|
||||
}
|
||||
// Note: The following assumes selectedFeedback and unselectedFeedback is using ExpandedTextArea
|
||||
// Content only needs to be set here when the 'next' feedback fields are shown.
|
||||
if (EditorsArray[`selectedFeedback-${newId}`]) {
|
||||
EditorsArray[`selectedFeedback-${newId}`].setContent(newAnswer.selectedFeedback ?? '');
|
||||
}
|
||||
if (EditorsArray[`unselectedFeedback-${newId}`]) {
|
||||
EditorsArray[`unselectedFeedback-${newId}`].setContent(newAnswer.unselectedFeedback ?? '');
|
||||
}
|
||||
return newAnswer;
|
||||
});
|
||||
const groupFeedbackList = state.groupFeedbackList.map(feedback => {
|
||||
const newAnswers = feedback.answers.filter(obj => obj !== id).map(letter => {
|
||||
if (letter.charCodeAt(0) > id.charCodeAt(0)) {
|
||||
return String.fromCharCode(letter.charCodeAt(0) - 1);
|
||||
}
|
||||
return letter;
|
||||
});
|
||||
return { ...feedback, answers: newAnswers };
|
||||
});
|
||||
return {
|
||||
...state,
|
||||
correctAnswerCount,
|
||||
answers,
|
||||
correctAnswerCount: correct ? state.correctAnswerCount - 1 : state.correctAnswerCount,
|
||||
groupFeedbackList,
|
||||
};
|
||||
},
|
||||
addAnswer: (state) => {
|
||||
|
||||
@@ -118,7 +118,6 @@ describe('problem reducer', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addAnswerRange', () => {
|
||||
const answerRange = {
|
||||
id: 'A',
|
||||
@@ -137,7 +136,6 @@ describe('problem reducer', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateAnswer', () => {
|
||||
it('sets answers, as well as setting the correctAnswerCount ', () => {
|
||||
const answer = { id: 'A', correct: true };
|
||||
@@ -158,63 +156,287 @@ describe('problem reducer', () => {
|
||||
});
|
||||
});
|
||||
describe('deleteAnswer', () => {
|
||||
it('sets answers, as well as setting the correctAnswerCount ', () => {
|
||||
const answer = { id: 'A', correct: false };
|
||||
let windowSpy;
|
||||
beforeEach(() => {
|
||||
windowSpy = jest.spyOn(window, 'window', 'get');
|
||||
});
|
||||
afterEach(() => {
|
||||
windowSpy.mockRestore();
|
||||
});
|
||||
it('sets a default when deleting the last answer', () => {
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: 'mock-editors',
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: 'empty',
|
||||
};
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
correctAnswerCount: 0,
|
||||
answers: [{ id: 'A', correct: false }],
|
||||
},
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
correctAnswerCount: 0,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
title: '',
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
correct: false,
|
||||
isAnswerRange: false,
|
||||
}],
|
||||
});
|
||||
});
|
||||
it('sets answers and correctAnswerCount', () => {
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: 'mock-editors',
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: {
|
||||
answers: { A: 'mockA' },
|
||||
},
|
||||
};
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: false,
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
correct: true,
|
||||
}],
|
||||
answers: [
|
||||
{ id: 'A', correct: false },
|
||||
{ id: 'B', correct: true },
|
||||
],
|
||||
},
|
||||
actions.deleteAnswer(answer),
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [
|
||||
{
|
||||
id: 'A',
|
||||
correct: true,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: true,
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
}],
|
||||
});
|
||||
});
|
||||
it('sets answers and correctAnswerCount with editorState for RichTextProblems', () => {
|
||||
const setContent = jest.fn();
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: {
|
||||
'answer-A': { setContent },
|
||||
'answer-B': { setContent },
|
||||
},
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: {
|
||||
answers: { A: 'editorAnsA', B: 'editorAnsB' },
|
||||
},
|
||||
};
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
problemType: ProblemTypeKeys.SINGLESELECT,
|
||||
correctAnswerCount: 1,
|
||||
answers: [
|
||||
{ id: 'A', correct: false },
|
||||
{ id: 'B', correct: true },
|
||||
],
|
||||
},
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
problemType: ProblemTypeKeys.SINGLESELECT,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: true,
|
||||
title: 'editorAnsB',
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
}],
|
||||
});
|
||||
});
|
||||
it('sets selectedFeedback and unselectedFeedback with editorState', () => {
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: {
|
||||
'answer-A': 'mockEditor',
|
||||
'answer-B': 'mockEditor',
|
||||
},
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: {
|
||||
answers: { A: 'editorAnsA', B: 'editorAnsB' },
|
||||
selectedFeedback: { A: 'editSelFA', B: 'editSelFB' },
|
||||
unselectedFeedback: { A: 'editUnselFA', B: 'editUnselFB' },
|
||||
},
|
||||
};
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [
|
||||
{ id: 'A', correct: false },
|
||||
{ id: 'B', correct: true },
|
||||
],
|
||||
},
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: true,
|
||||
selectedFeedback: 'editSelFB',
|
||||
unselectedFeedback: 'editUnselFB',
|
||||
}],
|
||||
});
|
||||
});
|
||||
it('calls editor setContent to set answer and feedback fields', () => {
|
||||
const setContent = jest.fn();
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: {
|
||||
'answer-A': { setContent },
|
||||
'answer-B': { setContent },
|
||||
'selectedFeedback-A': { setContent },
|
||||
'selectedFeedback-B': { setContent },
|
||||
'unselectedFeedback-A': { setContent },
|
||||
'unselectedFeedback-B': { setContent },
|
||||
},
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: {
|
||||
answers: { A: 'editorAnsA', B: 'editorAnsB' },
|
||||
selectedFeedback: { A: 'editSelFA', B: 'editSelFB' },
|
||||
unselectedFeedback: { A: 'editUnselFA', B: 'editUnselFB' },
|
||||
},
|
||||
};
|
||||
reducer(
|
||||
{
|
||||
...testingState,
|
||||
problemType: ProblemTypeKeys.SINGLESELECT,
|
||||
correctAnswerCount: 1,
|
||||
answers: [
|
||||
{ id: 'A', correct: false },
|
||||
{ id: 'B', correct: true },
|
||||
],
|
||||
},
|
||||
actions.deleteAnswer(payload),
|
||||
);
|
||||
expect(window.tinymce.editors['answer-A'].setContent).toHaveBeenCalled();
|
||||
expect(window.tinymce.editors['answer-A'].setContent).toHaveBeenCalledWith('editorAnsB');
|
||||
expect(window.tinymce.editors['selectedFeedback-A'].setContent).toHaveBeenCalledWith('editSelFB');
|
||||
expect(window.tinymce.editors['unselectedFeedback-A'].setContent).toHaveBeenCalledWith('editUnselFB');
|
||||
});
|
||||
it('sets groupFeedbackList by removing the checked item in the groupFeedback', () => {
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: 'mock-editors',
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
editorState: {
|
||||
answer: { A: 'aNSwERA', B: 'anSWeRB' },
|
||||
},
|
||||
};
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [
|
||||
{ id: 'A', correct: false },
|
||||
{ id: 'B', correct: true },
|
||||
{ id: 'C', correct: false },
|
||||
],
|
||||
groupFeedbackList: [{
|
||||
id: 0,
|
||||
answers: ['A', 'C'],
|
||||
feedback: 'fake feedback',
|
||||
}],
|
||||
},
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: true,
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
},
|
||||
{
|
||||
id: 'B',
|
||||
correct: false,
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
}],
|
||||
groupFeedbackList: [{
|
||||
id: 0,
|
||||
answers: ['B'],
|
||||
feedback: 'fake feedback',
|
||||
}],
|
||||
});
|
||||
});
|
||||
it('if you delete an answer range, it will be replaced with a blank answer', () => {
|
||||
const answer = {
|
||||
windowSpy.mockImplementation(() => ({
|
||||
tinymce: {
|
||||
editors: 'mock-editors',
|
||||
},
|
||||
}));
|
||||
const payload = {
|
||||
id: 'A',
|
||||
correct: true,
|
||||
selectedFeedback: '',
|
||||
title: '',
|
||||
isAnswerRange: false,
|
||||
unselectedFeedback: '',
|
||||
editorState: 'mockEditoRStAte',
|
||||
};
|
||||
const answerRange = {
|
||||
id: 'A',
|
||||
correct: false,
|
||||
selectedFeedback: '',
|
||||
title: '',
|
||||
isAnswerRange: true,
|
||||
unselectedFeedback: '',
|
||||
};
|
||||
|
||||
expect(reducer(
|
||||
{
|
||||
...testingState,
|
||||
problemType: ProblemTypeKeys.NUMERIC,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{ ...answerRange }],
|
||||
answers: [{
|
||||
id: 'A',
|
||||
correct: false,
|
||||
selectedFeedback: '',
|
||||
title: '',
|
||||
isAnswerRange: true,
|
||||
unselectedFeedback: '',
|
||||
}],
|
||||
},
|
||||
actions.deleteAnswer(answer),
|
||||
actions.deleteAnswer(payload),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
problemType: ProblemTypeKeys.NUMERIC,
|
||||
correctAnswerCount: 1,
|
||||
answers: [{ ...answer }],
|
||||
answers: [{
|
||||
id: 'A',
|
||||
title: '',
|
||||
selectedFeedback: '',
|
||||
unselectedFeedback: '',
|
||||
correct: true,
|
||||
isAnswerRange: false,
|
||||
}],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,8 +152,6 @@ export const setupCustomBehavior = ({
|
||||
updateContent,
|
||||
});
|
||||
});
|
||||
// TODO: consider using tinyMCE onblur for all react state updates
|
||||
editor.on('blur', () => updateContent(editor.getContent()));
|
||||
}
|
||||
editor.on('ExecCommand', (e) => {
|
||||
if (editorType === 'text' && e.command === 'mceFocus') {
|
||||
|
||||
Reference in New Issue
Block a user