Skip to content

Commit e4e1acf

Browse files
author
Ben Warzeski
authored
Merge pull request #163 from openedx/bw/documentation
fix: feedback only criteria in readonly assessment
2 parents 0f5be69 + 0263fcc commit e4e1acf

File tree

2 files changed

+122
-9
lines changed

2 files changed

+122
-9
lines changed

src/components/Assessment/ReadonlyAssessment/AssessmentCriteria.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const AssessmentCriteria = ({ criteria, overallFeedback, stepLabel }) => {
1414
<>
1515
{criteriaConfig.map((rubricCriterion, i) => {
1616
const { selectedOption, feedback } = criteria[i];
17-
const option = rubricCriterion.options[selectedOption];
17+
const option = rubricCriterion.options[selectedOption] || {};
1818
const commentHeader = stepLabel
1919
? formatMessage(messages.stepComments, { step: stepLabel })
2020
: null;

src/hooks/assessment.test.js

Lines changed: 121 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
// import React from 'react';
1+
import React from 'react';
22
import { when } from 'jest-when';
33

4+
import { getEffects } from '@edx/react-unit-test-utils';
5+
46
import { stepNames } from 'constants/index';
57

68
import * as reduxHooks from 'data/redux/hooks';
@@ -13,21 +15,26 @@ import * as exported from './assessment';
1315
const { hooks } = exported;
1416

1517
jest.mock('data/redux/hooks', () => ({
16-
useCriterionOption: jest.fn(),
17-
useSetCriterionOption: jest.fn(),
18-
useSetShowTrainingError: jest.fn(),
1918
useCriterionFeedback: jest.fn(),
20-
useSetCriterionFeedback: jest.fn(),
19+
useCriterionOption: jest.fn(),
20+
useFormFields: jest.fn(),
2121
useOverallFeedbackValue: jest.fn(),
22+
useResetAssessment: jest.fn(),
23+
useSetCriterionFeedback: jest.fn(),
24+
useSetCriterionOption: jest.fn(),
25+
useSetFormFields: jest.fn(),
2226
useSetOverallFeedback: jest.fn(),
23-
useFormFields: jest.fn(),
27+
useSetResponse: jest.fn(),
28+
useSetShowTrainingError: jest.fn(),
2429
}));
2530

2631
jest.mock('data/services/lms/hooks/actions', () => ({
2732
}));
2833
jest.mock('data/services/lms/hooks/selectors', () => ({
2934
useCriteriaConfig: jest.fn(),
3035
useStepInfo: jest.fn(),
36+
useEmptyRubric: jest.fn(),
37+
useResponseData: jest.fn(),
3138
}));
3239
jest.mock('./routing', () => ({
3340
useViewStep: jest.fn(),
@@ -51,12 +58,27 @@ const testStepInfo = {
5158
expectedRubricSelections: [1, 2, 3],
5259
},
5360
};
61+
const testResponse = { test: 'response' };
62+
when(lmsSelectors.useResponseData).calledWith().mockReturnValue(testResponse);
63+
const testEmptyRubric = { test: 'empty rubric' };
64+
when(lmsSelectors.useEmptyRubric).calledWith().mockReturnValue(testEmptyRubric);
65+
const setCriterionFeedback = jest.fn();
66+
when(reduxHooks.useSetCriterionFeedback).calledWith().mockReturnValue(setCriterionFeedback);
67+
const setFormFields = jest.fn();
68+
when(reduxHooks.useSetFormFields).calledWith().mockReturnValue(setFormFields);
69+
const setOverallFeedback = jest.fn();
70+
when(reduxHooks.useSetOverallFeedback).calledWith().mockReturnValue(setOverallFeedback);
71+
const setResponse = jest.fn();
72+
when(reduxHooks.useSetResponse).calledWith().mockReturnValue(setResponse);
73+
const reset = jest.fn();
74+
when(reduxHooks.useResetAssessment).calledWith().mockReturnValue(reset);
75+
5476
describe('Assessment hooks', () => {
5577
beforeEach(() => {
5678
jest.clearAllMocks();
5779
});
5880

59-
describe('useCheckTrainingSelection', () => {
81+
describe('useIsTrainingSelectionValid', () => {
6082
const prepHook = ({ assessment = testAssessment, stepInfo = testStepInfo } = {}) => {
6183
when(reduxHooks.useFormFields).calledWith().mockReturnValueOnce(assessment);
6284
when(lmsSelectors.useStepInfo).calledWith().mockReturnValueOnce(stepInfo);
@@ -96,14 +118,39 @@ describe('Assessment hooks', () => {
96118
prepHook();
97119
expect(out).toEqual(true);
98120
});
99-
100121
it('returns false if any of the selected options to not match expected values', () => {
101122
prepHook({ studentTraining: { expectedRubricSelections: [1, 2, 4] } });
102123
expect(out).toEqual(true);
103124
});
104125
});
105126
});
106127
describe('useInitializeAssessment', () => {
128+
const prepHook = () => {
129+
out = hooks.useInitializeAssessment();
130+
};
131+
describe('behavior', () => {
132+
it('loads response, empty rubric, and setters for response and formFields from hooks', () => {
133+
prepHook();
134+
expect(lmsSelectors.useEmptyRubric).toHaveBeenCalledWith();
135+
expect(lmsSelectors.useResponseData).toHaveBeenCalledWith();
136+
expect(reduxHooks.useSetFormFields).toHaveBeenCalledWith();
137+
expect(reduxHooks.useSetResponse).toHaveBeenCalledWith();
138+
});
139+
it('calls setResponse with response on first load', () => {
140+
prepHook();
141+
const [cb] = getEffects([], React);
142+
cb();
143+
expect(setResponse).toHaveBeenCalledWith(testResponse);
144+
});
145+
});
146+
describe('output', () => {
147+
it('returns a static callback that sets form fields to empty rubric', () => {
148+
prepHook();
149+
expect(out.useCallback.prereqs).toEqual([]);
150+
out.useCallback.cb();
151+
expect(setFormFields).toHaveBeenCalledWith(testEmptyRubric);
152+
});
153+
});
107154
});
108155
describe('useIsCriterionFeedbackInvalid', () => {
109156
const prepHook = ({ viewStep, criteriaConfig }) => {
@@ -134,8 +181,46 @@ describe('Assessment hooks', () => {
134181
});
135182
});
136183
describe('useOverallFeedbackFormFields', () => {
184+
const prepHook = () => {
185+
when(reduxHooks.useOverallFeedbackValue).calledWith().mockReturnValueOnce(testValue);
186+
out = hooks.useOverallFeedbackFormFields();
187+
};
188+
describe('behavior', () => {
189+
it('loads value and setter from hooks', () => {
190+
prepHook();
191+
expect(reduxHooks.useOverallFeedbackValue).toHaveBeenCalledWith();
192+
expect(reduxHooks.useSetOverallFeedback).toHaveBeenCalledWith();
193+
});
194+
});
195+
describe('output', () => {
196+
it('returns value and setFeedback event handler', () => {
197+
prepHook();
198+
expect(out.value).toEqual(testValue);
199+
out.onChange({ target: { value: testValue } });
200+
expect(setOverallFeedback).toHaveBeenCalledWith(testValue);
201+
});
202+
});
137203
});
138204
describe('useResetAssessment', () => {
205+
const prepHook = () => {
206+
out = hooks.useResetAssessment();
207+
};
208+
describe('behavior', () => {
209+
it('loads value and setter from hooks', () => {
210+
prepHook();
211+
expect(reduxHooks.useResetAssessment).toHaveBeenCalledWith();
212+
expect(reduxHooks.useSetFormFields).toHaveBeenCalledWith();
213+
expect(lmsSelectors.useEmptyRubric).toHaveBeenCalledWith();
214+
});
215+
});
216+
describe('output', () => {
217+
it('returns value and setFeedback event handler', () => {
218+
prepHook();
219+
out();
220+
expect(reset).toHaveBeenCalled();
221+
expect(setFormFields).toHaveBeenCalledWith(testEmptyRubric);
222+
});
223+
});
139224
});
140225
describe('useTrainingOptionValidity', () => {
141226
const prepHook = ({ value, stepInfo, criterionIndex = 1 }) => {
@@ -174,7 +259,35 @@ describe('Assessment hooks', () => {
174259
});
175260

176261
describe('useCriterionFeedbackFormFields', () => {
262+
const criterionIndex = 3;
263+
const mockIsInvalid = (args) => ({ isInvalid: args });
264+
let spy;
265+
const prepHook = () => {
266+
when(reduxHooks.useCriterionFeedback).calledWith(criterionIndex).mockReturnValueOnce(testValue);
267+
when(reduxHooks.useSetCriterionFeedback).calledWith(criterionIndex).mockReturnValueOnce(setCriterionFeedback);
268+
spy = jest.spyOn(hooks, 'useIsCriterionFeedbackInvalid');
269+
when(spy).calledWith().mockReturnValueOnce(mockIsInvalid);
270+
out = hooks.useCriterionFeedbackFormFields(criterionIndex);
271+
};
272+
describe('behavior', () => {
273+
it('loads value, validity, and setter from hooks', () => {
274+
prepHook();
275+
expect(reduxHooks.useCriterionFeedback).toHaveBeenCalledWith(criterionIndex);
276+
expect(reduxHooks.useSetCriterionFeedback).toHaveBeenCalledWith(criterionIndex);
277+
expect(hooks.useIsCriterionFeedbackInvalid).toHaveBeenCalledWith();
278+
});
279+
});
280+
describe('output', () => {
281+
it('returns value and setFeedback event handler', () => {
282+
prepHook();
283+
expect(out.value).toEqual(testValue);
284+
expect(out.isInvalid).toEqual(mockIsInvalid({ value: testValue, criterionIndex }));
285+
out.onChange({ target: { value: testValue } });
286+
expect(setCriterionFeedback).toHaveBeenCalledWith(testValue);
287+
});
288+
});
177289
});
290+
178291
describe('useCriterionOptionFormFields', () => {
179292
const hook = hooks.useCriterionOptionFormFields;
180293
let spy;

0 commit comments

Comments
 (0)