diff --git a/src/App.test.jsx b/src/App.test.jsx
index 6116b38..775e196 100644
--- a/src/App.test.jsx
+++ b/src/App.test.jsx
@@ -1,75 +1,41 @@
-// import React from 'react';
-// import { shallow } from 'enzyme';
+import React from 'react';
+import { shallow } from 'enzyme';
-// import Footer from '@edx/frontend-component-footer';
-// import { LearningHeader as Header } from '@edx/frontend-component-header';
+import { BrowserRouter } from 'react-router-dom';
-// import ListView from 'containers/ListView';
+import Footer from '@edx/frontend-component-footer';
-// import { App } from './App';
+import Dashboard from 'containers/Dashboard';
+import { App } from './App';
-// jest.mock('data/redux', () => ({
-// app: {
-// selectors: {
-// courseMetadata: (state) => ({ courseMetadata: state }),
-// isEnabled: (state) => ({ isEnabled: state }),
-// },
-// },
-// }));
+jest.mock('@edx/frontend-component-footer', () => 'Footer');
-// jest.mock('@edx/frontend-component-header', () => ({
-// LearningHeader: 'Header',
-// }));
-// jest.mock('@edx/frontend-component-footer', () => 'Footer');
+jest.mock('containers/Dashboard', () => 'Dashboard');
+jest.mock('containers/LearnerDashboardHeader', () => 'LearnerDashboardHeader');
-// jest.mock('containers/DemoWarning', () => 'DemoWarning');
-// jest.mock('containers/ListView', () => 'ListView');
+const logo = 'fakeLogo.png';
+let el;
+let router;
-// const logo = 'fakeLogo.png';
-// let el;
-// let router;
-
-// describe('App router component', () => {
-// const props = {
-// courseMetadata: {
-// org: 'course-org',
-// number: 'course-number',
-// title: 'course-title',
-// },
-// isEnabled: true,
-// };
-// test('snapshot: enabled', () => {
-// expect(shallow()).toMatchSnapshot();
-// });
-// test('snapshot: disabled (show demo warning)', () => {
-// expect(shallow()).toMatchSnapshot();
-// });
-// describe('component', () => {
-// beforeEach(() => {
-// process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG = logo;
-// el = shallow();
-// router = el.childAt(0);
-// });
-// describe('Router', () => {
-// test('Routing - ListView is only route', () => {
-// expect(router.find('main')).toEqual(shallow(
-// ,
-// ));
-// });
-// });
-// test('Footer logo drawn from env variable', () => {
-// expect(router.find(Footer).props().logo).toEqual(logo);
-// });
-
-// test('Header to use courseMetadata props', () => {
-// const {
-// courseTitle,
-// courseNumber,
-// courseOrg,
-// } = router.find(Header).props();
-// expect(courseTitle).toEqual(props.courseMetadata.title);
-// expect(courseNumber).toEqual(props.courseMetadata.number);
-// expect(courseOrg).toEqual(props.courseMetadata.org);
-// });
-// });
-// });
+describe('App router component', () => {
+ test('snapshot: enabled', () => {
+ expect(shallow()).toMatchSnapshot();
+ });
+ describe('component', () => {
+ beforeEach(() => {
+ process.env.LOGO_POWERED_BY_OPEN_EDX_URL_SVG = logo;
+ el = shallow();
+ router = el.find(BrowserRouter);
+ });
+ describe('Router', () => {
+ test('Routing - ListView is only route', () => {
+ expect(router.find('main')).toEqual(shallow(
+ ,
+ ));
+ });
+ });
+ test('Footer logo drawn from env variable', () => {
+ expect(router.find(Footer).props().logo).toEqual(logo);
+ });
+ });
+});
diff --git a/src/__snapshots__/App.test.jsx.snap b/src/__snapshots__/App.test.jsx.snap
new file mode 100644
index 0000000..0748d92
--- /dev/null
+++ b/src/__snapshots__/App.test.jsx.snap
@@ -0,0 +1,15 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`App router component snapshot: enabled 1`] = `
+
+
+
+
+
+
+
+
+
+`;
diff --git a/src/__snapshots__/index.test.jsx.snap b/src/__snapshots__/index.test.jsx.snap
index b7564fc..1e8cd8e 100644
--- a/src/__snapshots__/index.test.jsx.snap
+++ b/src/__snapshots__/index.test.jsx.snap
@@ -13,11 +13,7 @@ exports[`app registry subscribe: APP_READY. links App to root element 1`] = `
diff --git a/src/containers/UnenrollConfirmModal/components/ReasonPane.jsx b/src/containers/UnenrollConfirmModal/components/ReasonPane.jsx
index 425c686..1f40f77 100644
--- a/src/containers/UnenrollConfirmModal/components/ReasonPane.jsx
+++ b/src/containers/UnenrollConfirmModal/components/ReasonPane.jsx
@@ -58,7 +58,6 @@ ReasonPane.propTypes = {
}),
selected: PropTypes.string,
submit: PropTypes.func,
- isSubmited: PropTypes.bool,
}).isRequired,
};
diff --git a/src/containers/UnenrollConfirmModal/hooks.test.js b/src/containers/UnenrollConfirmModal/hooks.test.js
index 3355dac..9315ee2 100644
--- a/src/containers/UnenrollConfirmModal/hooks.test.js
+++ b/src/containers/UnenrollConfirmModal/hooks.test.js
@@ -1,8 +1,6 @@
-import React from 'react';
-
-import { MockUseState, testCardValues } from 'testUtils';
-import * as hooks from './hooks';
+import { MockUseState } from 'testUtils';
import { thunkActions } from 'data/redux';
+import * as hooks from './hooks';
jest.mock('data/redux/thunkActions/app', () => ({
refreshList: jest.fn((args) => ({ refreshList: args })),
diff --git a/src/data/redux/app/reducer.test.js b/src/data/redux/app/reducer.test.js
index 4302fd2..549ad75 100644
--- a/src/data/redux/app/reducer.test.js
+++ b/src/data/redux/app/reducer.test.js
@@ -1,43 +1,16 @@
import { initialState, reducer, actions } from './reducer';
describe('app reducer', () => {
- describe('initialState', () => {
- test('populated, but empty course metadata', () => {
- const data = initialState.courseMetadata;
- expect(data.name).toEqual('');
- expect(data.number).toEqual('');
- expect(data.org).toEqual('');
- expect(data.courseId).toEqual('');
- });
- test('disabled (waffle flag)', () => {
- expect(initialState.isEnabled).toEqual(false);
- });
- test('not grading', () => {
- expect(initialState.isGrading).toEqual(false);
- });
- test('populated, but empty ora metadata', () => {
- const data = initialState.oraMetadata;
- expect(data.prompt).toEqual('');
- expect(data.name).toEqual('');
- expect(data.type).toEqual('');
- expect(data.rubricConfig).toEqual(null);
- });
- test('not showing review', () => {
- expect(initialState.showReview).toEqual(false);
- });
- test('not showing rubric', () => {
- expect(initialState.showRubric).toEqual(false);
- });
- });
describe('reducers', () => {
it('returns initial state', () => {
expect(reducer(undefined, {})).toEqual(initialState);
});
const testState = {
...initialState,
- showRubric: true,
- showReview: true,
- arbitrary: 'state',
+ enrollments: [],
+ courseData: {
+ },
+ entitlements: [],
};
const testValue = 'my-test-value';
const testAction = (action, expected) => {
@@ -47,26 +20,46 @@ describe('app reducer', () => {
});
};
describe('action handlers', () => {
- test('loadIsEnabled loads isEnabled from payload', () => {
- testAction(actions.loadIsEnabled(testValue), { isEnabled: testValue });
+ test('loadEntitlements loads entitlements from payload', () => {
+ testAction(
+ actions.loadEntitlements(testValue),
+ { entitlements: testValue },
+ );
});
- test('loadCourseMetadata loads courseMetadata from payload', () => {
- testAction(actions.loadCourseMetadata(testValue), { courseMetadata: testValue });
- });
- test('loadOraMetadata loads oraMetadata from payload', () => {
- testAction(actions.loadOraMetadata(testValue), { oraMetadata: testValue });
- });
- describe('setShowReview', () => {
- it('loads showReview, sets showRubric to false if set to false', () => {
- testAction(actions.setShowReview(true), { showReview: true });
- testAction(actions.setShowReview(false), { showReview: false, showRubric: false });
+ describe('loadEnrollments', () => {
+ const enrollments = [
+ 'course-1',
+ 'course-2',
+ 'course-3',
+ ];
+ const courseData = {
+ [enrollments[0]]: {
+ courseRun: { courseNumber: enrollments[0] },
+ course: 1,
+ some: 'data',
+ },
+ [enrollments[1]]: {
+ courseRun: { courseNumber: enrollments[1] },
+ course: 2,
+ some: 'other data',
+ },
+ [enrollments[2]]: {
+ courseRun: { courseNumber: enrollments[2] },
+ course: 3,
+ some: 'still different data',
+ },
+ };
+ const enrollmentData = enrollments.map(v => courseData[v]);
+ let out;
+ beforeEach(() => {
+ out = reducer(testState, actions.loadEnrollments(enrollmentData));
+ });
+ it('loads list of courseRun ids into enrollments field', () => {
+ expect(out.enrollments).toEqual(enrollments);
+ });
+ it('loads object keyed by courseRun ids into courseData field', () => {
+ expect(out.courseData).toEqual(courseData);
});
- });
- test('setShowRubric loads showRubric from payload', () => {
- testAction(actions.setShowRubric(testValue), { showRubric: testValue });
- });
- test('toggleShowRubric toggles showRubric value', () => {
- testAction(actions.toggleShowRubric(), { showRubric: !testState.showRubric });
});
});
});
diff --git a/src/data/redux/requests/selectors.test.js b/src/data/redux/requests/selectors.test.js
index e5110a4..089dc71 100644
--- a/src/data/redux/requests/selectors.test.js
+++ b/src/data/redux/requests/selectors.test.js
@@ -30,12 +30,6 @@ describe('requests selectors unit tests', () => {
test('requestStatus returns data associated with given key', () => {
expect(selectors.requestStatus(testState, { requestKey })).toEqual(requestData);
});
- describe('allowNavigation', () => {
- it('returns false if any requests are pending', () => {
- expect(selectors.allowNavigation(testState)).toEqual(true);
- expect(selectors.allowNavigation({ requests: { key1: pendingRequest } })).toEqual(false);
- });
- });
const testStatusSelector = (selector, matchingRequest) => {
expect(selector(testState, { requestKey })).toEqual(false);
expect(selector(
diff --git a/src/data/redux/thunkActions/app.test.js b/src/data/redux/thunkActions/app.test.js
deleted file mode 100644
index 18765bd..0000000
--- a/src/data/redux/thunkActions/app.test.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import { locationId } from 'data/constants/app';
-
-import { selectors, actions } from 'data/redux';
-import { keyStore } from 'utils';
-import * as thunkActions from './app';
-
-jest.mock('./requests', () => ({
- initializeApp: (args) => ({ initializeApp: args }),
- batchUnlock: (args) => ({ batchUnlock: args }),
-}));
-
-const dispatch = jest.fn((action) => ({ dispatch: action }));
-const testState = { my: 'test state' };
-const getState = () => testState;
-const moduleKeys = keyStore(thunkActions);
-
-describe('app thunkActions', () => {
- let dispatchedAction;
- beforeEach(() => {
- jest.clearAllMocks();
- });
- describe('initialize', () => {
- beforeEach(() => {
- thunkActions.initialize()(dispatch);
- [[dispatchedAction]] = dispatch.mock.calls;
- });
- it('dispatches initializeApp with locationId and onSuccess', () => {
- expect(dispatchedAction.initializeApp.locationId).toEqual(locationId);
- expect(typeof dispatchedAction.initializeApp.onSuccess).toEqual('function');
- });
- describe('on success', () => {
- test('loads isEnabled, oraMetadata, courseMetadata and list data', () => {
- const response = {
- courseMetadata: { some: 'course-metadata' },
- isEnabled: { is: 'enabled?' },
- oraMetadata: { some: 'ora-metadata' },
- submissions: { some: 'submissions' },
- };
- dispatch.mockClear();
- dispatchedAction.initializeApp.onSuccess(response);
- expect(dispatch.mock.calls).toEqual([
- [actions.app.loadIsEnabled(response.isEnabled)],
- [actions.app.loadOraMetadata(response.oraMetadata)],
- [actions.app.loadCourseMetadata(response.courseMetadata)],
- [actions.submissions.loadList(response.submissions)],
- ]);
- });
- });
- });
- describe('cancelReview', () => {
- const gradingSelection = (args) => ({ gradingSelection: args });
- const mockInitialize = (args) => ({ initialize: args });
- const gradingKeys = keyStore(selectors.grading);
- beforeEach(() => {
- jest.spyOn(thunkActions, moduleKeys.initialize)
- .mockImplementationOnce(mockInitialize);
- jest.spyOn(selectors.grading, gradingKeys.selection)
- .mockImplementationOnce(gradingSelection);
- thunkActions.cancelReview()(dispatch, getState);
- [[dispatchedAction]] = dispatch.mock.calls;
- });
- it('dispatches batchUnlock with submissionUUIDs and onSuccess', () => {
- expect(dispatchedAction.batchUnlock.submissionUUIDs)
- .toEqual(gradingSelection(testState));
- expect(typeof dispatchedAction.batchUnlock.onSuccess).toEqual('function');
- });
- it('clears show review state and calls dispatches initialize thunkAction on success', () => {
- dispatch.mockClear();
- dispatchedAction.batchUnlock.onSuccess();
- expect(dispatch.mock.calls).toEqual([
- [actions.app.setShowReview(false)],
- [mockInitialize()],
- ]);
- });
- });
-});
diff --git a/src/data/redux/thunkActions/requests.test.js b/src/data/redux/thunkActions/requests.test.js
index 72e3262..2e2bfd8 100644
--- a/src/data/redux/thunkActions/requests.test.js
+++ b/src/data/redux/thunkActions/requests.test.js
@@ -1,16 +1,9 @@
import { actions } from 'data/redux';
-import { RequestKeys } from 'data/constants/requests';
-import api from 'data/services/lms/api';
+// import api from 'data/services/lms/api';
import * as requests from './requests';
jest.mock('data/services/lms/api', () => ({
- batchUnlockSubmissions: (submissionUUIDs) => ({ batchUnlockSubmissions: submissionUUIDs }),
- initializeApp: (locationId) => ({ initializeApp: locationId }),
- fetchSubmissionStatus: (submissionUUID) => ({ fetchSubmissionStatus: submissionUUID }),
- fetchSubmission: (submissionUUID) => ({ fetchSubmission: submissionUUID }),
- lockSubmission: ({ submissionUUID }) => ({ lockSubmission: { submissionUUID } }),
- unlockSubmission: ({ submissionUUID }) => ({ unlockSubmission: { submissionUUID } }),
- updateGrade: (submissionUUID, gradeData) => ({ updateGrade: { submissionUUID, gradeData } }),
+ // initializeList: (locationId) => ({ initializeList: locationId }),
}));
const dispatch = jest.fn();
@@ -91,6 +84,7 @@ describe('requests thunkActions module', () => {
});
});
+ /*
const testNetworkRequestAction = ({
action,
args,
@@ -117,92 +111,13 @@ describe('requests thunkActions module', () => {
});
});
};
+ */
describe('network request actions', () => {
- const submissionUUID = 'test-submission-id';
- const locationId = 'test-location-id';
beforeEach(() => {
requests.networkRequest = jest.fn(args => ({ networkRequest: args }));
});
- describe('initializeApp', () => {
- testNetworkRequestAction({
- action: requests.initializeApp,
- args: { locationId },
- expectedString: 'with initialize key, initializeApp promise',
- expectedData: {
- requestKey: RequestKeys.initialize,
- promise: api.initializeApp(locationId),
- },
- });
- });
- describe('fetchSubmissionStatus', () => {
- testNetworkRequestAction({
- action: requests.fetchSubmissionStatus,
- args: { submissionUUID },
- expectedString: 'with fetchSubmissionStatus promise',
- expectedData: {
- requestKey: RequestKeys.fetchSubmissionStatus,
- promise: api.fetchSubmissionStatus(submissionUUID),
- },
- });
- });
- describe('fetchSubmission', () => {
- testNetworkRequestAction({
- action: requests.fetchSubmission,
- args: { submissionUUID },
- expectedString: 'with fetchSubmission promise',
- expectedData: {
- requestKey: RequestKeys.fetchSubmission,
- promise: api.fetchSubmission(submissionUUID),
- },
- });
- });
- describe('setLock: true', () => {
- testNetworkRequestAction({
- action: requests.setLock,
- args: { submissionUUID, value: true },
- expectedString: 'with setLock promise',
- expectedData: {
- requestKey: RequestKeys.setLock,
- promise: api.lockSubmission(submissionUUID),
- },
- });
- });
- describe('setLock: false', () => {
- testNetworkRequestAction({
- action: requests.setLock,
- args: { submissionUUID, value: false },
- expectedString: 'with setLock promise',
- expectedData: {
- requestKey: RequestKeys.setLock,
- promise: api.unlockSubmission(submissionUUID),
- },
- });
- });
- describe('batchUnlock', () => {
- const submissionUUIDs = [1, 2, 3, 4, 5];
- testNetworkRequestAction({
- action: requests.batchUnlock,
- args: { submissionUUIDs, value: false },
- expectedString: 'with batchUnlock promise',
- expectedData: {
- requestKey: RequestKeys.batchUnlock,
- promise: api.batchUnlockSubmissions(submissionUUIDs),
- value: false,
- },
- });
- });
- describe('submitGrade', () => {
- const gradeData = 'test-grade-data';
- testNetworkRequestAction({
- action: requests.submitGrade,
- args: { submissionUUID, gradeData },
- expectedString: 'with submitGrade promise',
- expectedData: {
- requestKey: RequestKeys.submitGrade,
- promise: api.updateGrade(submissionUUID, gradeData),
- },
- });
+ describe('initializeList', () => {
});
});
});
diff --git a/src/index.test.jsx b/src/index.test.jsx
index 7c099e7..bd6dc20 100644
--- a/src/index.test.jsx
+++ b/src/index.test.jsx
@@ -35,6 +35,7 @@ jest.mock('@edx/frontend-platform', () => ({
jest.mock('@edx/frontend-component-footer', () => ({
messages: ['some', 'messages'],
}));
+jest.mock('data/store', () => ({ redux: 'store' }));
jest.mock('./App', () => 'App');
const testValue = 'my-test-value';
diff --git a/src/setupTest.jsx b/src/setupTest.jsx
index be5d5b1..2a96946 100755
--- a/src/setupTest.jsx
+++ b/src/setupTest.jsx
@@ -32,6 +32,7 @@ jest.mock('@edx/frontend-platform/i18n', () => {
),
formatDate: jest.fn().mockName('useIntl.formatDate'),
}),
+ IntlProvider: () => 'IntlProvider',
defineMessages: m => m,
FormattedMessage: () => 'FormattedMessage',
};
diff --git a/src/test/app.test.jsx b/src/test/app.test.jsx
index bd7021a..04a7a44 100644
--- a/src/test/app.test.jsx
+++ b/src/test/app.test.jsx
@@ -15,9 +15,7 @@ import thunk from 'redux-thunk';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import urls from 'data/services/lms/urls';
-import { ErrorStatuses, RequestKeys, RequestStates } from 'data/constants/requests';
-import { gradeStatuses, lockStatuses } from 'data/services/lms/constants';
-import fakeData from 'data/services/lms/fakeData';
+// import fakeData from 'data/services/lms/fakeData/courses';
import api from 'data/services/lms/api';
import reducers from 'data/redux';
import messages from 'i18n';
@@ -40,21 +38,6 @@ jest.mock('@edx/frontend-platform/auth', () => ({
getLoginRedirectUrl: jest.fn(),
}));
-jest.mock('react-pdf', () => ({
- Document: () => Document
,
- Image: () => Image
,
- Page: () => Page
,
- PDFViewer: jest.fn(() => null),
- StyleSheet: { create: () => {} },
- Text: () => Text
,
- View: () => View
,
- pdfjs: { GlobalWorkerOptions: {} },
-}));
-/*
-jest.mock('react-pdf/node_modules/pdfjs-dist/build/pdf.worker.entry', () => (
- jest.requireActual('react-pdf/dist/umd/entry.jest')
-));
-*/
const configureStore = () => redux.createStore(
reducers,
redux.compose(redux.applyMiddleware(thunk)),
@@ -66,8 +49,6 @@ let state;
let retryLink;
let inspector;
-const { rubricConfig } = fakeData.oraMetadata;
-
/**
* Simple wrapper for updating the top-level state variable, that also returns the new value
* @return {obj} - current redux store state
@@ -77,16 +58,6 @@ const getState = () => {
return state;
};
-/** Fake Data for quick access */
-const submissionUUIDs = [
- fakeData.ids.submissionUUID(0),
- fakeData.ids.submissionUUID(1),
- fakeData.ids.submissionUUID(2),
- fakeData.ids.submissionUUID(3),
- fakeData.ids.submissionUUID(4),
-];
-const submissions = submissionUUIDs.map(id => fakeData.mockSubmission(id));
-
/**
* Object to be filled with resolve/reject functions for all controlled network comm channels
*/
@@ -103,58 +74,7 @@ const mockForbiddenError = (reject) => () => reject(new Error({
}));
const mockApi = () => {
- api.initializeApp = jest.fn(() => new Promise(
- (resolve, reject) => {
- resolveFns.init = {
- success: () => resolve({
- isEnabled: true,
- oraMetadata: fakeData.oraMetadata,
- courseMetadata: fakeData.courseMetadata,
- submissions: fakeData.submissions,
- }),
- networkError: mockNetworkError(reject),
- };
- },
- ));
- api.fetchSubmission = jest.fn((submissionUUID) => new Promise(
- (resolve, reject) => {
- resolveFns.fetch = {
- success: () => resolve(fakeData.mockSubmission(submissionUUID)),
- networkError: mockNetworkError(reject),
- };
- },
- ));
- api.fetchSubmissionStatus = jest.fn((submissionUUID) => Promise.resolve(
- fakeData.mockSubmissionStatus(submissionUUID)
- ));
- api.lockSubmission = jest.fn(() => new Promise(
- (resolve, reject) => {
- resolveFns.lock = {
- success: () => resolve({ lockStatus: lockStatuses.inProgress }),
- networkError: mockForbiddenError(reject),
- };
- },
- ));
- api.unlockSubmission = jest.fn(() => new Promise(
- (resolve, reject) => {
- resolveFns.unlock = {
- success: () => resolve({ lockStatus: lockStatuses.unlocked }),
- networkError: mockNetworkError(reject),
- };
- },
- ));
- api.updateGrade = jest.fn((uuid, gradeData) => new Promise(
- (resolve, reject) => {
- resolveFns.updateGrade = {
- success: () => resolve({
- gradeData,
- gradeStatus: gradeStatuses.graded,
- lockStatus: lockStatuses.unlocked,
- }),
- networkError: mockNetworkError(reject),
- };
- },
- ));
+ api.initializeList = jest.fn(() => new Promise());
};
/**
@@ -172,344 +92,17 @@ const renderEl = async () => {
getState();
};
-/**
- * resolve the initalization promise, and update state object
- */
-const initialize = async () => {
- resolveFns.init.success();
- await inspector.find.listView.viewAllResponsesBtn();
- getState();
-};
-
-/**
- * Select the first 5 entries in the table and click the 'View Selected Responses' button
- * Wait for the review page to show and update the top-level state object.
- */
-const makeTableSelections = async () => {
- [0, 1, 2, 3, 4].forEach(index => userEvent.click(inspector.listView.listCheckbox(index)));
- userEvent.click(inspector.listView.selectedBtn(5));
- // wait for navigation, which will show while request is pending
- try {
- await inspector.find.review.prevNav();
- } catch (e) {
- throw(e);
- }
- getState();
-};
-
-const waitForEqual = async (valFn, expected, key) => waitFor(() => {
- expect(valFn(), `${key} is expected to equal ${expected}`).toEqual(expected);
-});
-const waitForRequestStatus = (key, status) => waitForEqual(
- () => getState().requests[key].status,
- status,
- key,
-);
-
-describe('ESG app integration tests', () => {
+describe('Learner Dashbpard app integration tests', () => {
beforeEach(async () => {
mockApi();
await renderEl();
- inspector = new Inspector(el);
+ // inspector = new Inspector(el);
});
test('initialization', async (done) => {
- const verifyInitialState = async () => {
- await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
- const testInitialState = (key) => expect(
- state[key],
- `${key} store should have its configured initial state`,
- ).toEqual(
- jest.requireActual(`data/redux/${key}/reducer`).initialState,
- );
- testInitialState('app');
- testInitialState('submissions');
- testInitialState('grading');
- expect(
- inspector.listView.loadingResponses(),
- 'Loading Responses pending state text should be displayed in the ListView',
- ).toBeVisible();
- }
- await verifyInitialState();
-
- // initialization network error
- const forceAndVerifyInitNetworkError = async () => {
- resolveFns.init.networkError();
- await waitForRequestStatus(RequestKeys.initialize, RequestStates.failed);
- expect(
- await inspector.find.listView.loadErrorHeading(),
- 'List Error should be available (by heading component)',
- ).toBeVisible();
- const backLink = inspector.listView.backLink();
- expect(
- backLink.href,
- 'Back to responses button href should link to urls.openResponse(courseId)',
- ).toEqual(urls.openResponse(getState().app.courseMetadata.courseId));
- };
- await forceAndVerifyInitNetworkError();
-
- // initialization retry/pending
- retryLink = inspector.listView.reloadBtn();
- await userEvent.click(retryLink);
- await waitForRequestStatus(RequestKeys.initialize, RequestStates.pending);
-
- // initialization success
- const forceAndVerifyInitSuccess = async () => {
- await initialize();
- await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
- expect(
- state.app.courseMetadata,
- 'Course metadata in redux should be populated with fake data',
- ).toEqual(fakeData.courseMetadata);
- expect(
- state.app.oraMetadata,
- 'ORA metadata in redux should be populated with fake data',
- ).toEqual(fakeData.oraMetadata);
- expect(
- state.submissions.allSubmissions,
- 'submissions data in redux should be populated with fake data',
- ).toEqual(fakeData.submissions);
- };
- await forceAndVerifyInitSuccess();
-
- await makeTableSelections();
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
done();
});
describe('initialized', () => {
- beforeEach(async () => {
- await initialize();
- await waitForRequestStatus(RequestKeys.initialize, RequestStates.completed);
- await makeTableSelections();
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
- });
-
- test('initial review state', async (done) => {
- // Make table selection and load Review pane
- expect(
- state.grading.selection,
- 'submission IDs should be loaded',
- ).toEqual(submissionUUIDs);
- expect(state.app.showReview, 'app store should have showReview: true').toEqual(true);
- expect(inspector.review.username(0), 'username should be visible').toBeVisible();
- const nextNav = inspector.review.nextNav();
- const prevNav = inspector.review.prevNav();
- expect(nextNav, 'next nav should be displayed').toBeVisible();
- expect(nextNav, 'next nav should be disabled').toHaveAttribute('disabled');
- expect(prevNav, 'prev nav should be displayed').toBeVisible();
- expect(prevNav, 'prev nav should be disabled').toHaveAttribute('disabled');
- expect(
- inspector.review.loadingResponse(),
- 'Loading Responses pending state text should be displayed in the ReviewModal',
- ).toBeVisible();
- done();
- });
-
- test('fetch network error and retry', async (done) => {
- await resolveFns.fetch.networkError();
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.failed);
- expect(
- await inspector.find.review.loadErrorHeading(),
- 'Load Submission error should be displayed in ReviewModal',
- ).toBeVisible();
- // fetch: retry and succeed
- await userEvent.click(inspector.review.retryFetchLink());
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.pending);
- done()
- });
-
- test('fetch success and nav chain', async (done) => {
- let showRubric = false;
- // fetch: success with chained navigation
- const verifyFetchSuccess = async (submissionIndex) => {
- const submissionString = `for submission ${submissionIndex}`;
- const submission = submissions[submissionIndex];
- const forceAndVerifyFetchSuccess = async () => {
- await resolveFns.fetch.success();
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.completed);
- expect(
- inspector.review.gradingStatus(submission),
- `Should display current submission grading status ${submissionString}`,
- ).toBeVisible();
- };
- await forceAndVerifyFetchSuccess();
-
- showRubric = showRubric || selectors.grading.selected.isGrading(getState());
-
- const verifyRubricVisibility = async () => {
- getState();
- expect(
- state.app.showRubric,
- `${showRubric ? 'Should' : 'Should not'} show rubric ${submissionString}`,
- ).toEqual(showRubric);
- if (showRubric) {
- expect(
- inspector.review.hideRubricBtn(),
- `Hide Rubric button should be visible when rubric is shown ${submissionString}`,
- ).toBeVisible();
-
- } else {
- expect(
- inspector.review.showRubricBtn(),
- `Show Rubric button should be visible when rubric is hidden ${submissionString}`,
- ).toBeVisible();
- }
- }
- await verifyRubricVisibility();
-
- // loads current submission
- const testSubmissionGradingState = () => {
- expect(
- state.grading.current,
- `Redux current grading state should load the current submission ${submissionString}`,
- ).toEqual({
- submissionUUID: submissionUUIDs[submissionIndex],
- ...submissions[submissionIndex],
- });
- };
- testSubmissionGradingState();
-
- const testNavState = () => {
- const expectDisabled = (getNav, name) => (
- expect(getNav(), `${name} should be disabled`).toHaveAttribute('disabled')
- );
- const expectEnabled = (getNav, name) => (
- expect(getNav(), `${name} should be enabled`).not.toHaveAttribute('disabled')
- );
- (submissionIndex > 0 ? expectEnabled : expectDisabled)(
- inspector.review.prevNav,
- 'Prev nav',
- );
- const hasNext = submissionIndex < submissions.length - 1;
- (hasNext ? expectEnabled : expectDisabled)(inspector.review.nextNav, 'Next nav');
- };
- testNavState();
- };
- await verifyFetchSuccess(0);
- for (let i = 1; i < 5; i++) {
- await userEvent.click(inspector.review.nextNav());
- await verifyFetchSuccess(i);
- }
- for (let i = 3; i >= 0; i--) {
- await userEvent.click(inspector.review.prevNav());
- await verifyFetchSuccess(i);
- }
- done();
- });
-
- describe('grading (basic)', () => {
- beforeEach(async () => {
- await resolveFns.fetch.success();
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.completed);
- await userEvent.click(await inspector.find.review.startGradingBtn());
- });
-
- describe('active grading', () => {
- beforeEach(async () => {
- await resolveFns.lock.success();
- });
-
- const selectedOptions = [1, 2];
- const feedback = ['feedback 0', 'feedback 1'];
- const overallFeedback = 'some overall feedback';
-
- // Set basic grade and feedback
- const setGrade = async (done) => {
- const {
- criterionOption,
- criterionFeedback,
- feedbackInput,
- } = inspector.review.rubric;
- const options = [
- criterionOption(0, selectedOptions[0]),
- criterionOption(1, selectedOptions[1]),
- ];
- await userEvent.click(options[0]);
- await userEvent.type(criterionFeedback(0), feedback[0]);
- await userEvent.click(options[1]);
- await userEvent.type(criterionFeedback(1), feedback[1]);
- await userEvent.type(inspector.review.rubric.feedbackInput(), overallFeedback);
- return;
- };
-
- // Verify active-grading state
- const checkGradingState = (submissionUUID=submissionUUIDs[0]) => {
- const entry = getState().grading.gradingData[submissionUUID];
- const checkCriteria = (index) => {
- const criterion = entry.criteria[index];
- const selected = rubricConfig.criteria[index].options[selectedOptions[index]].name;
- expect(criterion.selectedOption).toEqual(selected);
- expect(criterion.feedback).toEqual(feedback[index]);
- }
- [0, 1].forEach(checkCriteria);
- expect(entry.overallFeedback).toEqual(overallFeedback);
- }
-
- // Verify after-submission-success grade state
- const checkGradeSuccess = () => {
- const { gradeData, current } = getState().grading;
- const entry = gradeData[submissionUUIDs[0]];
- const checkCriteria = (index) => {
- const criterion = entry.criteria[index];
- const rubricOptions = rubricConfig.criteria[index].options;
- expect(criterion.selectedOption).toEqual(rubricOptions[selectedOptions[index]].name);
- expect(criterion.feedback).toEqual(feedback[index]);
- }
- [0, 1].forEach(checkCriteria);
- expect(entry.overallFeedback).toEqual(overallFeedback);
- expect(current.gradeStatus).toEqual(gradeStatuses.graded);
- expect(current.lockStatus).toEqual(lockStatuses.unlocked);
- }
-
- const loadNext = async () => {
- await userEvent.click(inspector.review.nextNav());
- await resolveFns.fetch.success();
- };
-
- const loadPrev = async () => {
- await userEvent.click(inspector.review.prevNav());
- await resolveFns.fetch.success();
- }
-
- const startGrading = async () => {
- await waitForRequestStatus(RequestKeys.fetchSubmission, RequestStates.completed);
- await userEvent.click(await inspector.find.review.startGradingBtn());
- await resolveFns.lock.success();
- }
- /*
- test('submit pending', async (done) => {
- done();
- });
- test('submit failed', async (done) => {
- done();
- });
- */
- test('grade and submit',
- async (done) => {
- expect(await inspector.find.review.submitGradeBtn()).toBeVisible();
- await setGrade();
- checkGradingState();
- await userEvent.click(inspector.review.rubric.submitGradeBtn());
- await resolveFns.updateGrade.success();
- checkGradeSuccess();
- done();
- },
- );
- test('grade, navigate, and return, maintaining gradingState',
- async (done) => {
- expect(await inspector.find.review.submitGradeBtn()).toBeVisible();
- await setGrade();
- checkGradingState();
- await loadNext();
- await waitForEqual(() => getState().grading.activeIndex, 1, 'activeIndex');
- await loadPrev();
- await waitForEqual(() => getState().grading.activeIndex, 0, 'activeIndex');
- checkGradingState();
- done();
- },
- );
- });
- });
});
});