From 571cb66fc940fd04c2e74ea7f508218e8bfc7987 Mon Sep 17 00:00:00 2001 From: Ben Warzeski Date: Tue, 5 Oct 2021 11:37:26 -0400 Subject: [PATCH] add unit tests for ReviewModal ReviewActions components --- .../ReviewModal/ReviewActions.test.jsx | 67 +++++++++++++++ .../ReviewModal/StartGradingButton.jsx | 4 +- .../ReviewModal/StartGradingButton.test.jsx | 75 ++++++++++++++++ .../ReviewModal/SubmissionNavigation.jsx | 16 ++-- .../ReviewModal/SubmissionNavigation.test.jsx | 86 +++++++++++++++++++ .../__snapshots__/ReviewActions.test.jsx.snap | 63 ++++++++++++++ .../StartGradingButton.test.jsx.snap | 33 +++++++ .../SubmissionNavigation.test.jsx.snap | 57 ++++++++++++ 8 files changed, 391 insertions(+), 10 deletions(-) create mode 100644 src/containers/ReviewModal/ReviewActions.test.jsx create mode 100644 src/containers/ReviewModal/StartGradingButton.test.jsx create mode 100644 src/containers/ReviewModal/SubmissionNavigation.test.jsx create mode 100644 src/containers/ReviewModal/__snapshots__/ReviewActions.test.jsx.snap create mode 100644 src/containers/ReviewModal/__snapshots__/StartGradingButton.test.jsx.snap create mode 100644 src/containers/ReviewModal/__snapshots__/SubmissionNavigation.test.jsx.snap diff --git a/src/containers/ReviewModal/ReviewActions.test.jsx b/src/containers/ReviewModal/ReviewActions.test.jsx new file mode 100644 index 0000000..6c439d5 --- /dev/null +++ b/src/containers/ReviewModal/ReviewActions.test.jsx @@ -0,0 +1,67 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import actions from 'data/actions'; +import selectors from 'data/selectors'; + +import { ReviewActions, mapStateToProps, mapDispatchToProps } from './ReviewActions'; + +jest.mock('@edx/paragon', () => ({ + ActionRow: () => 'ActionRow', + Button: () => 'Button', +})); +jest.mock('data/selectors', () => ({ + __esModule: true, + default: { + app: { showRubric: (state) => ({ showRubric: state }) }, + grading: { + selected: { + username: (state) => ({ username: state }), + gradingStatus: (state) => ({ gradingStatus: state }), + }, + }, + }, +})); +jest.mock('components/StatusBadge', () => 'StatusBadge'); +jest.mock('./StartGradingButton', () => 'StartGradingButton'); +jest.mock('./SubmissionNavigation', () => 'SubmissionNavigation'); + +describe('ReviewActions component', () => { + describe('component', () => { + const props = { + gradingStatus: 'grading-status', + username: 'test-username', + showRubric: false, + }; + beforeEach(() => { + props.toggleShowRubric = jest.fn().mockName('this.props.toggleShowRubric'); + }); + test('snapshot: do not show rubric', () => { + expect(shallow()).toMatchSnapshot(); + }); + test('snapshot: show rubric', () => { + expect(shallow()).toMatchSnapshot(); + }); + }); + describe('mapStateToProps', () => { + let mapped; + const testState = { some: 'test-state' }; + beforeEach(() => { + mapped = mapStateToProps(testState); + }); + test('username loads from grading.selected.username', () => { + expect(mapped.username).toEqual(selectors.grading.selected.username(testState)); + }); + test('gradingStatus loads from grading.selected.gradingStatus', () => { + expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState)); + }); + test('showRubric loads from app.showRubric', () => { + expect(mapped.showRubric).toEqual(selectors.app.showRubric(testState)); + }); + }); + describe('mapDispatchToProps', () => { + it('loads toggleShowRubric from actions.app.toggleShowRubric', () => { + expect(mapDispatchToProps.toggleShowRubric).toEqual(actions.app.toggleShowRubric); + }); + }); +}); diff --git a/src/containers/ReviewModal/StartGradingButton.jsx b/src/containers/ReviewModal/StartGradingButton.jsx index 47e58e9..64337e7 100644 --- a/src/containers/ReviewModal/StartGradingButton.jsx +++ b/src/containers/ReviewModal/StartGradingButton.jsx @@ -7,12 +7,11 @@ import { } from '@edx/paragon'; import { Cancel, Highlight } from '@edx/paragon/icons'; -import actions from 'data/actions'; import selectors from 'data/selectors'; import thunkActions from 'data/thunkActions'; import { gradingStatuses as statuses } from 'data/services/lms/constants'; -const buttonArgs = { +export const buttonArgs = { [statuses.ungraded]: { label: 'Start Grading', iconAfter: Highlight, @@ -58,7 +57,6 @@ export const mapStateToProps = (state) => ({ }); export const mapDispatchToProps = { - toggleShowRubric: actions.app.toggleShowRubric, startGrading: thunkActions.grading.startGrading, stopGrading: thunkActions.grading.stopGrading, }; diff --git a/src/containers/ReviewModal/StartGradingButton.test.jsx b/src/containers/ReviewModal/StartGradingButton.test.jsx new file mode 100644 index 0000000..625aa00 --- /dev/null +++ b/src/containers/ReviewModal/StartGradingButton.test.jsx @@ -0,0 +1,75 @@ +import React from 'react'; +import { shallow } from 'enzyme'; + +import selectors from 'data/selectors'; +import thunkActions from 'data/thunkActions'; +import { gradingStatuses as statuses } from 'data/services/lms/constants'; + +import { + StartGradingButton, + mapStateToProps, + mapDispatchToProps, +} from './StartGradingButton'; + +jest.mock('@edx/paragon', () => ({ + Button: () => 'Button', +})); +jest.mock('@edx/paragon/icons', () => ({ + Cancel: 'Cancel', + Highlight: 'Highlight', +})); +jest.mock('data/selectors', () => ({ + __esModule: true, + default: { + grading: { + selected: { + gradingStatus: (state) => ({ gradingStatus: state }), + }, + }, + }, +})); + +describe('StartGradingButton component', () => { + describe('component', () => { + const props = {}; + beforeEach(() => { + props.startGrading = jest.fn().mockName('this.props.startGrading'); + props.stopGrading = jest.fn().mockName('this.props.stopGrading'); + }); + const render = (gradingStatus) => shallow( + , + ); + test('snapshot: locked (null)', () => { + const el = render(statuses.locked); + expect(el).toMatchSnapshot(); + expect(el).toEqual({}); + }); + test('snapshot: ungraded (startGrading callback)', () => { + expect(render(statuses.ungraded)).toMatchSnapshot(); + }); + test('snapshot: graded (startGrading callback', () => { + expect(render(statuses.graded)).toMatchSnapshot(); + }); + test('snapshot: inProgress (stopGrading callback', () => { + expect(render(statuses.inProgress)).toMatchSnapshot(); + }); + }); + describe('mapStateToProps', () => { + let mapped; + const testState = { some: 'test-state' }; + beforeEach(() => { + mapped = mapStateToProps(testState); + }); + test('gradingStatus loads from grading.selected.gradingStatus', () => { + expect(mapped.gradingStatus).toEqual(selectors.grading.selected.gradingStatus(testState)); + }); + }); + describe('mapDispatchToProps', () => { + it('loads startGrading from thunkActions.grading.stargGrading', () => { + expect(mapDispatchToProps.startGrading).toEqual(thunkActions.grading.startGrading); + }); + it('loads stopGrading from thunkActions.grading.stopGrading', () => { + expect(mapDispatchToProps.stopGrading).toEqual(thunkActions.grading.stopGrading); + }); + }); +}); diff --git a/src/containers/ReviewModal/SubmissionNavigation.jsx b/src/containers/ReviewModal/SubmissionNavigation.jsx index 3239a4d..8cbf6b7 100644 --- a/src/containers/ReviewModal/SubmissionNavigation.jsx +++ b/src/containers/ReviewModal/SubmissionNavigation.jsx @@ -40,26 +40,28 @@ export const SubmissionNavigation = ({ ); SubmissionNavigation.defaultProps = { + hasPrevSubmission: false, + hasNextSubmission: false, }; SubmissionNavigation.propTypes = { - hasPrevSubmission: PropTypes.bool.isRequired, - hasNextSubmission: PropTypes.bool.isRequired, - loadPrev: PropTypes.func.isRequired, - loadNext: PropTypes.func.isRequired, activeIndex: PropTypes.number.isRequired, + hasNextSubmission: PropTypes.bool, + hasPrevSubmission: PropTypes.bool, + loadNext: PropTypes.func.isRequired, + loadPrev: PropTypes.func.isRequired, selectionLength: PropTypes.number.isRequired, }; export const mapStateToProps = (state) => ({ - hasPrevSubmission: selectors.grading.prev.doesExist(state), - hasNextSubmission: selectors.grading.next.doesExist(state), activeIndex: selectors.grading.activeIndex(state), + hasNextSubmission: selectors.grading.next.doesExist(state), + hasPrevSubmission: selectors.grading.prev.doesExist(state), selectionLength: selectors.grading.selectionLength(state), }); export const mapDispatchToProps = { - loadPrev: thunkActions.grading.loadPrev, loadNext: thunkActions.grading.loadNext, + loadPrev: thunkActions.grading.loadPrev, }; export default connect(mapStateToProps, mapDispatchToProps)(SubmissionNavigation); diff --git a/src/containers/ReviewModal/SubmissionNavigation.test.jsx b/src/containers/ReviewModal/SubmissionNavigation.test.jsx new file mode 100644 index 0000000..bc9cadd --- /dev/null +++ b/src/containers/ReviewModal/SubmissionNavigation.test.jsx @@ -0,0 +1,86 @@ +import React from 'react'; +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, + mapStateToProps, + mapDispatchToProps, +} from './SubmissionNavigation'; + +jest.mock('@edx/paragon', () => ({ + Icon: () => 'Icon', + IconButton: () => 'IconButton', +})); +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 }), + }, + }, +})); + +describe('SubmissionNavigation component', () => { + describe('component', () => { + const props = { + activeIndex: 4, + selectionLength: 5, + }; + beforeEach(() => { + props.loadNext = jest.fn().mockName('this.props.loadNext'); + props.loadPrev = jest.fn().mockName('this.props.loadPrev'); + }); + test('snapshot: no prev submission (disabled)', () => { + expect(shallow( + , + )).toMatchSnapshot(); + }); + test('snapshot: no next submission (disabled)', () => { + expect(shallow( + , + )).toMatchSnapshot(); + }); + }); + describe('mapStateToProps', () => { + let mapped; + const testState = { some: 'test-state' }; + beforeEach(() => { + mapped = mapStateToProps(testState); + }); + test('activeIndex loads from grading.activeIndex', () => { + expect(mapped.activeIndex).toEqual(selectors.grading.activeIndex(testState)); + }); + test('hasNextSubmission loads from grading.next.doesExist', () => { + expect(mapped.hasNextSubmission).toEqual(selectors.grading.next.doesExist(testState)); + }); + test('hasPrevSubmission loads from grading.prev.doesExist', () => { + expect(mapped.hasPrevSubmission).toEqual(selectors.grading.prev.doesExist(testState)); + }); + test('selectionLength loads from grading.selectionLength', () => { + expect(mapped.selectionLength).toEqual(selectors.grading.selectionLength(testState)); + }); + }); + describe('mapDispatchToProps', () => { + it('loads loadNext from thunkActions.grading.loadNext', () => { + expect(mapDispatchToProps.loadNext).toEqual(thunkActions.grading.loadNext); + }); + it('loads loadPrev from thunkActions.grading.loadPrev', () => { + expect(mapDispatchToProps.loadPrev).toEqual(thunkActions.grading.loadPrev); + }); + }); +}); diff --git a/src/containers/ReviewModal/__snapshots__/ReviewActions.test.jsx.snap b/src/containers/ReviewModal/__snapshots__/ReviewActions.test.jsx.snap new file mode 100644 index 0000000..8e413b4 --- /dev/null +++ b/src/containers/ReviewModal/__snapshots__/ReviewActions.test.jsx.snap @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ReviewActions component component snapshot: do not show rubric 1`] = ` +
+ + + test-username + + +
+ + + +
+
+
+`; + +exports[`ReviewActions component component snapshot: show rubric 1`] = ` +
+ + + test-username + + +
+ + + +
+
+
+`; diff --git a/src/containers/ReviewModal/__snapshots__/StartGradingButton.test.jsx.snap b/src/containers/ReviewModal/__snapshots__/StartGradingButton.test.jsx.snap new file mode 100644 index 0000000..800c162 --- /dev/null +++ b/src/containers/ReviewModal/__snapshots__/StartGradingButton.test.jsx.snap @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`StartGradingButton component component snapshot: graded (startGrading callback 1`] = ` + +`; + +exports[`StartGradingButton component component snapshot: inProgress (stopGrading callback 1`] = ` + +`; + +exports[`StartGradingButton component component snapshot: locked (null) 1`] = `""`; + +exports[`StartGradingButton component component snapshot: ungraded (startGrading callback) 1`] = ` + +`; diff --git a/src/containers/ReviewModal/__snapshots__/SubmissionNavigation.test.jsx.snap b/src/containers/ReviewModal/__snapshots__/SubmissionNavigation.test.jsx.snap new file mode 100644 index 0000000..af1c43c --- /dev/null +++ b/src/containers/ReviewModal/__snapshots__/SubmissionNavigation.test.jsx.snap @@ -0,0 +1,57 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SubmissionNavigation component component snapshot: no next submission (disabled) 1`] = ` + + + + 5 + of + 5 + + + +`; + +exports[`SubmissionNavigation component component snapshot: no prev submission (disabled) 1`] = ` + + + + 1 + of + 5 + + + +`;