Merge pull request #11 from muselesscreator/override_flow
Override Grade workflow
This commit is contained in:
@@ -8,11 +8,20 @@ exports[`ReviewActions component component snapshot: do not show rubric 1`] = `
|
||||
<span
|
||||
className="review-actions-username"
|
||||
>
|
||||
test-username
|
||||
<span
|
||||
className="lead"
|
||||
>
|
||||
test-username
|
||||
</span>
|
||||
<StatusBadge
|
||||
className="review-actions-status"
|
||||
className="review-actions-status mr-3"
|
||||
status="grading-status"
|
||||
/>
|
||||
<span
|
||||
className="small"
|
||||
>
|
||||
Score: 3/10
|
||||
</span>
|
||||
</span>
|
||||
<div
|
||||
className="review-actions-group"
|
||||
@@ -31,7 +40,7 @@ exports[`ReviewActions component component snapshot: do not show rubric 1`] = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ReviewActions component component snapshot: show rubric 1`] = `
|
||||
exports[`ReviewActions component component snapshot: show rubric, no score 1`] = `
|
||||
<div>
|
||||
<ActionRow
|
||||
className="review-actions"
|
||||
@@ -39,11 +48,18 @@ exports[`ReviewActions component component snapshot: show rubric 1`] = `
|
||||
<span
|
||||
className="review-actions-username"
|
||||
>
|
||||
test-username
|
||||
<span
|
||||
className="lead"
|
||||
>
|
||||
test-username
|
||||
</span>
|
||||
<StatusBadge
|
||||
className="review-actions-status"
|
||||
className="review-actions-status mr-3"
|
||||
status="grading-status"
|
||||
/>
|
||||
<span
|
||||
className="small"
|
||||
/>
|
||||
</span>
|
||||
<div
|
||||
className="review-actions-group"
|
||||
|
||||
@@ -106,6 +106,7 @@ export class StartGradingButton extends React.Component {
|
||||
isOpen={this.state.showConfirmStopGrading}
|
||||
onCancel={this.hideConfirmStopGrading}
|
||||
onConfirm={this.confirmStopGrading}
|
||||
isOverride={this.props.gradeStatus === statuses.graded}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
@@ -113,12 +114,14 @@ export class StartGradingButton extends React.Component {
|
||||
}
|
||||
|
||||
StartGradingButton.propTypes = {
|
||||
gradeStatus: PropTypes.string.isRequired,
|
||||
gradingStatus: PropTypes.string.isRequired,
|
||||
startGrading: PropTypes.func.isRequired,
|
||||
stopGrading: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export const mapStateToProps = (state) => ({
|
||||
gradeStatus: selectors.grading.selected.gradeStatus(state),
|
||||
gradingStatus: selectors.grading.selected.gradingStatus(state),
|
||||
});
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ jest.mock('data/selectors', () => ({
|
||||
default: {
|
||||
grading: {
|
||||
selected: {
|
||||
gradeStatus: (state) => ({ gradeStatus: state }),
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
},
|
||||
},
|
||||
@@ -38,26 +39,43 @@ describe('StartGradingButton component', () => {
|
||||
props.startGrading = jest.fn().mockName('this.props.startGrading');
|
||||
props.stopGrading = jest.fn().mockName('this.props.stopGrading');
|
||||
});
|
||||
const render = (gradingStatus) => shallow(
|
||||
<StartGradingButton {...props} gradingStatus={gradingStatus} />,
|
||||
);
|
||||
test('snapshot: locked (null)', () => {
|
||||
el = render(statuses.locked);
|
||||
expect(el).toMatchSnapshot();
|
||||
expect(el).toEqual({});
|
||||
});
|
||||
test('snapshot: ungraded (startGrading callback)', () => {
|
||||
expect(render(statuses.ungraded)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: graded, confirmOverride (startGrading callback)', () => {
|
||||
el = render(statuses.graded);
|
||||
el.setState({ showConfirmOverrideGrade: true });
|
||||
expect(el.instance().render()).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: inProgress, confirmStop (stopGrading callback)', () => {
|
||||
el = render(statuses.inProgress);
|
||||
el.setState({ showConfirmStopGrading: true });
|
||||
expect(el.instance().render()).toMatchSnapshot();
|
||||
describe('snapshotes', () => {
|
||||
const mockedEl = (gradingStatus, gradeStatus) => {
|
||||
const renderedEl = shallow(
|
||||
<StartGradingButton
|
||||
{...props}
|
||||
gradingStatus={gradingStatus}
|
||||
gradeStatus={gradeStatus || gradingStatus}
|
||||
/>,
|
||||
);
|
||||
const mockMethod = (methodName) => {
|
||||
renderedEl.instance()[methodName] = jest.fn().mockName(`this.${methodName}`);
|
||||
};
|
||||
mockMethod('handleClick');
|
||||
mockMethod('hideConfirmOverrideGrade');
|
||||
mockMethod('confirmOverrideGrade');
|
||||
mockMethod('hideConfirmStopGrading');
|
||||
mockMethod('confirmStopGrading');
|
||||
return renderedEl;
|
||||
};
|
||||
test('snapshot: locked (null)', () => {
|
||||
el = mockedEl(statuses.locked);
|
||||
expect(el.instance().render()).toMatchSnapshot();
|
||||
expect(el.isEmptyRender()).toEqual(true);
|
||||
});
|
||||
test('snapshot: ungraded (startGrading callback)', () => {
|
||||
expect(mockedEl(statuses.ungraded).instance().render()).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: graded, confirmOverride (startGrading callback)', () => {
|
||||
el = mockedEl(statuses.graded);
|
||||
el.setState({ showConfirmOverrideGrade: true });
|
||||
expect(el.instance().render()).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: inProgress, isOverride, confirmStop (stopGrading callback)', () => {
|
||||
el = mockedEl(statuses.inProgress, statuses.graded);
|
||||
el.setState({ showConfirmStopGrading: true });
|
||||
expect(el.instance().render()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
@@ -66,6 +84,9 @@ describe('StartGradingButton component', () => {
|
||||
beforeEach(() => {
|
||||
mapped = mapStateToProps(testState);
|
||||
});
|
||||
test('gradeStatus loads from grading.selected.gradeStatus', () => {
|
||||
expect(mapped.gradeStatus).toEqual(selectors.grading.selected.gradeStatus(testState));
|
||||
});
|
||||
test('gradingStatus loads from grading.selected.gradingStatus', () => {
|
||||
expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState));
|
||||
});
|
||||
|
||||
@@ -5,14 +5,21 @@ import ConfirmModal from 'components/ConfirmModal';
|
||||
|
||||
export const StopGradingConfirmModal = ({
|
||||
isOpen,
|
||||
isOverride,
|
||||
onCancel,
|
||||
onConfirm,
|
||||
}) => (
|
||||
<ConfirmModal
|
||||
title="Are you sure you want to stop grading this response?"
|
||||
title={(isOverride
|
||||
? 'Are you sure you want to stop grade override?'
|
||||
: 'Are you sure you want to stop grading this response?'
|
||||
)}
|
||||
content="Your progress will be lost."
|
||||
cancelText="Go back"
|
||||
confirmText="Cancel Grading"
|
||||
confirmText={(isOverride
|
||||
? 'Stop grade override'
|
||||
: 'Cancel grading'
|
||||
)}
|
||||
onCancel={onCancel}
|
||||
onConfirm={onConfirm}
|
||||
isOpen={isOpen}
|
||||
@@ -20,6 +27,7 @@ export const StopGradingConfirmModal = ({
|
||||
);
|
||||
StopGradingConfirmModal.propTypes = {
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
isOverride: PropTypes.bool.isRequired,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ jest.mock('components/ConfirmModal', () => 'ConfirmModal');
|
||||
describe('StopGradingConfirmModal', () => {
|
||||
const props = {
|
||||
isOpen: false,
|
||||
isOverride: false,
|
||||
onCancel: jest.fn().mockName('this.props.onCancel'),
|
||||
onConfirm: jest.fn().mockName('this.props.onConfirm'),
|
||||
};
|
||||
@@ -16,4 +17,7 @@ describe('StopGradingConfirmModal', () => {
|
||||
test('snapshot: open', () => {
|
||||
expect(shallow(<StopGradingConfirmModal {...props} isOpen />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: open, isOverride', () => {
|
||||
expect(shallow(<StopGradingConfirmModal {...props} isOverride />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
|
||||
import {
|
||||
SubmissionNavigation,
|
||||
|
||||
@@ -1,69 +1,72 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`StartGradingButton component component snapshot: graded, confirmOverride (startGrading callback) 1`] = `
|
||||
exports[`StartGradingButton component component snapshotes snapshot: graded, confirmOverride (startGrading callback) 1`] = `
|
||||
<React.Fragment>
|
||||
<Button
|
||||
iconAfter="Highlight"
|
||||
onClick={[Function]}
|
||||
onClick={[MockFunction this.handleClick]}
|
||||
variant="primary"
|
||||
>
|
||||
Override grade
|
||||
</Button>
|
||||
<OverrideGradeConfirmModal
|
||||
isOpen={true}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
onCancel={[MockFunction this.hideConfirmOverrideGrade]}
|
||||
onConfirm={[MockFunction this.confirmOverrideGrade]}
|
||||
/>
|
||||
<StopGradingConfirmModal
|
||||
isOpen={false}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
isOverride={true}
|
||||
onCancel={[MockFunction this.hideConfirmStopGrading]}
|
||||
onConfirm={[MockFunction this.confirmStopGrading]}
|
||||
/>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`StartGradingButton component component snapshot: inProgress, confirmStop (stopGrading callback) 1`] = `
|
||||
exports[`StartGradingButton component component snapshotes snapshot: inProgress, isOverride, confirmStop (stopGrading callback) 1`] = `
|
||||
<React.Fragment>
|
||||
<Button
|
||||
iconAfter="Cancel"
|
||||
onClick={[Function]}
|
||||
onClick={[MockFunction this.handleClick]}
|
||||
variant="primary"
|
||||
>
|
||||
Stop grading this response
|
||||
</Button>
|
||||
<OverrideGradeConfirmModal
|
||||
isOpen={false}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
onCancel={[MockFunction this.hideConfirmOverrideGrade]}
|
||||
onConfirm={[MockFunction this.confirmOverrideGrade]}
|
||||
/>
|
||||
<StopGradingConfirmModal
|
||||
isOpen={true}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
isOverride={true}
|
||||
onCancel={[MockFunction this.hideConfirmStopGrading]}
|
||||
onConfirm={[MockFunction this.confirmStopGrading]}
|
||||
/>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
exports[`StartGradingButton component component snapshot: locked (null) 1`] = `""`;
|
||||
exports[`StartGradingButton component component snapshotes snapshot: locked (null) 1`] = `null`;
|
||||
|
||||
exports[`StartGradingButton component component snapshot: ungraded (startGrading callback) 1`] = `
|
||||
<Fragment>
|
||||
exports[`StartGradingButton component component snapshotes snapshot: ungraded (startGrading callback) 1`] = `
|
||||
<React.Fragment>
|
||||
<Button
|
||||
iconAfter="Highlight"
|
||||
onClick={[Function]}
|
||||
onClick={[MockFunction this.handleClick]}
|
||||
variant="primary"
|
||||
>
|
||||
Start Grading
|
||||
</Button>
|
||||
<OverrideGradeConfirmModal
|
||||
isOpen={false}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
onCancel={[MockFunction this.hideConfirmOverrideGrade]}
|
||||
onConfirm={[MockFunction this.confirmOverrideGrade]}
|
||||
/>
|
||||
<StopGradingConfirmModal
|
||||
isOpen={false}
|
||||
onCancel={[Function]}
|
||||
onConfirm={[Function]}
|
||||
isOverride={false}
|
||||
onCancel={[MockFunction this.hideConfirmStopGrading]}
|
||||
onConfirm={[MockFunction this.confirmStopGrading]}
|
||||
/>
|
||||
</Fragment>
|
||||
</React.Fragment>
|
||||
`;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`StopGradingConfirmModal snapshot: closed 1`] = `
|
||||
<ConfirmModal
|
||||
cancelText="Go back"
|
||||
confirmText="Cancel Grading"
|
||||
confirmText="Cancel grading"
|
||||
content="Your progress will be lost."
|
||||
isOpen={false}
|
||||
onCancel={[MockFunction this.props.onCancel]}
|
||||
@@ -15,7 +15,7 @@ exports[`StopGradingConfirmModal snapshot: closed 1`] = `
|
||||
exports[`StopGradingConfirmModal snapshot: open 1`] = `
|
||||
<ConfirmModal
|
||||
cancelText="Go back"
|
||||
confirmText="Cancel Grading"
|
||||
confirmText="Cancel grading"
|
||||
content="Your progress will be lost."
|
||||
isOpen={true}
|
||||
onCancel={[MockFunction this.props.onCancel]}
|
||||
@@ -23,3 +23,15 @@ exports[`StopGradingConfirmModal snapshot: open 1`] = `
|
||||
title="Are you sure you want to stop grading this response?"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`StopGradingConfirmModal snapshot: open, isOverride 1`] = `
|
||||
<ConfirmModal
|
||||
cancelText="Go back"
|
||||
confirmText="Stop grade override"
|
||||
content="Your progress will be lost."
|
||||
isOpen={false}
|
||||
onCancel={[MockFunction this.props.onCancel]}
|
||||
onConfirm={[MockFunction this.props.onConfirm]}
|
||||
title="Are you sure you want to stop grade override?"
|
||||
/>
|
||||
`;
|
||||
|
||||
@@ -17,14 +17,18 @@ import SubmissionNavigation from './components/SubmissionNavigation';
|
||||
export const ReviewActions = ({
|
||||
gradingStatus,
|
||||
toggleShowRubric,
|
||||
score: { pointsEarned, pointsPossible },
|
||||
showRubric,
|
||||
username,
|
||||
}) => (
|
||||
<div>
|
||||
<ActionRow className="review-actions">
|
||||
<span className="review-actions-username">
|
||||
{username}
|
||||
<StatusBadge className="review-actions-status" status={gradingStatus} />
|
||||
<span className="lead">{username}</span>
|
||||
<StatusBadge className="review-actions-status mr-3" status={gradingStatus} />
|
||||
<span className="small">
|
||||
{pointsPossible && `Score: ${pointsEarned}/${pointsPossible}`}
|
||||
</span>
|
||||
</span>
|
||||
<div className="review-actions-group">
|
||||
<Button variant="outline-primary" onClick={toggleShowRubric}>
|
||||
@@ -39,6 +43,10 @@ export const ReviewActions = ({
|
||||
ReviewActions.propTypes = {
|
||||
gradingStatus: PropTypes.string.isRequired,
|
||||
username: PropTypes.string.isRequired,
|
||||
score: PropTypes.shape({
|
||||
pointsEarned: PropTypes.number,
|
||||
pointsPossible: PropTypes.number,
|
||||
}).isRequired,
|
||||
showRubric: PropTypes.bool.isRequired,
|
||||
toggleShowRubric: PropTypes.func.isRequired,
|
||||
};
|
||||
@@ -46,6 +54,7 @@ ReviewActions.propTypes = {
|
||||
export const mapStateToProps = (state) => ({
|
||||
username: selectors.grading.selected.username(state),
|
||||
gradingStatus: selectors.grading.selected.gradingStatus(state),
|
||||
score: selectors.grading.selected.score(state),
|
||||
showRubric: selectors.app.showRubric(state),
|
||||
});
|
||||
|
||||
|
||||
@@ -16,8 +16,9 @@ jest.mock('data/selectors', () => ({
|
||||
app: { showRubric: (state) => ({ showRubric: state }) },
|
||||
grading: {
|
||||
selected: {
|
||||
username: (state) => ({ username: state }),
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
score: (state) => ({ score: state }),
|
||||
username: (state) => ({ username: state }),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -32,6 +33,7 @@ describe('ReviewActions component', () => {
|
||||
gradingStatus: 'grading-status',
|
||||
username: 'test-username',
|
||||
showRubric: false,
|
||||
score: { pointsEarned: 3, pointsPossible: 10 },
|
||||
};
|
||||
beforeEach(() => {
|
||||
props.toggleShowRubric = jest.fn().mockName('this.props.toggleShowRubric');
|
||||
@@ -39,8 +41,8 @@ describe('ReviewActions component', () => {
|
||||
test('snapshot: do not show rubric', () => {
|
||||
expect(shallow(<ReviewActions {...props} />)).toMatchSnapshot();
|
||||
});
|
||||
test('snapshot: show rubric', () => {
|
||||
expect(shallow(<ReviewActions {...props} showRubric />)).toMatchSnapshot();
|
||||
test('snapshot: show rubric, no score', () => {
|
||||
expect(shallow(<ReviewActions {...props} showRubric score={{}} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
describe('mapStateToProps', () => {
|
||||
@@ -55,6 +57,9 @@ describe('ReviewActions component', () => {
|
||||
test('gradingStatus loads from grading.selected.gradingStatus', () => {
|
||||
expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState));
|
||||
});
|
||||
test('score loads from grading.selected.score', () => {
|
||||
expect(mapped.score).toEqual(selectors.grading.selected.score(testState));
|
||||
});
|
||||
test('showRubric loads from app.showRubric', () => {
|
||||
expect(mapped.showRubric).toEqual(selectors.app.showRubric(testState));
|
||||
});
|
||||
|
||||
@@ -103,12 +103,20 @@ const app = createReducer(initialState, {
|
||||
prev: state.current,
|
||||
current: { response: state.next.response, ...payload },
|
||||
activeIndex: state.activeIndex + 1,
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[payload.submissionId]: payload.gradeData,
|
||||
},
|
||||
next: null,
|
||||
}),
|
||||
[actions.grading.loadPrev]: (state, { payload }) => ({
|
||||
...state,
|
||||
next: state.current,
|
||||
current: { response: state.prev.response, ...payload },
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[payload.submissionId]: payload.gradeData,
|
||||
},
|
||||
activeIndex: state.activeIndex - 1,
|
||||
prev: null,
|
||||
}),
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
import { createSelector } from 'reselect';
|
||||
|
||||
import { feedbackRequirement } from 'data/services/lms/constants';
|
||||
|
||||
// import * in order to mock in-file references
|
||||
import * as selectors from './app';
|
||||
// import default export in order to test simpleSelectors not exported individually
|
||||
import exportedSelectors from './app';
|
||||
|
||||
jest.mock('reselect', () => ({
|
||||
createSelector: jest.fn((preSelectors, cb) => ({ preSelectors, cb })),
|
||||
|
||||
@@ -33,8 +33,12 @@ export const selected = {};
|
||||
* @return {string} selected submission id
|
||||
*/
|
||||
selected.submissionId = createSelector(
|
||||
[module.simpleSelectors.selected, submissionsSelectors.allSubmissions],
|
||||
(selectedIds, submissions) => submissions[selectedIds[0]].submissionId,
|
||||
[
|
||||
module.simpleSelectors.selected,
|
||||
submissionsSelectors.allSubmissions,
|
||||
module.simpleSelectors.activeIndex,
|
||||
],
|
||||
(selectedIds, submissions, activeIndex) => submissions[selectedIds[activeIndex]].submissionId,
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -125,6 +129,15 @@ selected.criteriaGradeData = createSelector(
|
||||
(data) => (data ? data.criteria : []),
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the score object associated with the grade
|
||||
* @return {obj} score object
|
||||
*/
|
||||
selected.score = createSelector(
|
||||
[module.selected.gradeData],
|
||||
(data) => ((data && data.score) ? data.score : {}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the rubric-level feedback for the selected submission
|
||||
* @return {string} selected submission's associated rubric-level feedback
|
||||
|
||||
Reference in New Issue
Block a user