@@ -5,7 +5,7 @@ import { BrowserRouter as Router } from 'react-router-dom';
|
||||
|
||||
import Footer from '@edx/frontend-component-footer';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
|
||||
import ListView from 'containers/ListView';
|
||||
import './App.scss';
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Form } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { feedbackRequirement } from 'data/services/lms/constants';
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import messages from './messages';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import {
|
||||
feedbackRequirement,
|
||||
gradeStatuses,
|
||||
@@ -20,24 +19,19 @@ jest.mock('@edx/paragon', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
rubric: {
|
||||
criterionFeedbackConfig: jest.fn((...args) => ({
|
||||
rubricCriterionFeedbackConfig: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
grading: {
|
||||
selected: {
|
||||
criterionFeedback: jest.fn((...args) => ({
|
||||
selectedCriterionFeedback: args,
|
||||
})),
|
||||
gradeStatus: jest.fn((...args) => ({ selectedGradeStatus: args })),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
rubric: {
|
||||
criterionFeedbackConfig: jest.fn((...args) => ({
|
||||
rubricCriterionFeedbackConfig: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
criterionFeedback: jest.fn((...args) => ({
|
||||
selectedCriterionFeedback: args,
|
||||
})),
|
||||
gradeStatus: jest.fn((...args) => ({ selectedGradeStatus: args })),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { Form } from '@edx/paragon';
|
||||
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import messages from './messages';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import { formatMessage } from 'testUtils';
|
||||
import {
|
||||
RadioCriterion,
|
||||
@@ -17,23 +16,18 @@ jest.mock('@edx/paragon', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
grading: {
|
||||
selected: {
|
||||
criterionGradeData: jest.fn((...args) => ({
|
||||
selectedCriterionGradeData: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
criterionGradeData: jest.fn((...args) => ({
|
||||
selectedCriterionGradeData: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { Form, FormControlFeedback } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import messages from './messages';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { ReviewCriterion, mapStateToProps } from './ReviewCriterion';
|
||||
import messages from './messages';
|
||||
|
||||
@@ -12,23 +12,18 @@ jest.mock('@edx/paragon', () => ({
|
||||
FormControlFeedback: () => 'FormControlFeedback',
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
grading: {
|
||||
selected: {
|
||||
criterionGradeData: jest.fn((...args) => ({
|
||||
selectedCriterionGradeData: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
criterionGradeData: jest.fn((...args) => ({
|
||||
selectedCriterionGradeData: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { connect } from 'react-redux';
|
||||
|
||||
import { Form } from '@edx/paragon';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { gradeStatuses } from 'data/services/lms/constants';
|
||||
|
||||
import InfoPopover from 'components/InfoPopover';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { gradeStatuses } from 'data/services/lms/constants';
|
||||
|
||||
import { CriterionContainer, mapStateToProps } from '.';
|
||||
@@ -18,21 +18,16 @@ jest.mock('@edx/paragon', () => ({
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
grading: {
|
||||
selected: {
|
||||
gradeStatus: jest.fn((...args) => ({ selectedGradeStatus: args })),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
rubric: {
|
||||
criterionConfig: jest.fn((...args) => ({
|
||||
rubricCriterionConfig: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
gradeStatus: jest.fn((...args) => ({ selectedGradeStatus: args })),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ArrowBack, Launch } from '@edx/paragon/icons';
|
||||
import { Hyperlink, Icon } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { locationId } from 'data/constants/app';
|
||||
import urls from 'data/services/lms/urls';
|
||||
import messages from './messages';
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
|
||||
import * as constants from 'data/constants/app';
|
||||
import urls from 'data/services/lms/urls';
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
|
||||
import {
|
||||
ListViewBreadcrumb,
|
||||
@@ -23,15 +23,10 @@ jest.mock('@edx/paragon/icons', () => ({
|
||||
Launch: 'icons.Launch',
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
courseId: (...args) => ({ courseId: args }),
|
||||
ora: {
|
||||
name: (...args) => ({ oraName: args }),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
courseId: (...args) => ({ courseId: args }),
|
||||
ora: {
|
||||
name: (...args) => ({ oraName: args }),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { gradingStatuses } from 'data/services/lms/constants';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import lmsMessages from 'data/services/lms/messages';
|
||||
|
||||
import StatusBadge from 'components/StatusBadge';
|
||||
|
||||
@@ -7,8 +7,7 @@ import {
|
||||
TextFilter,
|
||||
} from '@edx/paragon';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
|
||||
import StatusBadge from 'components/StatusBadge';
|
||||
@@ -38,13 +37,20 @@ jest.mock('components/StatusBadge', () => 'StatusBadge');
|
||||
jest.mock('containers/ReviewModal', () => 'ReviewModal');
|
||||
jest.mock('./ListViewBreadcrumb', () => 'ListViewBreadcrumb');
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
jest.mock('data/redux', () => ({
|
||||
selectors: {
|
||||
submissions: {
|
||||
listData: (...args) => ({ listData: args }),
|
||||
},
|
||||
},
|
||||
thunkActions: {
|
||||
app: {
|
||||
initialize: (...args) => ({ initialize: args }),
|
||||
},
|
||||
grading: {
|
||||
loadSelectionForReview: (...args) => ({ loadSelectionForReview: args }),
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
let el;
|
||||
|
||||
@@ -8,7 +8,7 @@ import createDOMPurify from 'dompurify';
|
||||
|
||||
import parse from 'html-react-parser';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { fileUploadResponseOptions } from 'data/services/lms/constants';
|
||||
|
||||
import SubmissionFiles from './SubmissionFiles';
|
||||
|
||||
@@ -4,8 +4,8 @@ import { shallow } from 'enzyme';
|
||||
import createDOMPurify from 'dompurify';
|
||||
import parse from 'html-react-parser';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { fileUploadResponseOptions } from 'data/services/lms/constants';
|
||||
import { selectors } from 'data/redux';
|
||||
|
||||
import { ResponseDisplay, mapStateToProps } from '.';
|
||||
|
||||
@@ -17,9 +17,8 @@ jest.mock('@edx/paragon', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
jest.mock('data/redux', () => ({
|
||||
selectors: {
|
||||
grading: {
|
||||
selected: {
|
||||
response: (state) => ({ response: state }),
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Button } from '@edx/paragon';
|
||||
import { Cancel, Highlight } from '@edx/paragon/icons';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
|
||||
import StopGradingConfirmModal from './StopGradingConfirmModal';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
|
||||
import {
|
||||
@@ -18,15 +17,10 @@ jest.mock('@edx/paragon/icons', () => ({
|
||||
Cancel: 'Cancel',
|
||||
Highlight: 'Highlight',
|
||||
}));
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
grading: {
|
||||
selected: {
|
||||
gradeStatus: (state) => ({ gradeStatus: state }),
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
gradeStatus: (state) => ({ gradeStatus: state }),
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
},
|
||||
}));
|
||||
jest.mock('./OverrideGradeConfirmModal', () => 'OverrideGradeConfirmModal');
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Icon, IconButton } from '@edx/paragon';
|
||||
import { ChevronLeft, ChevronRight } from '@edx/paragon/icons';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
import messages from './messages';
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import thunkActions from 'data/thunkActions';
|
||||
import { selectors, thunkActions } from 'data/redux';
|
||||
|
||||
import { formatMessage } from 'testUtils';
|
||||
|
||||
@@ -20,20 +19,15 @@ jest.mock('@edx/paragon/icons', () => ({
|
||||
ChevronLeft: 'ChevronLeft',
|
||||
ChevronRight: 'ChevronRight',
|
||||
}));
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
grading: {
|
||||
prev: {
|
||||
doesExist: (state) => ({ prevDoesExist: state }),
|
||||
},
|
||||
next: {
|
||||
doesExist: (state) => ({ nextDoesExist: state }),
|
||||
},
|
||||
activeIndex: (state) => ({ activeIndex: state }),
|
||||
selectionLength: (state) => ({ selectionlength: state }),
|
||||
},
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
prev: {
|
||||
doesExist: (state) => ({ prevDoesExist: state }),
|
||||
},
|
||||
next: {
|
||||
doesExist: (state) => ({ nextDoesExist: state }),
|
||||
},
|
||||
activeIndex: (state) => ({ activeIndex: state }),
|
||||
selectionLength: (state) => ({ selectionlength: state }),
|
||||
}));
|
||||
|
||||
describe('SubmissionNavigation component', () => {
|
||||
|
||||
@@ -5,8 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { ActionRow, Button } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
|
||||
import StatusBadge from 'components/StatusBadge';
|
||||
import StartGradingButton from './components/StartGradingButton';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
|
||||
import { ReviewActions, mapStateToProps, mapDispatchToProps } from '.';
|
||||
|
||||
@@ -10,17 +9,14 @@ jest.mock('@edx/paragon', () => ({
|
||||
ActionRow: () => 'ActionRow',
|
||||
Button: () => 'Button',
|
||||
}));
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: { showRubric: (state) => ({ showRubric: state }) },
|
||||
grading: {
|
||||
selected: {
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
score: (state) => ({ score: state }),
|
||||
username: (state) => ({ username: state }),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
showRubric: (state) => ({ showRubric: state }),
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
gradingStatus: (state) => ({ gradingStatus: state }),
|
||||
score: (state) => ({ score: state }),
|
||||
username: (state) => ({ username: state }),
|
||||
},
|
||||
}));
|
||||
jest.mock('components/StatusBadge', () => 'StatusBadge');
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
Col,
|
||||
} from '@edx/paragon';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import actions from 'data/actions';
|
||||
import { selectors, actions } from 'data/redux';
|
||||
|
||||
import ResponseDisplay from 'containers/ResponseDisplay';
|
||||
import Rubric from 'containers/Rubric';
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
|
||||
.popover.overlay-help-popover {
|
||||
z-index: 4000;
|
||||
margin-right: map-get($spacers, 1) !important;
|
||||
.help-popover-option {
|
||||
margin-bottom: map-get($spacers, 1);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@ import { Form } from '@edx/paragon';
|
||||
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import { feedbackRequirement } from 'data/services/lms/constants';
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import InfoPopover from 'components/InfoPopover';
|
||||
|
||||
import messages from './messages';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import {
|
||||
feedbackRequirement,
|
||||
gradeStatuses,
|
||||
@@ -27,27 +26,22 @@ jest.mock('@edx/paragon', () => {
|
||||
return { Form };
|
||||
});
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
isGrading: jest.fn((...args) => ({ isGragrding: args })),
|
||||
rubric: {
|
||||
feedbackConfig: jest.fn((...args) => ({
|
||||
rubricFeedbackConfig: args,
|
||||
})),
|
||||
feedbackPrompt: jest.fn((...args) => ({
|
||||
rubricFeedbackPrompt: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
grading: {
|
||||
selected: {
|
||||
overallFeedback: jest.fn((...args) => ({
|
||||
selectedOverallFeedback: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
isGrading: jest.fn((...args) => ({ isGragrding: args })),
|
||||
rubric: {
|
||||
feedbackConfig: jest.fn((...args) => ({
|
||||
rubricFeedbackConfig: args,
|
||||
})),
|
||||
feedbackPrompt: jest.fn((...args) => ({
|
||||
rubricFeedbackPrompt: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
selected: {
|
||||
overallFeedback: jest.fn((...args) => ({
|
||||
selectedOverallFeedback: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -14,7 +14,9 @@ exports[`Rubric Container snapshot is grading 1`] = `
|
||||
id="ora-grading.Rubric.rubric"
|
||||
/>
|
||||
</h3>
|
||||
<hr />
|
||||
<hr
|
||||
className="m-2.5"
|
||||
/>
|
||||
<CriterionContainer
|
||||
isGrading={true}
|
||||
key="1"
|
||||
@@ -71,7 +73,9 @@ exports[`Rubric Container snapshot is not grading 1`] = `
|
||||
id="ora-grading.Rubric.rubric"
|
||||
/>
|
||||
</h3>
|
||||
<hr />
|
||||
<hr
|
||||
className="m-2.5"
|
||||
/>
|
||||
<CriterionContainer
|
||||
isGrading={false}
|
||||
key="1"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { connect } from 'react-redux';
|
||||
import { Card, Button } from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
|
||||
import CriterionContainer from 'containers/CriterionContainer';
|
||||
import RubricFeedback from './RubricFeedback';
|
||||
@@ -20,7 +20,7 @@ export const Rubric = ({ isGrading, criteriaIndices }) => (
|
||||
<Card className="grading-rubric-card">
|
||||
<Card.Body className="grading-rubric-body">
|
||||
<h3><FormattedMessage {...messages.rubric} /></h3>
|
||||
<hr />
|
||||
<hr className="m-2.5" />
|
||||
{criteriaIndices.map((index) => (
|
||||
<CriterionContainer
|
||||
isGrading={isGrading}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import selectors from 'data/selectors';
|
||||
import { selectors } from 'data/redux';
|
||||
import { Rubric, mapStateToProps } from '.';
|
||||
|
||||
jest.mock('containers/CriterionContainer', () => 'CriterionContainer');
|
||||
@@ -14,17 +14,12 @@ jest.mock('@edx/paragon', () => {
|
||||
return { Button, Card };
|
||||
});
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
isGrading: jest.fn((...args) => ({ isGragrding: args })),
|
||||
rubric: {
|
||||
criteriaIndices: jest.fn((...args) => ({
|
||||
rubricCriteriaIndices: args,
|
||||
})),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
isGrading: jest.fn((...args) => ({ isGragrding: args })),
|
||||
rubric: {
|
||||
criteriaIndices: jest.fn((...args) => ({
|
||||
rubricCriteriaIndices: args,
|
||||
})),
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createActionFactory } from './utils';
|
||||
|
||||
export const dataKey = 'app';
|
||||
const createAction = createActionFactory(dataKey);
|
||||
|
||||
export const loadCourseMetadata = createAction('loadCourseMetadata');
|
||||
export const loadOraMetadata = createAction('loadOraMetadata');
|
||||
export const setGrading = createAction('setGrading');
|
||||
export const setShowReview = createAction('setShowReview');
|
||||
export const toggleShowRubric = createAction('toggleShowRubric');
|
||||
|
||||
export default StrictDict({
|
||||
loadCourseMetadata,
|
||||
loadOraMetadata,
|
||||
setGrading,
|
||||
setShowReview,
|
||||
toggleShowRubric,
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
import actions, { dataKey } from './app';
|
||||
import { testAction, testActionTypes } from './testUtils';
|
||||
|
||||
describe('actions', () => {
|
||||
describe('action types', () => {
|
||||
const actionTypes = [
|
||||
actions.loadCourseMetadata,
|
||||
actions.loadOraMetadata,
|
||||
actions.setGrading,
|
||||
actions.setShowReview,
|
||||
actions.toggleShowRubric,
|
||||
].map(action => action.toString());
|
||||
testActionTypes(actionTypes, dataKey);
|
||||
});
|
||||
describe('app actions provided', () => {
|
||||
test('loadCourseMetadata action', () => testAction(actions.loadCourseMetadata));
|
||||
test('loadOraMetadata action', () => testAction(actions.loadOraMetadata));
|
||||
test('setGrading action', () => testAction(actions.setGrading));
|
||||
test('setShowReview action', () => testAction(actions.setShowReview));
|
||||
test('toggleShowRubric action', () => testAction(actions.toggleShowRubric));
|
||||
});
|
||||
});
|
||||
@@ -1,95 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createActionFactory } from './utils';
|
||||
|
||||
export const dataKey = 'grading';
|
||||
const createAction = createActionFactory(dataKey);
|
||||
|
||||
/**
|
||||
* Load the first of the selected submission list for review, and initializes
|
||||
* the review pane to the first index.
|
||||
* @param {obj} submission data for the review/grading view
|
||||
* {
|
||||
* {obj} response - api response data
|
||||
* {obj} gradeData - api grade data
|
||||
* {str} status - api grade status
|
||||
* }
|
||||
*/
|
||||
const loadSubmission = createAction('loadSubmission');
|
||||
|
||||
/**
|
||||
* Pre-load just the static info about the "next" submission in the review queue.
|
||||
* Load submission and the learner's response.
|
||||
* @param {obj} submission ({ response })
|
||||
*/
|
||||
const preloadNext = createAction('preloadNext');
|
||||
|
||||
/**
|
||||
* Pre-load just the static info about the "previous" submission in the review queue.
|
||||
* Load submission and the learner's response.
|
||||
* @param {obj} submission ({ response })
|
||||
*/
|
||||
const preloadPrev = createAction('preloadPrev');
|
||||
|
||||
/**
|
||||
* Load the "next" submission in the selected queue as the current selection, load its current
|
||||
* status and grade data, and update prev/next accordingly.
|
||||
* @param {obj} { status, gradeData }
|
||||
*/
|
||||
const loadNext = createAction('loadNext');
|
||||
|
||||
/**
|
||||
* Load the "prev" submission in the selected queue as the current selection, load its current
|
||||
* status and grade data, and update prev/next accordingly.
|
||||
* @param {obj} { status, gradeData }
|
||||
*/
|
||||
const loadPrev = createAction('loadPrev');
|
||||
|
||||
/**
|
||||
* Load the selected submissions, storing their static data in an ordered array and setting the starting
|
||||
* index at the beginning of the list.
|
||||
* @param {obj[]} selection - ordered array of submission static data for all selected submissions
|
||||
*/
|
||||
const updateSelection = createAction('updateSelection');
|
||||
|
||||
// TODO: implement/design data workflow
|
||||
const rubric = StrictDict({
|
||||
/*
|
||||
* update the local version of the rubric-level comment
|
||||
* @param {string} comment
|
||||
*/
|
||||
updateComment: createAction('rubric/comment'),
|
||||
/*
|
||||
* update the local version of points for the given criterion
|
||||
* @param {number} index
|
||||
* @param {number} points
|
||||
*/
|
||||
updateCriterionPoints: createAction('rubric/criterionPoints'),
|
||||
/*
|
||||
* update the local version of comment for the given criterion
|
||||
* @param {number} index
|
||||
* @param {string} comments
|
||||
*/
|
||||
updateCriterionComment: createAction('rubric/criterionComment'),
|
||||
});
|
||||
|
||||
export const startGrading = createAction('grading/start');
|
||||
export const setRubricFeedback = createAction('grading/setRubricFeedback');
|
||||
export const setCriterionFeedback = createAction('grading/setCriterionFeedback');
|
||||
export const setCriterionOption = createAction('grading/setCriterionOption');
|
||||
export const clearGrade = createAction('grading/clear');
|
||||
|
||||
export default StrictDict({
|
||||
loadSubmission,
|
||||
preloadNext,
|
||||
preloadPrev,
|
||||
loadNext,
|
||||
loadPrev,
|
||||
updateSelection,
|
||||
rubric,
|
||||
|
||||
startGrading,
|
||||
setRubricFeedback,
|
||||
setCriterionFeedback,
|
||||
setCriterionOption,
|
||||
clearGrade,
|
||||
});
|
||||
@@ -1,36 +0,0 @@
|
||||
import actions, { dataKey } from './grading';
|
||||
import { testAction, testActionTypes } from './testUtils';
|
||||
|
||||
describe('actions', () => {
|
||||
describe('action types', () => {
|
||||
const actionTypes = [
|
||||
actions.loadSubmission,
|
||||
actions.preloadNext,
|
||||
actions.loadNext,
|
||||
actions.loadPrev,
|
||||
actions.updateSelection,
|
||||
actions.rubric.updateComment,
|
||||
actions.rubric.updateCriterionPoints,
|
||||
actions.rubric.updateCriterionComment,
|
||||
actions.startGrading,
|
||||
actions.setRubricFeedback,
|
||||
actions.setCriterionFeedback,
|
||||
actions.clearGrade,
|
||||
].map(action => action.toString());
|
||||
testActionTypes(actionTypes, dataKey);
|
||||
});
|
||||
describe('grading actions provided', () => {
|
||||
test('loadSubmission action', () => testAction(actions.loadSubmission));
|
||||
test('preloadNext action', () => testAction(actions.preloadNext));
|
||||
test('loadNext action', () => testAction(actions.loadNext));
|
||||
test('loadPrev action', () => testAction(actions.loadPrev));
|
||||
test('updateSelection action', () => testAction(actions.updateSelection));
|
||||
test('rubric updateComment action', () => testAction(actions.rubric.updateComment));
|
||||
test('rubric updateCritrionPoints action', () => testAction(actions.rubric.updateCriterionPoints));
|
||||
test('rubric updateCriterionComment action', () => testAction(actions.rubric.updateCriterionComment));
|
||||
test('startGrading action', () => testAction(actions.startGrading));
|
||||
test('setRubricFeedback action', () => testAction(actions.setRubricFeedback));
|
||||
test('setCriterionFeedback action', () => testAction(actions.setCriterionFeedback));
|
||||
test('clearGrade action', () => testAction(actions.clearGrade));
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import app from './app';
|
||||
import grading from './grading';
|
||||
import requests from './requests';
|
||||
import submissions from './submissions';
|
||||
|
||||
export default StrictDict({
|
||||
app,
|
||||
grading,
|
||||
requests,
|
||||
submissions,
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createActionFactory } from './utils';
|
||||
|
||||
export const dataKey = 'requests';
|
||||
const createAction = createActionFactory(dataKey);
|
||||
|
||||
export const startRequest = createAction('startRequest');
|
||||
export const completeRequest = createAction('completeRequest');
|
||||
export const failRequest = createAction('failRequest');
|
||||
|
||||
export default StrictDict({
|
||||
startRequest,
|
||||
completeRequest,
|
||||
failRequest,
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import actions, { dataKey } from './requests';
|
||||
import { testAction, testActionTypes } from './testUtils';
|
||||
|
||||
describe('actions', () => {
|
||||
describe('action types', () => {
|
||||
const actionTypes = [
|
||||
actions.startRequest,
|
||||
actions.completeRequest,
|
||||
actions.failRequest,
|
||||
].map(action => action.toString());
|
||||
testActionTypes(actionTypes, dataKey);
|
||||
});
|
||||
describe('actions provided', () => {
|
||||
test('startRequest action', () => testAction(actions.startRequest));
|
||||
test('completeRequest action', () => testAction(actions.completeRequest));
|
||||
test('failRequest action', () => testAction(actions.failRequest));
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createActionFactory } from './utils';
|
||||
|
||||
export const dataKey = 'submissions';
|
||||
const createAction = createActionFactory(dataKey);
|
||||
|
||||
/**
|
||||
* Load the basic list-level submission data, keyed by submission id
|
||||
* @param {obj} submissionListData
|
||||
*/
|
||||
const loadList = createAction('loadList');
|
||||
|
||||
export default StrictDict({
|
||||
loadList,
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
import actions, { dataKey } from './submissions';
|
||||
import { testAction, testActionTypes } from './testUtils';
|
||||
|
||||
describe('actions', () => {
|
||||
describe('action types', () => {
|
||||
const actionTypes = [
|
||||
actions.loadList,
|
||||
].map(action => action.toString());
|
||||
testActionTypes(actionTypes, dataKey);
|
||||
});
|
||||
describe('submissionsactions provided', () => {
|
||||
test('loadList action', () => testAction(actions.loadList));
|
||||
});
|
||||
});
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* testActionTypes(actionTypes, dataKey)
|
||||
* Takes a list of actionTypes and a module dataKey, and verifies that
|
||||
* * all actionTypes are unique
|
||||
* * all actionTypes begin with the dataKey
|
||||
* @param {string[]} actionTypes - list of action types
|
||||
* @param {string} dataKey - module data key
|
||||
*/
|
||||
export const testActionTypes = (actionTypes, dataKey) => {
|
||||
test('all types are unique', () => {
|
||||
expect(actionTypes.length).toEqual((new Set(actionTypes)).size);
|
||||
});
|
||||
test('all types begin with the module dataKey', () => {
|
||||
actionTypes.forEach(type => {
|
||||
expect(type.startsWith(dataKey)).toEqual(true);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* testAction(action, args, expectedPayload)
|
||||
* Multi-purpose action creator test function.
|
||||
* If args/expectedPayload are passed, verifies that it produces the expected output when called
|
||||
* with the given args.
|
||||
* If none are passed, (for action creators with basic definition) it tests against a default
|
||||
* test payload.
|
||||
* @param {object} action - action creator object/method
|
||||
* @param {[object]} args - optional payload argument
|
||||
* @param {[object]} expectedPayload - optional expected payload.
|
||||
*/
|
||||
export const testAction = (action, args, expectedPayload) => {
|
||||
const type = action.toString();
|
||||
if (args) {
|
||||
if (Array.isArray(args)) {
|
||||
expect(action(...args)).toEqual({ type, payload: expectedPayload });
|
||||
} else {
|
||||
expect(action(args)).toEqual({ type, payload: expectedPayload });
|
||||
}
|
||||
} else {
|
||||
const payload = { test: 'PAYload' };
|
||||
expect(action(payload)).toEqual({ type, payload });
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
testAction,
|
||||
testActionTypes,
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
|
||||
const createActionFactory = (dataKey) => (actionKey, ...args) => (
|
||||
createAction(`${dataKey}/${actionKey}`, ...args)
|
||||
);
|
||||
|
||||
export {
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
createActionFactory,
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import * as utils from './utils';
|
||||
|
||||
jest.mock('@reduxjs/toolkit', () => ({
|
||||
createAction: (key, ...args) => ({ action: key, args }),
|
||||
}));
|
||||
|
||||
describe('redux action utils', () => {
|
||||
describe('createActionFactory', () => {
|
||||
it('returns an action creator with the data key', () => {
|
||||
const dataKey = 'part-of-the-model';
|
||||
const actionKey = 'an-action';
|
||||
const args = ['some', 'args'];
|
||||
expect(utils.createActionFactory(dataKey)(actionKey, ...args)).toEqual(
|
||||
createAction(`${dataKey}/${actionKey}`, ...args),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,43 +0,0 @@
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
import actions from 'data/actions';
|
||||
|
||||
const initialState = {
|
||||
oraMetadata: {
|
||||
prompt: '',
|
||||
name: '',
|
||||
type: '',
|
||||
rubricConfig: null,
|
||||
fileUploadResponseConfig: null,
|
||||
},
|
||||
courseMetadata: {
|
||||
name: '',
|
||||
number: '',
|
||||
org: '',
|
||||
courseId: '',
|
||||
},
|
||||
showReview: false,
|
||||
showRubric: false,
|
||||
isGrading: false,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const app = createReducer(initialState, {
|
||||
[actions.app.loadCourseMetadata]: (state, { payload }) => ({ ...state, courseMetadata: payload }),
|
||||
[actions.app.loadOraMetadata]: (state, { payload }) => ({ ...state, oraMetadata: payload }),
|
||||
[actions.app.setShowReview]: (state, { payload }) => ({
|
||||
...state,
|
||||
showReview: payload,
|
||||
isReview: state.isGrading && payload, // stop grading when closing review window
|
||||
showRubric: state.showRubric && payload, // Hide rubric when closing review window
|
||||
}),
|
||||
[actions.app.setGrading]: (state, { payload }) => ({
|
||||
...state,
|
||||
isGrading: payload,
|
||||
showRubric: payload || state.showRubric, // open rubric when starting grading
|
||||
}),
|
||||
[actions.app.toggleShowRubric]: (state) => ({ ...state, showRubric: !state.showRubric }),
|
||||
});
|
||||
|
||||
export { initialState };
|
||||
export default app;
|
||||
@@ -1,159 +0,0 @@
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
import { lockStatuses } from 'data/services/lms/constants';
|
||||
import actions from 'data/actions';
|
||||
|
||||
const initialState = {
|
||||
selected: [
|
||||
/**
|
||||
* {
|
||||
* submissionId: '',
|
||||
* username: ''
|
||||
* teamName: ''
|
||||
* dateSubmitted: 0,
|
||||
* gradeStatus: '',
|
||||
* }
|
||||
*/
|
||||
],
|
||||
gradeData: {
|
||||
/**
|
||||
* <submissionId>: {
|
||||
* overallFeedback: '',
|
||||
* criteria: [{
|
||||
* orderNum: 0,
|
||||
* points: 0,
|
||||
* comments: '',
|
||||
* }],
|
||||
* }
|
||||
*/
|
||||
},
|
||||
activeIndex: null,
|
||||
current: {
|
||||
/**
|
||||
* gradeData: {
|
||||
* score: {
|
||||
* pointsEarned: 0,
|
||||
* pointsPossible: 0,
|
||||
* }
|
||||
* overallFeedback: '',
|
||||
* criteria: [{
|
||||
* name: '',
|
||||
* feedback: '',
|
||||
* selectedOption: '',
|
||||
* }],
|
||||
* }
|
||||
* gradeStatus: '',
|
||||
* response: {
|
||||
* text: '',
|
||||
* files: [{
|
||||
* download_url: '',
|
||||
* description: '',
|
||||
* name: '',
|
||||
* }],
|
||||
* },
|
||||
*/
|
||||
},
|
||||
prev: null, // { response }
|
||||
next: null, // { response }
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the given state's gradeData entry for the seleted submission,
|
||||
* overlaying the passed data on top of the existing data for the that
|
||||
* submission.
|
||||
* @return {object} - new state
|
||||
*/
|
||||
export const updateGradeData = (state, data) => ({
|
||||
...state,
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[state.current.submissionId]: {
|
||||
...state.gradeData[state.current.submissionId],
|
||||
...data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Updates the given state's gradeData entry for the seleted submission,
|
||||
* overlaying the passed data on top of the existing data for the criterion
|
||||
* at the given index (orderNum) for the rubric.
|
||||
* @return {object} - new state
|
||||
*/
|
||||
export const updateCriterion = (state, orderNum, data) => {
|
||||
const entry = state.gradeData[state.current.submissionId];
|
||||
const criteria = {
|
||||
...entry.criteria,
|
||||
[orderNum]: { ...entry.criteria[orderNum], ...data },
|
||||
};
|
||||
return updateGradeData(state, { ...entry, criteria });
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const app = createReducer(initialState, {
|
||||
[actions.grading.loadSubmission]: (state, { payload }) => ({
|
||||
...state,
|
||||
current: { ...payload },
|
||||
activeIndex: 0,
|
||||
}),
|
||||
[actions.grading.preloadNext]: (state, { payload }) => ({ ...state, next: payload }),
|
||||
[actions.grading.preloadPrev]: (state, { payload }) => ({ ...state, prev: payload }),
|
||||
[actions.grading.loadNext]: (state, { payload }) => ({
|
||||
...state,
|
||||
prev: { response: state.current.response },
|
||||
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: { response: state.current.response },
|
||||
current: { response: state.prev.response, ...payload },
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[payload.submissionId]: payload.gradeData,
|
||||
},
|
||||
activeIndex: state.activeIndex - 1,
|
||||
prev: null,
|
||||
}),
|
||||
[actions.grading.updateSelection]: (state, { payload }) => ({
|
||||
...state,
|
||||
selected: payload,
|
||||
activeIndex: 0,
|
||||
}),
|
||||
[actions.grading.startGrading]: (state, { payload }) => updateGradeData(
|
||||
{
|
||||
...state,
|
||||
current: { ...state.current, lockStatus: lockStatuses.inProgress },
|
||||
},
|
||||
{ ...payload },
|
||||
),
|
||||
[actions.grading.setRubricFeedback]: (state, { payload }) => (
|
||||
updateGradeData(state, { overallFeedback: payload })
|
||||
),
|
||||
[actions.grading.setCriterionOption]: (state, { payload: { orderNum, value } }) => (
|
||||
updateCriterion(state, orderNum, { selectedOption: value })
|
||||
),
|
||||
[actions.grading.setCriterionFeedback]: (state, { payload: { orderNum, value } }) => (
|
||||
updateCriterion(state, orderNum, { feedback: value })
|
||||
),
|
||||
[actions.grading.clearGrade]: (state) => {
|
||||
const gradeData = { ...state.gradeData };
|
||||
delete gradeData[state.current.submissionId];
|
||||
return {
|
||||
...state,
|
||||
gradeData,
|
||||
current: {
|
||||
...state.current,
|
||||
lockStatus: lockStatuses.unlocked,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
export { initialState };
|
||||
export default app;
|
||||
@@ -1,16 +0,0 @@
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import app from './app';
|
||||
import grading from './grading';
|
||||
import requests from './requests';
|
||||
import submissions from './submissions';
|
||||
|
||||
/* istanbul ignore next */
|
||||
const rootReducer = combineReducers({
|
||||
app,
|
||||
grading,
|
||||
requests,
|
||||
submissions,
|
||||
});
|
||||
|
||||
export default rootReducer;
|
||||
@@ -1,41 +0,0 @@
|
||||
import { createReducer } from '@reduxjs/toolkit';
|
||||
|
||||
import { RequestStates, RequestKeys } from 'data/constants/requests';
|
||||
import actions from 'data/actions';
|
||||
|
||||
const initialState = {
|
||||
[RequestKeys.initialize]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchSubmission]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchSubmissionStatus]: { status: RequestStates.inactive },
|
||||
[RequestKeys.setLock]: { status: RequestStates.inactive },
|
||||
[RequestKeys.prefetchNext]: { status: RequestStates.inactive },
|
||||
[RequestKeys.prefetchPrev]: { status: RequestStates.inactive },
|
||||
[RequestKeys.submitGrade]: { status: RequestStates.inactive },
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const app = createReducer(initialState, {
|
||||
[actions.requests.startRequest]: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload]: {
|
||||
status: RequestStates.pending,
|
||||
},
|
||||
}),
|
||||
[actions.requests.completeRequest]: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload.requestKey]: {
|
||||
status: RequestStates.completed,
|
||||
response: payload.response,
|
||||
},
|
||||
}),
|
||||
[actions.requests.failRequest]: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload.requestKey]: {
|
||||
status: RequestStates.failed,
|
||||
error: payload.error,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
export { initialState };
|
||||
export default app;
|
||||
@@ -1,32 +0,0 @@
|
||||
import actions from 'data/actions';
|
||||
|
||||
const initialState = {
|
||||
allSubmissions: {
|
||||
/**
|
||||
* <submissionId>: {
|
||||
* submissionId: '',
|
||||
* username: ''
|
||||
* teamName: ''
|
||||
* dateSubmitted: 0,
|
||||
* gradeStatus: ''
|
||||
* grade: {
|
||||
* pointsEarned: 0,
|
||||
* pointsPossible: 0,
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
},
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const grades = (state = initialState, { type, payload }) => {
|
||||
switch (type) {
|
||||
case actions.submissions.loadList.toString():
|
||||
return { ...state, allSubmissions: payload };
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export { initialState };
|
||||
export default grades;
|
||||
2
src/data/redux/app/index.js
Normal file
2
src/data/redux/app/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { actions, reducer } from './reducer';
|
||||
export { default as selectors } from './selectors';
|
||||
52
src/data/redux/app/reducer.js
Normal file
52
src/data/redux/app/reducer.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { StrictDict } from 'utils';
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
const initialState = {
|
||||
oraMetadata: {
|
||||
prompt: '',
|
||||
name: '',
|
||||
type: '',
|
||||
rubricConfig: null,
|
||||
},
|
||||
courseMetadata: {
|
||||
name: '',
|
||||
number: '',
|
||||
org: '',
|
||||
courseId: '',
|
||||
},
|
||||
showReview: false,
|
||||
showRubric: false,
|
||||
isGrading: false,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const app = createSlice({
|
||||
name: 'app',
|
||||
initialState,
|
||||
reducers: {
|
||||
loadCourseMetadata: (state, { payload }) => ({ ...state, courseMetadata: payload }),
|
||||
loadOraMetadata: (state, { payload }) => ({ ...state, oraMetadata: payload }),
|
||||
setShowReview: (state, { payload }) => ({
|
||||
...state,
|
||||
showReview: payload,
|
||||
isReview: state.isGrading && payload, // stop grading when closing review window
|
||||
showRubric: state.showRubric && payload, // Hide rubric when closing review window
|
||||
}),
|
||||
setGrading: (state, { payload }) => ({
|
||||
...state,
|
||||
isGrading: payload,
|
||||
showRubric: payload || state.showRubric, // open rubric when starting grading
|
||||
}),
|
||||
toggleShowRubric: (state) => ({ ...state, showRubric: !state.showRubric }),
|
||||
},
|
||||
});
|
||||
|
||||
const actions = StrictDict(app.actions);
|
||||
|
||||
const { reducer } = app;
|
||||
|
||||
export {
|
||||
actions,
|
||||
initialState,
|
||||
reducer,
|
||||
};
|
||||
@@ -4,7 +4,7 @@ import { feedbackRequirement } from 'data/services/lms/constants';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import * as module from './app';
|
||||
import * as module from './selectors';
|
||||
|
||||
export const appSelector = (state) => state.app;
|
||||
|
||||
@@ -42,8 +42,8 @@ export const ora = {
|
||||
*/
|
||||
type: oraMetadataSelector(data => data.type),
|
||||
/**
|
||||
* Return file load response config
|
||||
* @returns {string} - file load response config
|
||||
* Returns file load response config
|
||||
* @return {string} - file upload response config
|
||||
*/
|
||||
fileUploadResponseConfig: oraMetadataSelector(data => data.fileUploadResponseConfig),
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { feedbackRequirement } from 'data/services/lms/constants';
|
||||
|
||||
// import * in order to mock in-file references
|
||||
import * as selectors from './app';
|
||||
import * as selectors from './selectors';
|
||||
|
||||
jest.mock('reselect', () => ({
|
||||
createSelector: jest.fn((preSelectors, cb) => ({ preSelectors, cb })),
|
||||
@@ -19,6 +19,7 @@ const testState = {
|
||||
name: 'test-ora-name',
|
||||
prompt: 'test-ora-prompt',
|
||||
type: 'test-ora-type',
|
||||
fileUploadResponseConfig: 'file-upload-response-config',
|
||||
rubricConfig: {
|
||||
feedback: 'optional',
|
||||
criteria: [
|
||||
@@ -104,12 +105,15 @@ describe('app selectors unit tests', () => {
|
||||
test('ora.type selector returns type from oraMetadata', () => {
|
||||
testOraSelector(selectors.ora.type, oraMetadata.type);
|
||||
});
|
||||
test('ora.fileUploadResponseConfig selector returns file upload config from oraMetadata', () => {
|
||||
testOraSelector(selectors.ora.fileUploadResponseConfig, oraMetadata.fileUploadResponseConfig);
|
||||
});
|
||||
test('rubricConfig selector returns rubricConfig from oraMetadata', () => {
|
||||
testOraSelector(selectors.rubric.config, oraMetadata.rubricConfig);
|
||||
});
|
||||
test('fileUploadResponseConfig returns fileUploadResponseconfig from oraMetadata', () => {
|
||||
testOraSelector(
|
||||
selectors.ora.fileUploadResponseConfig,
|
||||
oraMetadata.fileUploadResponseConfig,
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('rubricConfig selectors', () => {
|
||||
const { rubricConfig } = testState.app.oraMetadata;
|
||||
2
src/data/redux/grading/index.js
Normal file
2
src/data/redux/grading/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { actions, reducer } from './reducer';
|
||||
export { default as selectors } from './selectors';
|
||||
170
src/data/redux/grading/reducer.js
Normal file
170
src/data/redux/grading/reducer.js
Normal file
@@ -0,0 +1,170 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import { lockStatuses } from 'data/services/lms/constants';
|
||||
|
||||
const initialState = {
|
||||
selected: [
|
||||
/**
|
||||
* {
|
||||
* submissionId: '',
|
||||
* username: ''
|
||||
* teamName: ''
|
||||
* dateSubmitted: 0,
|
||||
* gradeStatus: '',
|
||||
* }
|
||||
*/
|
||||
],
|
||||
gradeData: {
|
||||
/**
|
||||
* <submissionId>: {
|
||||
* overallFeedback: '',
|
||||
* criteria: [{
|
||||
* orderNum: 0,
|
||||
* points: 0,
|
||||
* comments: '',
|
||||
* }],
|
||||
* }
|
||||
*/
|
||||
},
|
||||
activeIndex: null,
|
||||
current: {
|
||||
/**
|
||||
* gradeData: {
|
||||
* score: {
|
||||
* pointsEarned: 0,
|
||||
* pointsPossible: 0,
|
||||
* }
|
||||
* overallFeedback: '',
|
||||
* criteria: [{
|
||||
* name: '',
|
||||
* feedback: '',
|
||||
* selectedOption: '',
|
||||
* }],
|
||||
* }
|
||||
* gradeStatus: '',
|
||||
* response: {
|
||||
* text: '',
|
||||
* files: [{
|
||||
* download_url: '',
|
||||
* description: '',
|
||||
* name: '',
|
||||
* }],
|
||||
* },
|
||||
*/
|
||||
},
|
||||
prev: null, // { response }
|
||||
next: null, // { response }
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the given state's gradeData entry for the seleted submission,
|
||||
* overlaying the passed data on top of the existing data for the that
|
||||
* submission.
|
||||
* @return {object} - new state
|
||||
*/
|
||||
export const updateGradeData = (state, data) => ({
|
||||
...state,
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[state.current.submissionId]: {
|
||||
...state.gradeData[state.current.submissionId],
|
||||
...data,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Updates the given state's gradeData entry for the seleted submission,
|
||||
* overlaying the passed data on top of the existing data for the criterion
|
||||
* at the given index (orderNum) for the rubric.
|
||||
* @return {object} - new state
|
||||
*/
|
||||
export const updateCriterion = (state, orderNum, data) => {
|
||||
const entry = state.gradeData[state.current.submissionId];
|
||||
const criteria = {
|
||||
...entry.criteria,
|
||||
[orderNum]: { ...entry.criteria[orderNum], ...data },
|
||||
};
|
||||
return updateGradeData(state, { ...entry, criteria });
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const grading = createSlice({
|
||||
name: 'grading',
|
||||
initialState,
|
||||
reducers: {
|
||||
loadSubmission: (state, { payload }) => ({
|
||||
...state,
|
||||
current: { ...payload },
|
||||
activeIndex: 0,
|
||||
}),
|
||||
preloadNext: (state, { payload }) => ({ ...state, next: payload }),
|
||||
preloadPrev: (state, { payload }) => ({ ...state, prev: payload }),
|
||||
loadNext: (state, { payload }) => ({
|
||||
...state,
|
||||
prev: { response: state.current.response },
|
||||
current: { response: state.next.response, ...payload },
|
||||
activeIndex: state.activeIndex + 1,
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[payload.submissionId]: payload.gradeData,
|
||||
},
|
||||
next: null,
|
||||
}),
|
||||
loadPrev: (state, { payload }) => ({
|
||||
...state,
|
||||
next: { response: state.current.response },
|
||||
current: { response: state.prev.response, ...payload },
|
||||
gradeData: {
|
||||
...state.gradeData,
|
||||
[payload.submissionId]: payload.gradeData,
|
||||
},
|
||||
activeIndex: state.activeIndex - 1,
|
||||
prev: null,
|
||||
}),
|
||||
updateSelection: (state, { payload }) => ({
|
||||
...state,
|
||||
selected: payload,
|
||||
activeIndex: 0,
|
||||
}),
|
||||
startGrading: (state, { payload }) => updateGradeData(
|
||||
{
|
||||
...state,
|
||||
current: { ...state.current, lockStatus: lockStatuses.inProgress },
|
||||
},
|
||||
{ ...payload },
|
||||
),
|
||||
setRubricFeedback: (state, { payload }) => (
|
||||
updateGradeData(state, { overallFeedback: payload })
|
||||
),
|
||||
setCriterionOption: (state, { payload: { orderNum, value } }) => (
|
||||
updateCriterion(state, orderNum, { selectedOption: value })
|
||||
),
|
||||
setCriterionFeedback: (state, { payload: { orderNum, value } }) => (
|
||||
updateCriterion(state, orderNum, { feedback: value })
|
||||
),
|
||||
clearGrade: (state) => {
|
||||
const gradeData = { ...state.gradeData };
|
||||
delete gradeData[state.current.submissionId];
|
||||
return {
|
||||
...state,
|
||||
gradeData,
|
||||
current: {
|
||||
...state.current,
|
||||
lockStatus: lockStatuses.unlocked,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const actions = StrictDict(grading.actions);
|
||||
const { reducer } = grading;
|
||||
|
||||
export {
|
||||
actions,
|
||||
reducer,
|
||||
initialState,
|
||||
};
|
||||
@@ -2,8 +2,8 @@ import { createSelector } from 'reselect';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
import { lockStatuses } from 'data/services/lms/constants';
|
||||
import submissionsSelectors from './submissions';
|
||||
import * as module from './grading';
|
||||
import submissionsSelectors from '../submissions/selectors';
|
||||
import * as module from './selectors';
|
||||
|
||||
export const simpleSelectors = {
|
||||
selected: state => state.grading.selected,
|
||||
32
src/data/redux/index.js
Normal file
32
src/data/redux/index.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import { combineReducers } from 'redux';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import * as app from './app';
|
||||
import * as grading from './grading';
|
||||
import * as requests from './requests';
|
||||
import * as submissions from './submissions';
|
||||
|
||||
export { default as thunkActions } from './thunkActions';
|
||||
|
||||
const modules = {
|
||||
app,
|
||||
grading,
|
||||
requests,
|
||||
submissions,
|
||||
};
|
||||
|
||||
const moduleProps = (propName) => Object.keys(modules).reduce(
|
||||
(obj, moduleKey) => ({ ...obj, [moduleKey]: modules[moduleKey][propName] }),
|
||||
{},
|
||||
);
|
||||
|
||||
const rootReducer = combineReducers(moduleProps('reducer'));
|
||||
|
||||
const actions = StrictDict(moduleProps('actions'));
|
||||
|
||||
const selectors = StrictDict(moduleProps('selectors'));
|
||||
|
||||
export { actions, selectors };
|
||||
|
||||
export default rootReducer;
|
||||
1
src/data/redux/requests/index.js
Normal file
1
src/data/redux/requests/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { actions, reducer } from './reducer';
|
||||
52
src/data/redux/requests/reducer.js
Normal file
52
src/data/redux/requests/reducer.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import { RequestStates, RequestKeys } from 'data/constants/requests';
|
||||
|
||||
const initialState = {
|
||||
[RequestKeys.initialize]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchSubmission]: { status: RequestStates.inactive },
|
||||
[RequestKeys.fetchSubmissionStatus]: { status: RequestStates.inactive },
|
||||
[RequestKeys.setLock]: { status: RequestStates.inactive },
|
||||
[RequestKeys.prefetchNext]: { status: RequestStates.inactive },
|
||||
[RequestKeys.prefetchPrev]: { status: RequestStates.inactive },
|
||||
[RequestKeys.submitGrade]: { status: RequestStates.inactive },
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const requests = createSlice({
|
||||
name: 'requests',
|
||||
initialState,
|
||||
reducers: {
|
||||
startRequest: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload]: {
|
||||
status: RequestStates.pending,
|
||||
},
|
||||
}),
|
||||
completeRequest: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload.requestKey]: {
|
||||
status: RequestStates.completed,
|
||||
response: payload.response,
|
||||
},
|
||||
}),
|
||||
failRequest: (state, { payload }) => ({
|
||||
...state,
|
||||
[payload.requestKey]: {
|
||||
status: RequestStates.failed,
|
||||
error: payload.error,
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const actions = StrictDict(requests.actions);
|
||||
const { reducer } = requests;
|
||||
|
||||
export {
|
||||
actions,
|
||||
reducer,
|
||||
initialState,
|
||||
};
|
||||
@@ -1,6 +1,5 @@
|
||||
import actions from 'data/actions';
|
||||
import { RequestStates } from 'data/constants/requests';
|
||||
import requests, { initialState } from './requests';
|
||||
import { initialState, actions, reducer } from './reducer';
|
||||
|
||||
const testingState = {
|
||||
...initialState,
|
||||
@@ -9,39 +8,39 @@ const testingState = {
|
||||
|
||||
describe('requests reducer', () => {
|
||||
it('has initial state', () => {
|
||||
expect(requests(undefined, {})).toEqual(initialState);
|
||||
expect(reducer(undefined, {})).toEqual(initialState);
|
||||
});
|
||||
|
||||
const testValue = 'roll for initiative';
|
||||
const testKey = 'test-key';
|
||||
describe('handling actions', () => {
|
||||
describe('requests.startRequest', () => {
|
||||
describe('startRequest', () => {
|
||||
it('adds a pending status for the given key', () => {
|
||||
expect(requests(
|
||||
expect(reducer(
|
||||
testingState,
|
||||
actions.requests.startRequest(testKey),
|
||||
actions.startRequest(testKey),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
[testKey]: { status: RequestStates.pending },
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('requests.completeRequest', () => {
|
||||
describe('completeRequest', () => {
|
||||
it('adds a completed status with passed response', () => {
|
||||
expect(requests(
|
||||
expect(reducer(
|
||||
testingState,
|
||||
actions.requests.completeRequest({ requestKey: testKey, response: testValue }),
|
||||
actions.completeRequest({ requestKey: testKey, response: testValue }),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
[testKey]: { status: RequestStates.completed, response: testValue },
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('requests.failRequest', () => {
|
||||
describe('failRequest', () => {
|
||||
it('adds a failed status with passed error', () => {
|
||||
expect(requests(
|
||||
expect(reducer(
|
||||
testingState,
|
||||
actions.requests.failRequest({ requestKey: testKey, error: testValue }),
|
||||
actions.failRequest({ requestKey: testKey, error: testValue }),
|
||||
)).toEqual({
|
||||
...testingState,
|
||||
[testKey]: { status: RequestStates.failed, error: testValue },
|
||||
2
src/data/redux/submissions/index.js
Normal file
2
src/data/redux/submissions/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export { actions, reducer } from './reducer';
|
||||
export { default as selectors } from './selectors';
|
||||
39
src/data/redux/submissions/reducer.js
Normal file
39
src/data/redux/submissions/reducer.js
Normal file
@@ -0,0 +1,39 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
const initialState = {
|
||||
allSubmissions: {
|
||||
/**
|
||||
* <submissionId>: {
|
||||
* submissionId: '',
|
||||
* username: ''
|
||||
* teamName: ''
|
||||
* dateSubmitted: 0,
|
||||
* gradeStatus: ''
|
||||
* grade: {
|
||||
* pointsEarned: 0,
|
||||
* pointsPossible: 0,
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
},
|
||||
};
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const submissions = createSlice({
|
||||
name: 'submissions',
|
||||
initialState,
|
||||
reducers: {
|
||||
loadList: (state, { payload }) => ({ ...state, allSubmissions: payload }),
|
||||
},
|
||||
});
|
||||
|
||||
const actions = StrictDict(submissions.actions);
|
||||
const { reducer } = submissions;
|
||||
|
||||
export {
|
||||
actions,
|
||||
reducer,
|
||||
initialState,
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import { actions } from 'data/redux';
|
||||
import { locationId } from 'data/constants/app';
|
||||
import { initializeApp } from './requests';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { locationId } from 'data/constants/app';
|
||||
|
||||
import actions from 'data/actions';
|
||||
import { actions } from 'data/redux';
|
||||
import thunkActions from './app';
|
||||
|
||||
jest.mock('./requests', () => ({
|
||||
@@ -1,9 +1,9 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
import { gradingStatuses as statuses } from 'data/services/lms/constants';
|
||||
import { actions, selectors } from 'data/redux';
|
||||
|
||||
import * as module from './grading';
|
||||
import requests from './requests';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import { gradingStatuses } from 'data/services/lms/constants';
|
||||
import actions from 'data/actions';
|
||||
import selectors from 'data/selectors';
|
||||
|
||||
import { actions, selectors } from 'data/redux';
|
||||
import * as thunkActions from './grading';
|
||||
|
||||
jest.mock('./requests', () => ({
|
||||
@@ -12,26 +12,22 @@ jest.mock('./requests', () => ({
|
||||
submitGrade: (args) => ({ submitGrade: args }),
|
||||
}));
|
||||
|
||||
jest.mock('data/selectors', () => ({
|
||||
__esModule: true,
|
||||
default: {
|
||||
app: {
|
||||
emptyGrade: (state) => ({ emptyGrade: state }),
|
||||
},
|
||||
grading: {
|
||||
prev: {
|
||||
submissionId: (state) => ({ prevSubmissionId: state }),
|
||||
doesExist: jest.fn((state) => ({ prevDoesExist: state })),
|
||||
},
|
||||
next: {
|
||||
submissionId: (state) => ({ prevSubmissionId: state }),
|
||||
doesExist: jest.fn((state) => ({ nextDoesExist: state })),
|
||||
},
|
||||
selected: {
|
||||
submissionId: (state) => ({ selectedSubmissionId: state }),
|
||||
gradeData: jest.fn((state) => ({ gradeData: state })),
|
||||
},
|
||||
},
|
||||
jest.mock('data/redux/app/selectors', () => ({
|
||||
emptyGrade: (state) => ({ emptyGrade: state }),
|
||||
}));
|
||||
|
||||
jest.mock('data/redux/grading/selectors', () => ({
|
||||
prev: {
|
||||
submissionId: (state) => ({ prevSubmissionId: state }),
|
||||
doesExist: jest.fn((state) => ({ prevDoesExist: state })),
|
||||
},
|
||||
next: {
|
||||
submissionId: (state) => ({ prevSubmissionId: state }),
|
||||
doesExist: jest.fn((state) => ({ nextDoesExist: state })),
|
||||
},
|
||||
selected: {
|
||||
submissionId: (state) => ({ selectedSubmissionId: state }),
|
||||
gradeData: jest.fn((state) => ({ gradeData: state })),
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import actions from 'data/actions';
|
||||
import { actions } from 'data/redux';
|
||||
import api from 'data/services/lms/api';
|
||||
|
||||
import * as module from './requests';
|
||||
|
||||
/**
|
||||
@@ -1,4 +1,4 @@
|
||||
import actions from 'data/actions';
|
||||
import { actions } from 'data/redux';
|
||||
import { RequestKeys } from 'data/constants/requests';
|
||||
import api from 'data/services/lms/api';
|
||||
import * as requests from './requests';
|
||||
@@ -1,11 +0,0 @@
|
||||
import { StrictDict } from 'utils';
|
||||
|
||||
import app from './app';
|
||||
import grading from './grading';
|
||||
import submissions from './submissions';
|
||||
|
||||
export default StrictDict({
|
||||
app,
|
||||
grading,
|
||||
submissions,
|
||||
});
|
||||
@@ -3,9 +3,7 @@ import thunkMiddleware from 'redux-thunk';
|
||||
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
|
||||
import { createLogger } from 'redux-logger';
|
||||
|
||||
import actions from './actions';
|
||||
import selectors from './selectors';
|
||||
import reducers from './reducers';
|
||||
import reducer, { actions, selectors } from './redux';
|
||||
|
||||
export const createStore = () => {
|
||||
const loggerMiddleware = createLogger();
|
||||
@@ -13,7 +11,7 @@ export const createStore = () => {
|
||||
const middleware = [thunkMiddleware, loggerMiddleware];
|
||||
|
||||
const store = redux.createStore(
|
||||
reducers,
|
||||
reducer,
|
||||
composeWithDevTools(redux.applyMiddleware(...middleware)),
|
||||
);
|
||||
|
||||
|
||||
@@ -3,15 +3,16 @@ import thunkMiddleware from 'redux-thunk';
|
||||
import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
|
||||
import { createLogger } from 'redux-logger';
|
||||
|
||||
import actions from './actions';
|
||||
import selectors from './selectors';
|
||||
import reducers from './reducers';
|
||||
import rootReducer, { actions, selectors } from 'data/redux';
|
||||
|
||||
import exportedStore, { createStore } from './store';
|
||||
|
||||
jest.mock('./reducers', () => 'REDUCER');
|
||||
jest.mock('./actions', () => 'ACTIONS');
|
||||
jest.mock('./selectors', () => 'SELECTORS');
|
||||
jest.mock('data/redux', () => ({
|
||||
__esModule: true,
|
||||
default: 'REDUCER',
|
||||
actions: 'ACTIONS',
|
||||
selectors: 'SELECTORS',
|
||||
}));
|
||||
|
||||
jest.mock('redux-logger', () => ({
|
||||
createLogger: () => 'logger',
|
||||
@@ -31,7 +32,7 @@ describe('store aggregator module', () => {
|
||||
expect(exportedStore).toEqual(createStore());
|
||||
});
|
||||
it('creates store with connected reducers', () => {
|
||||
expect(createStore().reducer).toEqual(reducers);
|
||||
expect(createStore().reducer).toEqual(rootReducer);
|
||||
});
|
||||
describe('middleware', () => {
|
||||
it('exports thunk and logger middleware, composed and applied with dev tools', () => {
|
||||
|
||||
@@ -16,6 +16,7 @@ jest.mock('react-dom', () => ({
|
||||
render: jest.fn(),
|
||||
}));
|
||||
jest.mock('@edx/frontend-platform', () => ({
|
||||
...jest.requireActual('@edx/frontend-platform'),
|
||||
APP_READY: 'app-is-ready-key',
|
||||
initialize: jest.fn(),
|
||||
subscribe: jest.fn(),
|
||||
|
||||
@@ -14,7 +14,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
|
||||
import fakeData from 'data/services/lms/fakeData';
|
||||
import api from 'data/services/lms/api';
|
||||
import reducers from 'data/reducers';
|
||||
import reducers from 'data/redux';
|
||||
import { gradingStatuses } from 'data/services/lms/constants';
|
||||
import messages from 'i18n';
|
||||
import reviewActionsMessages from 'containers/ReviewActions/messages';
|
||||
@@ -179,11 +179,15 @@ describe('ESG app integration tests', () => {
|
||||
|
||||
test('initialState', async () => {
|
||||
await renderEl();
|
||||
expect(state.app).toEqual(jest.requireActual('data/reducers/app').initialState);
|
||||
expect(state.submissions).toEqual(
|
||||
jest.requireActual('data/reducers/submissions').initialState,
|
||||
expect(state.app).toEqual(
|
||||
jest.requireActual('data/redux/app/reducer').initialState,
|
||||
);
|
||||
expect(state.submissions).toEqual(
|
||||
jest.requireActual('data/redux/submissions/reducer').initialState,
|
||||
);
|
||||
expect(state.grading).toEqual(
|
||||
jest.requireActual('data/redux/grading/reducer').initialState,
|
||||
);
|
||||
expect(state.grading).toEqual(jest.requireActual('data/reducers/grading').initialState);
|
||||
});
|
||||
|
||||
test('initialization', async () => {
|
||||
|
||||
Reference in New Issue
Block a user