,
+jest.mock('../../editors/sharedComponents/TinyMceWidget', () => ({
+ __esModule: true, // Required to mock a default export
+ default: () =>
Widget
,
prepareEditorRef: jest.fn(() => ({
refReady: true,
setEditorRef: jest.fn().mockName('prepareEditorRef.setEditorRef'),
diff --git a/src/custom-pages/CustomPages.jsx b/src/custom-pages/CustomPages.jsx
index 5d16dbf713..f5392abf8b 100644
--- a/src/custom-pages/CustomPages.jsx
+++ b/src/custom-pages/CustomPages.jsx
@@ -18,11 +18,9 @@ import {
Container,
} from '@openedx/paragon';
import { Add, SpinnerSimple } from '@openedx/paragon/icons';
-import Placeholder, {
- DraggableList,
- SortableItem,
- ErrorAlert,
-} from '@edx/frontend-lib-content-components';
+import Placeholder from '../editors/Placeholder';
+import DraggableList, { SortableItem } from '../editors/sharedComponents/DraggableList';
+import ErrorAlert from '../editors/sharedComponents/ErrorAlerts/ErrorAlert';
import { RequestStatus } from '../data/constants';
import { useModels, useModel } from '../generic/model-store';
diff --git a/src/custom-pages/EditModal.jsx b/src/custom-pages/EditModal.jsx
index 0f540c74ec..e89b39b827 100644
--- a/src/custom-pages/EditModal.jsx
+++ b/src/custom-pages/EditModal.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { getConfig } from '@edx/frontend-platform';
-import { EditorPage } from '@edx/frontend-lib-content-components';
+import EditorPage from '../editors/EditorPage';
const EditModal = ({
pageId,
diff --git a/src/editors/Editor.jsx b/src/editors/Editor.jsx
index 18ead54a01..044c773f26 100644
--- a/src/editors/Editor.jsx
+++ b/src/editors/Editor.jsx
@@ -8,7 +8,7 @@ import * as hooks from './hooks';
import supportedEditors from './supportedEditors';
-export const Editor = ({
+const Editor = ({
learningContextId,
blockType,
blockId,
diff --git a/src/editors/Editor.test.jsx b/src/editors/Editor.test.jsx
index d2f09629b0..fa19e60689 100644
--- a/src/editors/Editor.test.jsx
+++ b/src/editors/Editor.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { useDispatch } from 'react-redux';
import { shallow } from '@edx/react-unit-test-utils';
-import { Editor } from './Editor';
+import Editor from './Editor';
import supportedEditors from './supportedEditors';
import * as hooks from './hooks';
import { blockTypes } from './data/constants/app';
diff --git a/src/editors/EditorContainer.jsx b/src/editors/EditorContainer.jsx
index c9e821daf7..34ca5ba631 100644
--- a/src/editors/EditorContainer.jsx
+++ b/src/editors/EditorContainer.jsx
@@ -1,9 +1,10 @@
import React from 'react';
import PropTypes from 'prop-types';
import { useParams } from 'react-router-dom';
-import { EditorPage } from '@edx/frontend-lib-content-components';
import { getConfig } from '@edx/frontend-platform';
+import EditorPage from './EditorPage';
+
const EditorContainer = ({
courseId,
}) => {
diff --git a/src/editors/EditorContainer.test.jsx b/src/editors/EditorContainer.test.jsx
index bee812eff5..a6186050ae 100644
--- a/src/editors/EditorContainer.test.jsx
+++ b/src/editors/EditorContainer.test.jsx
@@ -2,8 +2,6 @@ import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import EditorContainer from './EditorContainer';
-jest.mock('@edx/frontend-lib-content-components', () => ({ EditorPage: () => 'HeaderTitle' }));
-
jest.mock('react-router', () => ({
...jest.requireActual('react-router'), // use actual for all non-hook parts
useParams: () => ({
diff --git a/src/editors/EditorPage.jsx b/src/editors/EditorPage.jsx
index 2b717d4116..60de6e1cc6 100644
--- a/src/editors/EditorPage.jsx
+++ b/src/editors/EditorPage.jsx
@@ -6,7 +6,7 @@ import store from './data/store';
import Editor from './Editor';
import ErrorBoundary from './sharedComponents/ErrorBoundary';
-export const EditorPage = ({
+const EditorPage = ({
courseId,
blockType,
blockId,
diff --git a/src/editors/Placeholder.test.jsx b/src/editors/Placeholder.test.jsx
index 1025e1ad33..186bc9d781 100644
--- a/src/editors/Placeholder.test.jsx
+++ b/src/editors/Placeholder.test.jsx
@@ -4,7 +4,7 @@ import TestRenderer from 'react-test-renderer';
import { AppContext } from '@edx/frontend-platform/react';
import { Context as ResponsiveContext } from 'react-responsive';
-import Placeholder from '../index';
+import Placeholder from './Placeholder';
describe('', () => {
it('renders correctly', () => {
diff --git a/src/editors/VideoSelector.jsx b/src/editors/VideoSelector.jsx
index a427eb1e6b..4711b76cfc 100644
--- a/src/editors/VideoSelector.jsx
+++ b/src/editors/VideoSelector.jsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import VideoGallery from './containers/VideoGallery';
import * as hooks from './hooks';
-export const VideoSelector = ({
+const VideoSelector = ({
blockId,
learningContextId,
lmsEndpointUrl,
diff --git a/src/editors/VideoSelector.test.jsx b/src/editors/VideoSelector.test.jsx
index aa55253f8c..f3d0e60ae3 100644
--- a/src/editors/VideoSelector.test.jsx
+++ b/src/editors/VideoSelector.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { useDispatch } from 'react-redux';
import { shallow } from '@edx/react-unit-test-utils';
diff --git a/src/editors/__snapshots__/EditorContainer.test.jsx.snap b/src/editors/__snapshots__/EditorContainer.test.jsx.snap
index e6c223bef8..c742c7a606 100644
--- a/src/editors/__snapshots__/EditorContainer.test.jsx.snap
+++ b/src/editors/__snapshots__/EditorContainer.test.jsx.snap
@@ -9,6 +9,8 @@ exports[`Editor Container snapshots rendering correctly with expected Input 1`]
blockType="html"
courseId="cOuRsEId"
lmsEndpointUrl="http://localhost:18000"
+ onClose={null}
+ returnFunction={null}
studioEndpointUrl="http://localhost:18010"
/>
diff --git a/src/editors/__snapshots__/Placeholder.test.jsx.snap b/src/editors/__snapshots__/Placeholder.test.jsx.snap
new file mode 100644
index 0000000000..f504cf0632
--- /dev/null
+++ b/src/editors/__snapshots__/Placeholder.test.jsx.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders correctly 1`] = `
+
+
+ Under Construction
+
+ Coming Soon
+
+
+`;
diff --git a/src/editors/containers/EditorContainer/components/EditorFooter/index.jsx b/src/editors/containers/EditorContainer/components/EditorFooter/index.jsx
index 4376ab38d8..20c2f2d560 100644
--- a/src/editors/containers/EditorContainer/components/EditorFooter/index.jsx
+++ b/src/editors/containers/EditorContainer/components/EditorFooter/index.jsx
@@ -12,7 +12,7 @@ import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/
import messages from './messages';
-export const EditorFooter = ({
+const EditorFooter = ({
clearSaveFailed,
disableSave,
onCancel,
@@ -60,4 +60,5 @@ EditorFooter.propTypes = {
intl: intlShape.isRequired,
};
+export const EditorFooterInternal = EditorFooter; // For testing only
export default injectIntl(EditorFooter);
diff --git a/src/editors/containers/EditorContainer/components/EditorFooter/index.test.jsx b/src/editors/containers/EditorContainer/components/EditorFooter/index.test.jsx
index 97f3f72dfa..aaa78980a2 100644
--- a/src/editors/containers/EditorContainer/components/EditorFooter/index.test.jsx
+++ b/src/editors/containers/EditorContainer/components/EditorFooter/index.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../testUtils';
-import { EditorFooter } from '.';
+import { formatMessage } from '../../../../testUtils';
+import { EditorFooterInternal as EditorFooter } from '.';
jest.mock('../../hooks', () => ({
nullMethod: jest.fn().mockName('hooks.nullMethod'),
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.jsx
index bf2ca571d0..32d64e52c4 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.jsx
@@ -7,7 +7,7 @@ import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import messages from './messages';
-export const EditConfirmationButtons = ({
+const EditConfirmationButtons = ({
updateTitle,
cancelEdit,
// injected
@@ -37,4 +37,5 @@ EditConfirmationButtons.propTypes = {
// injected
intl: intlShape.isRequired,
};
+export const EditConfirmationButtonsInternal = EditConfirmationButtons; // For testing only
export default injectIntl(EditConfirmationButtons);
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.test.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.test.jsx
index 65619c46c1..99361275a9 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.test.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/EditConfirmationButtons.test.jsx
@@ -1,7 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../testUtils';
-import * as module from './EditConfirmationButtons';
+import { formatMessage } from '../../../../testUtils';
+
+import { EditConfirmationButtonsInternal as EditConfirmationButtons } from './EditConfirmationButtons';
describe('EditConfirmationButtons', () => {
const props = {
@@ -11,7 +13,7 @@ describe('EditConfirmationButtons', () => {
};
describe('snapshot', () => {
test('snapshot', () => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
});
});
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.jsx
index bacd05f250..fe51bcd337 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.jsx
@@ -2,9 +2,9 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Form } from '@openedx/paragon';
-import EditConfirmationButtons from './EditConfirmationButtons';
+import { EditConfirmationButtonsInternal as EditConfirmationButtons } from './EditConfirmationButtons';
-export const EditableHeader = ({
+const EditableHeader = ({
handleChange,
updateTitle,
handleKeyDown,
@@ -41,4 +41,5 @@ EditableHeader.propTypes = {
cancelEdit: PropTypes.func.isRequired,
};
+export const EditableHeaderInternal = EditableHeader; // For testing only
export default EditableHeader;
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.test.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.test.jsx
index 929000c2b3..66c1705856 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.test.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/EditableHeader.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { Form } from '@openedx/paragon';
-import * as module from './EditableHeader';
-import EditConfirmationButtons from './EditConfirmationButtons';
+import { EditableHeaderInternal as EditableHeader } from './EditableHeader';
+import { EditConfirmationButtonsInternal as EditConfirmationButtons } from './EditConfirmationButtons';
describe('EditableHeader', () => {
const props = {
@@ -15,7 +16,7 @@ describe('EditableHeader', () => {
};
let el;
beforeEach(() => {
- el = shallow();
+ el = shallow();
});
describe('snapshot', () => {
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/__snapshots__/EditableHeader.test.jsx.snap b/src/editors/containers/EditorContainer/components/TitleHeader/__snapshots__/EditableHeader.test.jsx.snap
index d47c195548..0d202841d6 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/__snapshots__/EditableHeader.test.jsx.snap
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/__snapshots__/EditableHeader.test.jsx.snap
@@ -15,7 +15,7 @@ exports[`EditableHeader snapshot snapshot 1`] = `
}
}
trailingElement={
-
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/hooks.js b/src/editors/containers/EditorContainer/components/TitleHeader/hooks.js
index 62ac756a36..d64801c071 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/hooks.js
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/hooks.js
@@ -3,6 +3,10 @@ import { useSelector } from 'react-redux';
import { actions, selectors } from '../../../../data/redux';
import * as textEditorHooks from '../../hooks';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const { navigateCallback } = textEditorHooks;
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/hooks.test.js b/src/editors/containers/EditorContainer/components/TitleHeader/hooks.test.js
index 7bc6869553..8698282021 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/hooks.test.js
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/hooks.test.js
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { useSelector } from 'react-redux';
import { actions, selectors } from '../../../../data/redux';
-import { MockUseState } from '../../../../../testUtils';
+import { MockUseState } from '../../../../testUtils';
import * as hooks from './hooks';
jest.mock('react', () => {
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/index.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/index.jsx
index 1e63ce80cf..8e3f017bce 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/index.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/index.jsx
@@ -11,7 +11,7 @@ import { localTitleHooks } from './hooks';
import messages from './messages';
import EditableHeader from './EditableHeader';
-export const TitleHeader = ({
+const TitleHeader = ({
isInitialized,
// injected
intl,
@@ -70,4 +70,5 @@ TitleHeader.propTypes = {
intl: intlShape.isRequired,
};
+export const TitleHeaderInternal = TitleHeader; // For testing only
export default injectIntl(TitleHeader);
diff --git a/src/editors/containers/EditorContainer/components/TitleHeader/index.test.jsx b/src/editors/containers/EditorContainer/components/TitleHeader/index.test.jsx
index 0672d5b278..6366e1c758 100644
--- a/src/editors/containers/EditorContainer/components/TitleHeader/index.test.jsx
+++ b/src/editors/containers/EditorContainer/components/TitleHeader/index.test.jsx
@@ -1,10 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { useDispatch } from 'react-redux';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../testUtils';
+import { formatMessage } from '../../../../testUtils';
import { localTitleHooks } from './hooks';
-import * as module from '.';
+import { TitleHeaderInternal as TitleHeader } from '.';
jest.mock('./hooks', () => ({
localTitleHooks: jest.fn(),
@@ -37,7 +38,7 @@ describe('TitleHeader', () => {
describe('behavior', () => {
it(' calls localTitleHooks with initialization args', () => {
localTitleHooks.mockReturnValue(localTitleHooksProps);
- shallow();
+ shallow();
const dispatch = useDispatch();
expect(localTitleHooks).toHaveBeenCalledWith({
dispatch,
@@ -47,15 +48,15 @@ describe('TitleHeader', () => {
describe('snapshots', () => {
test('not initialized', () => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
test('initialized', () => {
localTitleHooks.mockReturnValue(localTitleHooksProps);
- expect(shallow().shallowWrapper).toMatchSnapshot();
+ expect(shallow().shallowWrapper).toMatchSnapshot();
});
test('editing', () => {
localTitleHooks.mockReturnValue({ ...localTitleHooksProps, isEditing: true });
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
});
});
diff --git a/src/editors/containers/EditorContainer/hooks.js b/src/editors/containers/EditorContainer/hooks.js
index caae0263d6..72b8a0e20f 100644
--- a/src/editors/containers/EditorContainer/hooks.js
+++ b/src/editors/containers/EditorContainer/hooks.js
@@ -6,6 +6,10 @@ import { RequestKeys } from '../../data/constants/requests';
import { selectors } from '../../data/redux';
import { StrictDict } from '../../utils';
import * as appHooks from '../../hooks';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const {
diff --git a/src/editors/containers/EditorContainer/hooks.test.jsx b/src/editors/containers/EditorContainer/hooks.test.jsx
index c2e4d46499..e73534f5b3 100644
--- a/src/editors/containers/EditorContainer/hooks.test.jsx
+++ b/src/editors/containers/EditorContainer/hooks.test.jsx
@@ -1,5 +1,6 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import * as reactRedux from 'react-redux';
-import { MockUseState } from '../../../testUtils';
+import { MockUseState } from '../../testUtils';
import { RequestKeys } from '../../data/constants/requests';
import { selectors } from '../../data/redux';
diff --git a/src/editors/containers/EditorContainer/index.jsx b/src/editors/containers/EditorContainer/index.jsx
index f568257a61..5c80cbce79 100644
--- a/src/editors/containers/EditorContainer/index.jsx
+++ b/src/editors/containers/EditorContainer/index.jsx
@@ -15,7 +15,7 @@ import * as hooks from './hooks';
import messages from './messages';
import './index.scss';
-export const EditorContainer = ({
+const EditorContainer = ({
children,
getContent,
onClose,
@@ -99,4 +99,5 @@ EditorContainer.propTypes = {
intl: intlShape.isRequired,
};
+export const EditorContainerInternal = EditorContainer; // For testing only
export default injectIntl(EditorContainer);
diff --git a/src/editors/containers/EditorContainer/index.test.jsx b/src/editors/containers/EditorContainer/index.test.jsx
index c0068955aa..5360fdb7de 100644
--- a/src/editors/containers/EditorContainer/index.test.jsx
+++ b/src/editors/containers/EditorContainer/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import { useDispatch } from 'react-redux';
-import { EditorContainer } from '.';
+import { EditorContainerInternal as EditorContainer } from '.';
import * as hooks from './hooks';
-import { formatMessage } from '../../../testUtils';
+import { formatMessage } from '../../testUtils';
const props = {
getContent: jest.fn().mockName('props.getContent'),
diff --git a/src/editors/containers/GameEditor/index.jsx b/src/editors/containers/GameEditor/index.jsx
index b6e0f9ad77..e14c3bad0f 100644
--- a/src/editors/containers/GameEditor/index.jsx
+++ b/src/editors/containers/GameEditor/index.jsx
@@ -1,3 +1,5 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+/* eslint-disable no-unused-vars */
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */
/**
@@ -6,8 +8,6 @@
* To use run npm run-script addXblock
*/
-/* eslint-disable no-unused-vars */
-
import React from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
@@ -16,6 +16,10 @@ import { Spinner } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import EditorContainer from '../EditorContainer';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from '.';
import { actions, selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
index bac86c98ae..8ac30a31c4 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.jsx
@@ -18,7 +18,7 @@ import * as hooks from './hooks';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
import ExpandableTextArea from '../../../../../sharedComponents/ExpandableTextArea';
-export const AnswerOption = ({
+const AnswerOption = ({
answer,
hasSingleAnswer,
// injected
@@ -142,4 +142,5 @@ export const mapStateToProps = (state) => ({
});
export const mapDispatchToProps = {};
+export const AnswerOptionInternal = AnswerOption; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(memo(AnswerOption)));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
index 862b3b2140..7ef58f6d9a 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswerOption.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
+import { formatMessage } from '../../../../../testUtils';
import { selectors } from '../../../../../data/redux';
-import { AnswerOption, mapStateToProps } from './AnswerOption';
+import { AnswerOptionInternal as AnswerOption, mapStateToProps } from './AnswerOption';
jest.mock('../../../../../data/redux', () => ({
__esModule: true,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
index 2b1efbe968..1a5d547cb4 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.jsx
@@ -13,7 +13,7 @@ import AnswerOption from './AnswerOption';
import Button from '../../../../../sharedComponents/Button';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
-export const AnswersContainer = ({
+const AnswersContainer = ({
problemType,
// Redux
answers,
@@ -95,4 +95,5 @@ export const mapDispatchToProps = {
updateField: actions.problem.updateField,
};
+export const AnswersContainerInternal = AnswersContainer; // For testing only
export default connect(mapStateToProps, mapDispatchToProps)(AnswersContainer);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx
index 1445c0cdd4..c52933af2d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/AnswersContainer.test.jsx
@@ -1,13 +1,12 @@
/* eslint-disable react/prop-types */
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { act, render, waitFor } from '@testing-library/react';
import { actions, selectors } from '../../../../../data/redux';
-import * as module from './AnswersContainer';
-
-import { AnswersContainer as AnswersContainerWithoutHOC } from './AnswersContainer';
+import { AnswersContainerInternal as AnswersContainer, mapStateToProps, mapDispatchToProps } from './AnswersContainer';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
jest.mock('@edx/frontend-platform/i18n', () => ({
@@ -44,13 +43,13 @@ describe('AnswersContainer', () => {
describe('render', () => {
test('snapshot: renders correct default', () => {
act(() => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
});
test('snapshot: renders correctly with answers', () => {
act(() => {
expect(shallow(
- ,
@@ -67,7 +66,7 @@ describe('AnswersContainer', () => {
addAnswerRange: jest.fn(),
};
expect(shallow(
- ,
).snapshot).toMatchSnapshot();
@@ -90,7 +89,7 @@ describe('AnswersContainer', () => {
addAnswerRange: jest.fn(),
};
expect(shallow(
- ,
).snapshot).toMatchSnapshot();
@@ -122,7 +121,7 @@ describe('AnswersContainer', () => {
addAnswerRange: jest.fn(),
};
expect(shallow(
- ,
).snapshot).toMatchSnapshot();
@@ -133,7 +132,7 @@ describe('AnswersContainer', () => {
let container = null;
await act(async () => {
const wrapper = render(
- ,
@@ -142,7 +141,7 @@ describe('AnswersContainer', () => {
});
await waitFor(() => expect(container.querySelector('button')).toBeTruthy());
- await new Promise(resolve => setTimeout(resolve, 500));
+ await new Promise(resolve => { setTimeout(resolve, 500); });
expect(props.updateField).toHaveBeenCalledWith(expect.objectContaining({ correctAnswerCount: 2 }));
});
@@ -151,16 +150,16 @@ describe('AnswersContainer', () => {
const testState = { A: 'pple', B: 'anana', C: 'ucumber' };
test('answers from problem.answers', () => {
expect(
- module.mapStateToProps(testState).answers,
+ mapStateToProps(testState).answers,
).toEqual(selectors.problem.answers(testState));
});
});
describe('mapDispatchToProps', () => {
test('updateField from actions.problem.updateField', () => {
- expect(module.mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
+ expect(mapDispatchToProps.updateField).toEqual(actions.problem.updateField);
});
test('updateField from actions.problem.addAnswer', () => {
- expect(module.mapDispatchToProps.addAnswer).toEqual(actions.problem.addAnswer);
+ expect(mapDispatchToProps.addAnswer).toEqual(actions.problem.addAnswer);
});
});
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
index 46653ced11..1f99057ac2 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Checker/index.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import Checker from '.';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.jsx
index 13a850af02..7fb51bf491 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/components/Feedback/FeedbackControl.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import FeedbackControl from './FeedbackControl';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
index 0d7b423f6b..b1e9585cf6 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.js
@@ -1,5 +1,9 @@
import { useState, useEffect } from 'react';
import { StrictDict } from '../../../../../utils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { actions } from '../../../../../data/redux';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
index 6aa791c6a3..9614e635f3 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/hooks.test.js
@@ -1,9 +1,14 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { actions } from '../../../../../data/redux';
-import { MockUseState } from '../../../../../../testUtils';
+import { MockUseState } from '../../../../../testUtils';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
jest.mock('react', () => {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/index.jsx
index 4e3045262b..c7e865212e 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/AnswerWidget/index.jsx
@@ -34,4 +34,5 @@ AnswerWidget.propTypes = {
// injected
intl: intlShape.isRequired,
};
+export const AnswerWidgetInternal = AnswerWidget; // For testing only
export default injectIntl(AnswerWidget);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
index 86298d5d95..16bdbab9a7 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.jsx
@@ -8,7 +8,7 @@ import messages from './messages';
import TinyMceWidget from '../../../../../sharedComponents/TinyMceWidget';
import { prepareEditorRef, replaceStaticWithAsset } from '../../../../../sharedComponents/TinyMceWidget/hooks';
-export const ExplanationWidget = ({
+const ExplanationWidget = ({
// redux
settings,
learningContextId,
@@ -57,4 +57,5 @@ export const mapStateToProps = (state) => ({
learningContextId: selectors.app.learningContextId(state),
});
+export const ExplanationWidgetInternal = ExplanationWidget; // For testing only
export default injectIntl(connect(mapStateToProps)(ExplanationWidget));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx
index 6e22712c2c..062330c190 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/ExplanationWidget/index.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
+import { formatMessage } from '../../../../../testUtils';
import { selectors } from '../../../../../data/redux';
-import { ExplanationWidget, mapStateToProps } from '.';
+import { ExplanationWidgetInternal as ExplanationWidget, mapStateToProps } from '.';
jest.mock('../../../../../data/redux', () => ({
__esModule: true,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
index 5580975bf7..a0ecde82a1 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.jsx
@@ -8,7 +8,7 @@ import messages from './messages';
import TinyMceWidget from '../../../../../sharedComponents/TinyMceWidget';
import { prepareEditorRef, replaceStaticWithAsset } from '../../../../../sharedComponents/TinyMceWidget/hooks';
-export const QuestionWidget = ({
+const QuestionWidget = ({
// redux
question,
learningContextId,
@@ -53,4 +53,5 @@ export const mapStateToProps = (state) => ({
learningContextId: selectors.app.learningContextId(state),
});
+export const QuestionWidgetInternal = QuestionWidget; // For testing only
export default injectIntl(connect(mapStateToProps)(QuestionWidget));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx
index 6602eb1ae2..c867da970a 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/QuestionWidget/index.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
+import { formatMessage } from '../../../../../testUtils';
import { selectors } from '../../../../../data/redux';
-import { QuestionWidget, mapStateToProps } from '.';
+import { QuestionWidgetInternal as QuestionWidget, mapStateToProps } from '.';
jest.mock('../../../../../data/redux', () => ({
__esModule: true,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.jsx
index 2c5bc69604..a11f9ea276 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/CardSection.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { shallow } from '@edx/react-unit-test-utils';
import CardSection from './CardSection';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
index d04d94bec2..929bedb245 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.jsx
@@ -11,7 +11,7 @@ import {
import { showFullCard } from './hooks';
import CardSection from './CardSection';
-export const SettingsOption = ({
+const SettingsOption = ({
title, className, extraSections, children, summary, hasExpandableTextArea, ...passThroughProps
}) => {
const { isCardCollapsibleOpen, toggleCardCollapse } = showFullCard(hasExpandableTextArea);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.jsx
index e7c3074e78..5c9c1a17e8 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/SettingsOption.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import SettingsOption from './SettingsOption';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
index a76fef4221..1fb8fa6a8c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.js
@@ -1,6 +1,10 @@
import { useState, useEffect } from 'react';
-import _ from 'lodash-es';
+import _ from 'lodash';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import messages from './messages';
import {
@@ -129,7 +133,7 @@ export const scoringCardHooks = (scoring, updateSettings, defaultValue) => {
const handleMaxAttemptChange = (event) => {
let unlimitedAttempts = false;
- let attemptNumber = parseInt(event.target.value);
+ let attemptNumber = parseInt(event.target.value, 10);
if (!_.isFinite(attemptNumber) || attemptNumber === defaultValue) {
attemptNumber = null;
@@ -147,7 +151,7 @@ export const scoringCardHooks = (scoring, updateSettings, defaultValue) => {
};
const handleOnChange = (event) => {
- let newMaxAttempt = parseInt(event.target.value);
+ let newMaxAttempt = parseInt(event.target.value, 10);
if (newMaxAttempt === defaultValue) {
newMaxAttempt = `${defaultValue} (Default)`;
} else if (_.isNaN(newMaxAttempt)) {
@@ -193,7 +197,7 @@ export const useAnswerSettings = (showAnswer, updateSettings) => {
};
const handleAttemptsChange = (event) => {
- let attempts = parseInt(event.target.value);
+ let attempts = parseInt(event.target.value, 10);
if (_.isNaN(attempts)) {
attempts = 0;
}
@@ -209,7 +213,7 @@ export const useAnswerSettings = (showAnswer, updateSettings) => {
export const timerCardHooks = (updateSettings) => ({
handleChange: (event) => {
- let time = parseInt(event.target.value);
+ let time = parseInt(event.target.value, 10);
if (_.isNaN(time)) {
time = 0;
}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
index 8b636c0a88..2576025a99 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/hooks.test.js
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { MockUseState } from '../../../../../../testUtils';
+import { MockUseState } from '../../../../../testUtils';
import messages from './messages';
import { keyStore } from '../../../../../utils';
import * as hooks from './hooks';
@@ -286,7 +286,9 @@ describe('Problem settings hooks', () => {
test('test handleAttemptsChange', () => {
const value = 3;
output.handleAttemptsChange({ target: { value } });
- expect(updateSettings).toHaveBeenCalledWith({ showAnswer: { ...showAnswer, afterAttempts: parseInt(value) } });
+ expect(updateSettings).toHaveBeenCalledWith({
+ showAnswer: { ...showAnswer, afterAttempts: parseInt(value, 10) },
+ });
});
});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
index 32be62ce1d..6c858b7361 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.jsx
@@ -23,7 +23,7 @@ import { ProblemTypeKeys } from '../../../../../data/constants/problem';
import Randomization from './settingsComponents/Randomization';
// This widget should be connected, grab all settings from store, update them as needed.
-export const SettingsWidget = ({
+const SettingsWidget = ({
problemType,
// redux
answers,
@@ -192,4 +192,5 @@ export const mapDispatchToProps = {
updateAnswer: actions.problem.updateAnswer,
};
+export const SettingsWidgetInternal = SettingsWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SettingsWidget));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.scss b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.scss
index ec4cee4412..ad6d2705a5 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.scss
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.scss
@@ -1,5 +1,5 @@
.settingsCardTitleSection {
- padding-bottom: 0rem;
+ padding-bottom: 0;
}
.halfSpacedMessage {
@@ -12,6 +12,7 @@
.settingsWidget {
margin-top: 40px;
+
.pgn__form-text {
font-size: small;
}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.jsx
index 9a95851a58..a432a5730d 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/index.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { showAdvancedSettingsCards } from './hooks';
-import { SettingsWidget, mapDispatchToProps } from '.';
+import { SettingsWidgetInternal as SettingsWidget, mapDispatchToProps } from '.';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
import { actions } from '../../../../../data/redux';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
index cd4f8a77bb..c168392b37 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.js
@@ -1,6 +1,10 @@
import { useState, useEffect } from 'react';
-import _ from 'lodash-es';
+import _ from 'lodash';
import messages from './messages';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const state = {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
index d866353bb4..5d5c98d528 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/hooks.test.js
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { MockUseState } from '../../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../../testUtils';
import messages from './messages';
import * as hooks from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.jsx
index af5befed9e..f24152c649 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GeneralFeedback/index.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../../testUtils';
import { GeneralFeedbackCard } from './index';
import { generalFeedbackHooks } from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
index 9d1ebff4c9..53e232cbc9 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.jsx
@@ -7,7 +7,7 @@ import { DeleteOutline } from '@openedx/paragon/icons';
import PropTypes from 'prop-types';
import messages from '../../messages';
-export const GroupFeedbackRow = ({
+const GroupFeedbackRow = ({
value,
handleAnswersSelectedChange,
handleFeedbackChange,
@@ -76,4 +76,5 @@ GroupFeedbackRow.propTypes = {
intl: intlShape.isRequired,
};
+export const GroupFeedbackRowInternal = GroupFeedbackRow; // For testing only
export default injectIntl(GroupFeedbackRow);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.test.jsx
index ea29dd2f40..93be2e2664 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/GroupFeedbackRow.test.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../../testUtils';
-import { GroupFeedbackRow } from './GroupFeedbackRow';
+import { formatMessage } from '../../../../../../../testUtils';
+import { GroupFeedbackRowInternal as GroupFeedbackRow } from './GroupFeedbackRow';
jest.mock('@openedx/paragon', () => ({
...jest.requireActual('@openedx/paragon'),
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
index 71956ee541..4dbe89c00c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.js
@@ -1,6 +1,10 @@
import { useState, useEffect } from 'react';
-import _ from 'lodash-es';
+import { isEmpty } from 'lodash';
import messages from './messages';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const state = {
@@ -30,7 +34,7 @@ export const groupFeedbackCardHooks = (groupFeedbacks, updateSettings, answersli
const handleAdd = () => {
let newId = 0;
- if (!_.isEmpty(groupFeedbacks)) {
+ if (!isEmpty(groupFeedbacks)) {
newId = Math.max(...groupFeedbacks.map(feedback => feedback.id)) + 1;
}
const groupFeedback = { id: newId, answers: [], feedback: '' };
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
index 91728e55aa..14adde6d3b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/hooks.test.js
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { MockUseState } from '../../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../../testUtils';
import messages from './messages';
import * as hooks from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.jsx
index 3fe4a7ff4f..531be7bad4 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.jsx
@@ -7,7 +7,7 @@ import { groupFeedbackCardHooks, groupFeedbackRowHooks } from './hooks';
import GroupFeedbackRow from './GroupFeedbackRow';
import Button from '../../../../../../../sharedComponents/Button';
-export const GroupFeedbackCard = ({
+const GroupFeedbackCard = ({
groupFeedbacks,
updateSettings,
answers,
@@ -63,4 +63,5 @@ GroupFeedbackCard.propTypes = {
updateSettings: PropTypes.func.isRequired,
};
+export const GroupFeedbackCardInternal = GroupFeedbackCard; // For testing only
export default injectIntl(GroupFeedbackCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.jsx
index b3c7c1d679..2c52195242 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/GroupFeedback/index.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../../testUtils';
-import { GroupFeedbackCard } from './index';
+import { formatMessage } from '../../../../../../../testUtils';
+import { GroupFeedbackCardInternal as GroupFeedbackCard } from './index';
import { groupFeedbackRowHooks, groupFeedbackCardHooks } from './hooks';
import messages from './messages';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx
index 7f8e8b7333..55817d51a1 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types';
import messages from '../messages';
import ExpandableTextArea from '../../../../../../sharedComponents/ExpandableTextArea';
-export const HintRow = ({
+const HintRow = ({
value,
handleChange,
handleDelete,
@@ -49,4 +49,5 @@ HintRow.propTypes = {
intl: intlShape.isRequired,
};
+export const HintRowInternal = HintRow; // For testing only
export default injectIntl(HintRow);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.jsx
index e0d22b5878..3d7673ec9f 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { HintRow } from './HintRow';
+import { formatMessage } from '../../../../../../testUtils';
+import { HintRowInternal as HintRow } from './HintRow';
describe('HintRow', () => {
const props = {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.jsx
index de29ba8ff1..cdb399d91f 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.jsx
@@ -8,7 +8,7 @@ import { hintsCardHooks, hintsRowHooks } from '../hooks';
import HintRow from './HintRow';
import Button from '../../../../../../sharedComponents/Button';
-export const HintsCard = ({
+const HintsCard = ({
hints,
problemType,
updateSettings,
@@ -56,4 +56,5 @@ HintsCard.propTypes = {
updateSettings: PropTypes.func.isRequired,
};
+export const HintsCardInternal = HintsCard; // For testing only
export default injectIntl(HintsCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.test.jsx
index e1c3e8998b..3105445b6b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintsCard.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { HintsCard } from './HintsCard';
+import { formatMessage } from '../../../../../../testUtils';
+import { HintsCardInternal as HintsCard } from './HintsCard';
import { hintsCardHooks, hintsRowHooks } from '../hooks';
import messages from '../messages';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js
index 28c5e8fef9..888488895c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.js
@@ -1,5 +1,9 @@
import { useState, useEffect } from 'react';
import { RandomizationTypes, RandomizationTypesKeys } from '../../../../../../../data/constants/problem';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const state = {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
index cd202f555b..dc4cf2cb1c 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/hooks.test.js
@@ -1,5 +1,5 @@
import { useEffect } from 'react';
-import { MockUseState } from '../../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../../testUtils';
import * as hooks from './hooks';
import { RandomizationTypes, RandomizationTypesKeys } from '../../../../../../../data/constants/problem';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.jsx
index 8dac761f53..d3438f6196 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Randomization/index.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../../testUtils';
import { RandomizationCard } from './index';
import { useRandomizationSettingStatus } from './hooks';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
index ef132a2539..1413f092e9 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.jsx
@@ -8,7 +8,7 @@ import messages from '../messages';
import { resetCardHooks } from '../hooks';
import { selectors } from '../../../../../../data/redux';
-export const ResetCard = ({
+const ResetCard = ({
showResetButton,
defaultValue,
updateSettings,
@@ -58,4 +58,5 @@ ResetCard.propTypes = {
intl: intlShape.isRequired,
};
+export const ResetCardInternal = ResetCard; // For testing only
export default injectIntl(ResetCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
index 5802d6d11d..d3c46314fb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ResetCard.test.jsx
@@ -1,7 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { ResetCard } from './ResetCard';
+import { useSelector } from 'react-redux';
+import { formatMessage } from '../../../../../../testUtils';
+import { ResetCardInternal as ResetCard } from './ResetCard';
import { resetCardHooks } from '../hooks';
jest.mock('../hooks', () => ({
@@ -17,9 +19,7 @@ jest.mock('../../../../../../data/redux', () => ({
},
}));
-jest.mock('react-redux', () => ({
- useSelector: jest.fn().mockImplementation((args) => args),
-}));
+useSelector.mockImplementation((args) => args);
describe('ResetCard', () => {
const props = {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
index 60dc034476..d7710313c1 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import _ from 'lodash-es';
+import _ from 'lodash';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
@@ -9,7 +9,7 @@ import SettingsOption from '../SettingsOption';
import messages from '../messages';
import { scoringCardHooks } from '../hooks';
-export const ScoringCard = ({
+const ScoringCard = ({
scoring,
defaultValue,
updateSettings,
@@ -113,4 +113,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const ScoringCardInternal = ScoringCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ScoringCard));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
index e95fcbce7c..29d8e922cf 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ScoringCard.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { scoringCardHooks } from '../hooks';
-import { ScoringCard } from './ScoringCard';
+import { ScoringCardInternal as ScoringCard } from './ScoringCard';
jest.mock('../hooks', () => ({
scoringCardHooks: jest.fn(),
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
index 0d06ab63b5..eb2690194f 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.jsx
@@ -9,7 +9,7 @@ import { selectors } from '../../../../../../data/redux';
import messages from '../messages';
import { useAnswerSettings } from '../hooks';
-export const ShowAnswerCard = ({
+const ShowAnswerCard = ({
showAnswer,
updateSettings,
defaultValue,
@@ -113,4 +113,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const ShowAnswerCardInternal = ShowAnswerCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ShowAnswerCard));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.jsx
index ae1c850e11..dae004510b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/ShowAnswerCard.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { selectors } from '../../../../../../data/redux';
-import { ShowAnswerCard, mapStateToProps, mapDispatchToProps } from './ShowAnswerCard';
+import { ShowAnswerCardInternal as ShowAnswerCard, mapStateToProps, mapDispatchToProps } from './ShowAnswerCard';
import { useAnswerSettings } from '../hooks';
jest.mock('../hooks', () => ({
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.jsx
index 2828b037c8..90454579ea 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.jsx
@@ -10,7 +10,7 @@ import Button from '../../../../../../sharedComponents/Button';
import { confirmSwitchToAdvancedEditor } from '../hooks';
import { ProblemTypeKeys } from '../../../../../../data/constants/problem';
-export const SwitchToAdvancedEditorCard = ({
+const SwitchToAdvancedEditorCard = ({
problemType,
switchToAdvancedEditor,
}) => {
@@ -59,4 +59,5 @@ export const mapDispatchToProps = {
switchToAdvancedEditor: thunkActions.problem.switchToAdvancedEditor,
};
+export const SwitchToAdvancedEditorCardInternal = SwitchToAdvancedEditorCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SwitchToAdvancedEditorCard));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.test.jsx
index 9f16c8a8d5..b9d59f27f1 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/SwitchToAdvancedEditorCard.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { SwitchToAdvancedEditorCard, mapDispatchToProps } from './SwitchToAdvancedEditorCard';
+import { SwitchToAdvancedEditorCardInternal as SwitchToAdvancedEditorCard, mapDispatchToProps } from './SwitchToAdvancedEditorCard';
import { thunkActions } from '../../../../../../data/redux';
describe('SwitchToAdvancedEditorCard snapshot', () => {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.jsx
index 28e159b8c1..33032b529b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.jsx
@@ -6,7 +6,7 @@ import SettingsOption from '../SettingsOption';
import messages from '../messages';
import { timerCardHooks } from '../hooks';
-export const TimerCard = ({
+const TimerCard = ({
timeBetween,
updateSettings,
// inject
@@ -42,4 +42,5 @@ TimerCard.propTypes = {
intl: intlShape.isRequired,
};
+export const TimerCardInternal = TimerCard; // For testing only
export default injectIntl(TimerCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.jsx
index 46de822d58..614a73639b 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TimerCard.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { TimerCard } from './TimerCard';
+import { formatMessage } from '../../../../../../testUtils';
+import { TimerCardInternal as TimerCard } from './TimerCard';
import { timerCardHooks } from '../hooks';
jest.mock('../hooks', () => ({
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
index cdb57f6511..150a2f39bd 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.jsx
@@ -42,7 +42,7 @@ export const getSummary = ({ tolerance, intl }) => {
}
};
-export const ToleranceCard = ({
+const ToleranceCard = ({
tolerance,
answers,
updateSettings,
@@ -119,4 +119,5 @@ ToleranceCard.propTypes = {
intl: intlShape.isRequired,
};
+export const ToleranceCardInternal = ToleranceCard; // For testing only
export default injectIntl(ToleranceCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
index d0ba299ee8..d429128ccb 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/index.test.jsx
@@ -4,8 +4,8 @@ import {
import React from 'react';
import messages from './messages';
import { ToleranceTypes } from './constants';
-import { ToleranceCard } from './index';
-import { formatMessage } from '../../../../../../../../testUtils';
+import { ToleranceCardInternal as ToleranceCard } from './index';
+import { formatMessage } from '../../../../../../../testUtils';
jest.mock('@edx/frontend-platform/i18n', () => ({
__esmodule: true,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.jsx
index aa6808196b..75137b5050 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.jsx
@@ -6,7 +6,7 @@ import { ProblemTypeKeys, ProblemTypes } from '../../../../../../data/constants/
import messages from '../messages';
import TypeRow from './TypeRow';
-export const TypeCard = ({
+const TypeCard = ({
answers,
blockTitle,
correctAnswerCount,
@@ -64,4 +64,5 @@ TypeCard.propTypes = {
intl: intlShape.isRequired,
};
+export const TypeCardInternal = TypeCard; // For testing only
export default injectIntl(TypeCard);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.test.jsx
index f64fa1b300..bd914dec9a 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeCard.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { TypeCard } from './TypeCard';
+import { formatMessage } from '../../../../../../testUtils';
+import { TypeCardInternal as TypeCard } from './TypeCard';
import { ProblemTypeKeys } from '../../../../../../data/constants/problem';
describe('TypeCard', () => {
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
index cad93083a0..ec8bc78ec9 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.jsx
@@ -6,7 +6,7 @@ import { typeRowHooks } from '../hooks';
import Button from '../../../../../../sharedComponents/Button';
-export const TypeRow = ({
+const TypeRow = ({
answers,
blockTitle,
correctAnswerCount,
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.jsx
index a34c14df06..3902fd9659 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/TypeRow.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { TypeRow } from './TypeRow';
+import TypeRow from './TypeRow';
import { typeRowHooks } from '../hooks';
jest.mock('../hooks', () => ({
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
index 6a11b3f711..642e149955 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.js
@@ -24,7 +24,7 @@ export const fetchEditorContent = ({ format }) => {
const editorObject = { hints: [] };
const EditorsArray = window.tinymce.editors;
Object.entries(EditorsArray).forEach(([id, editor]) => {
- if (Number.isNaN(parseInt(id))) {
+ if (Number.isNaN(parseInt(id, 10))) {
if (id.startsWith('answer')) {
const { answers } = editorObject;
const answerId = id.substring(id.indexOf('-') + 1);
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
index fe3a4d7b03..11f38473b4 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/hooks.test.js
@@ -1,6 +1,6 @@
import { ProblemTypeKeys, ShowAnswerTypesKeys } from '../../../../data/constants/problem';
import * as hooks from './hooks';
-import { MockUseState } from '../../../../../testUtils';
+import { MockUseState } from '../../../../testUtils';
const mockRawOLX = 'rawOLX';
const mockBuiltOLX = 'builtOLX';
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
index e05a4ae4b2..64d9229061 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/index.jsx
@@ -24,7 +24,7 @@ import messages from './messages';
import ExplanationWidget from './ExplanationWidget';
import { saveBlock } from '../../../../hooks';
-export const EditProblemView = ({
+const EditProblemView = ({
returnFunction,
// redux
problemType,
@@ -139,4 +139,5 @@ export const mapStateToProps = (state) => ({
problemState: selectors.problem.completeState(state),
});
+export const EditProblemViewInternal = EditProblemView; // For testing only
export default injectIntl(connect(mapStateToProps)(EditProblemView));
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/index.scss b/src/editors/containers/ProblemEditor/components/EditProblemView/index.scss
index 95d58efef1..1c14750ebf 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/index.scss
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/index.scss
@@ -4,9 +4,11 @@
flex-grow: 0;
flex-shrink: 0;
}
+
.advancedEditorTopMargin {
margin-top: 40px;
}
+
.answer-option {
.pgn__form-checkbox,
.pgn__form-radio {
@@ -15,6 +17,7 @@
}
}
}
+
.settingsOption {
.pgn__form-checkbox .pgn__form-label {
min-width: .8rem;
@@ -24,7 +27,7 @@
.tinyMceWidget {
.tox-tinymce {
- border-radius: 0.375rem;
+ border-radius: .375rem;
}
.tox {
@@ -41,11 +44,11 @@
// TODO: Find a way to override the border without !important
border-right: none !important;
- &:after {
+ &::after {
content: '';
position: relative;
left: 5px;
- border: 1px solid #eae6e5;
+ border: 1px solid #EAE6E5;
height: 24px;
}
}
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.jsx b/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.jsx
index 6a40796cef..a55d025bad 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/index.test.jsx
@@ -1,18 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { EditProblemView } from '.';
-import AnswerWidget from './AnswerWidget';
+import { EditProblemViewInternal as EditProblemView } from '.';
+import { AnswerWidgetInternal as AnswerWidget } from './AnswerWidget';
import { ProblemTypeKeys } from '../../../../data/constants/problem';
import RawEditor from '../../../../sharedComponents/RawEditor';
-import { formatMessage } from '../../../../../testUtils';
-
-jest.mock('@openedx/paragon', () => ({
- ...jest.requireActual('@openedx/paragon'),
- Container: 'Container',
- Button: 'Button',
- AlertModal: 'AlertModal',
- ActionRow: 'ActionRow',
-}));
+import { formatMessage } from '../../../../testUtils';
describe('EditorProblemView component', () => {
test('renders simple view', () => {
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.jsx
index 677dc4988e..733f87a1a2 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.jsx
@@ -9,11 +9,11 @@ import {
} from '@openedx/paragon';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import messages from './messages';
-import hooks from '../hooks';
+import * as hooks from '../hooks';
import { actions, selectors } from '../../../../../data/redux';
-export const SelectTypeFooter = ({
+const SelectTypeFooter = ({
onCancel,
selected,
// redux
@@ -79,4 +79,5 @@ export const mapDispatchToProps = {
setBlockTitle: actions.app.setBlockTitle,
};
+export const SelectTypeFooterInternal = SelectTypeFooter; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SelectTypeFooter));
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.test.jsx
index 2a9e142362..c00cd02d48 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/SelectTypeFooter.test.jsx
@@ -1,12 +1,15 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { Button } from '@openedx/paragon';
-import { formatMessage } from '../../../../../../testUtils';
+import { formatMessage } from '../../../../../testUtils';
import * as module from './SelectTypeFooter';
-import hooks from '../hooks';
+import * as hooks from '../hooks';
import { actions } from '../../../../../data/redux';
+const SelectTypeFooter = module.SelectTypeFooterInternal;
+
jest.mock('../hooks', () => ({
onSelect: jest.fn().mockName('onSelect'),
}));
@@ -23,13 +26,13 @@ describe('SelectTypeFooter', () => {
};
test('snapshot', () => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
describe('behavior', () => {
let el;
beforeEach(() => {
- el = shallow();
+ el = shallow();
});
test('close behavior is linked to modal onCancel', () => {
const expected = props.onCancel;
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.jsx
index 8f05c83328..f747783f5a 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.jsx
@@ -8,7 +8,7 @@ import SelectTypeFooter from './SelectTypeFooter';
import * as hooks from '../../../../EditorContainer/hooks';
import messages from './messages';
-export const SelectTypeWrapper = ({
+const SelectTypeWrapper = ({
children,
onClose,
selected,
@@ -51,4 +51,5 @@ SelectTypeWrapper.propTypes = {
onClose: PropTypes.func,
};
+export const SelectTypeWrapperInternal = SelectTypeWrapper; // For testing only
export default injectIntl(SelectTypeWrapper);
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.jsx
index 3bdd2088ee..ec2e3a51a6 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/SelectTypeWrapper/index.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { IconButton } from '@openedx/paragon';
-import * as module from '.';
+import { SelectTypeWrapperInternal as SelectTypeWrapper } from '.';
import { handleCancel } from '../../../../EditorContainer/hooks';
jest.mock('../../../../EditorContainer/hooks', () => ({
@@ -16,13 +17,13 @@ describe('SelectTypeWrapper', () => {
};
test('snapshot', () => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
describe('behavior', () => {
let el;
beforeEach(() => {
- el = shallow();
+ el = shallow();
});
test('close behavior is linked to modal onClose', () => {
const expected = handleCancel({ onClose: props.onClose });
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.jsx
index 6dda14eaa6..d60061ddd1 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.jsx
@@ -16,7 +16,7 @@ import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/
import { AdvanceProblems, ProblemTypeKeys } from '../../../../../data/constants/problem';
import messages from './messages';
-export const AdvanceTypeSelect = ({
+const AdvanceTypeSelect = ({
selected,
setSelected,
// injected
@@ -97,4 +97,5 @@ AdvanceTypeSelect.propTypes = {
intl: intlShape.isRequired,
};
+export const AdvanceTypeSelectInternal = AdvanceTypeSelect; // For testing only
export default injectIntl(AdvanceTypeSelect);
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.jsx
index f385f1b6fe..978b35e7c5 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/AdvanceTypeSelect.test.jsx
@@ -1,9 +1,12 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
+import { formatMessage } from '../../../../../testUtils';
import * as module from './AdvanceTypeSelect';
+const AdvanceTypeSelect = module.AdvanceTypeSelectInternal;
+
describe('AdvanceTypeSelect', () => {
const props = {
intl: { formatMessage },
@@ -13,42 +16,42 @@ describe('AdvanceTypeSelect', () => {
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is circuitschematic', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is customgrader', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is drag_and_drop', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is formularesponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is imageresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is jsinput_response', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is problem_with_hint', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
index bca710bd25..7077c18a56 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.jsx
@@ -9,7 +9,7 @@ import {
import messages from './messages';
import { ProblemTypes } from '../../../../../data/constants/problem';
-export const Preview = ({
+const Preview = ({
problemType,
// injected
intl,
@@ -52,4 +52,5 @@ Preview.propTypes = {
intl: intlShape.isRequired,
};
+export const PreviewInternal = Preview; // For testing only
export default injectIntl(Preview);
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.test.jsx
index 6db9965d4f..36cf961fc8 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/Preview.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
-import * as module from './Preview';
+import { formatMessage } from '../../../../../testUtils';
+import { PreviewInternal as Preview } from './Preview';
describe('Preview', () => {
const props = {
@@ -12,32 +13,32 @@ describe('Preview', () => {
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is stringresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is numericalresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is optionresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is choiceresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with problemType is multiplechoiceresponse', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.jsx
index 8fcf860a2f..e58d731af2 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.jsx
@@ -8,7 +8,7 @@ import SelectableBox from '../../../../../sharedComponents/SelectableBox';
import { ProblemTypes, ProblemTypeKeys, AdvanceProblemKeys } from '../../../../../data/constants/problem';
import messages from './messages';
-export const ProblemTypeSelect = ({
+const ProblemTypeSelect = ({
selected,
setSelected,
}) => {
@@ -50,4 +50,5 @@ ProblemTypeSelect.propTypes = {
setSelected: PropTypes.func.isRequired,
};
+export const ProblemTypeSelectInternal = ProblemTypeSelect; // For testing only
export default injectIntl(ProblemTypeSelect);
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.jsx
index e6463db987..7482f843ef 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/content/ProblemTypeSelect.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { ProblemTypeKeys } from '../../../../../data/constants/problem';
-import * as module from './ProblemTypeSelect';
+import { ProblemTypeSelectInternal as ProblemTypeSelect } from './ProblemTypeSelect';
describe('ProblemTypeSelect', () => {
const props = {
@@ -12,27 +13,27 @@ describe('ProblemTypeSelect', () => {
describe('snapshot', () => {
test('SINGLESELECT', () => {
expect(shallow(
- ,
+ ,
).snapshot).toMatchSnapshot();
});
test('MULTISELECT', () => {
expect(shallow(
- ,
+ ,
).snapshot).toMatchSnapshot();
});
test('DROPDOWN', () => {
expect(shallow(
- ,
+ ,
).snapshot).toMatchSnapshot();
});
test('NUMERIC', () => {
expect(shallow(
- ,
+ ,
).snapshot).toMatchSnapshot();
});
test('TEXTINPUT', () => {
expect(shallow(
- ,
+ ,
).snapshot).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
index ef70a36133..d25c028aaa 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.js
@@ -3,6 +3,10 @@ import {
AdvanceProblemKeys, AdvanceProblems, ProblemTypeKeys, ProblemTypes,
} from '../../../../data/constants/problem';
import { StrictDict, snakeCaseKeys } from '../../../../utils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
@@ -72,10 +76,3 @@ export const useArrowNav = (selected, setSelected) => {
};
}, [selected, setSelected]);
};
-
-export default {
- state,
- selectHooks,
- onSelect,
- useArrowNav,
-};
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.test.js b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.test.js
index 2970c87b39..e0582b5fb2 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.test.js
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/hooks.test.js
@@ -1,6 +1,10 @@
/* eslint-disable prefer-destructuring */
import React from 'react';
-import { MockUseState } from '../../../../../testUtils';
+import { MockUseState } from '../../../../testUtils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { AdvanceProblems, ProblemTypeKeys, ProblemTypes } from '../../../../data/constants/problem';
import { getDataFromOlx } from '../../../../data/redux/thunkActions/problem';
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.jsx
index e39100edb7..828dc4be05 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.jsx
@@ -6,10 +6,10 @@ import ProblemTypeSelect from './content/ProblemTypeSelect';
import Preview from './content/Preview';
import AdvanceTypeSelect from './content/AdvanceTypeSelect';
import SelectTypeWrapper from './SelectTypeWrapper';
-import hooks from './hooks';
+import * as hooks from './hooks';
import { AdvanceProblemKeys } from '../../../../data/constants/problem';
-export const SelectTypeModal = ({
+const SelectTypeModal = ({
onClose,
}) => {
const { selected, setSelected } = hooks.selectHooks();
diff --git a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.test.jsx b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.test.jsx
index 8347aff4e4..4574c1b799 100644
--- a/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/components/SelectTypeModal/index.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import * as module from '.';
+import SelectTypeModal from '.';
jest.mock('./hooks', () => ({
selectHooks: jest.fn(() => ({
@@ -16,6 +17,6 @@ describe('SelectTypeModal', () => {
};
test('snapshot', () => {
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/ProblemEditor/data/OLXParser.js b/src/editors/containers/ProblemEditor/data/OLXParser.js
index 0a3d0ff6a3..e9a12348fb 100644
--- a/src/editors/containers/ProblemEditor/data/OLXParser.js
+++ b/src/editors/containers/ProblemEditor/data/OLXParser.js
@@ -2,7 +2,7 @@
/* eslint no-eval: 0 */
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
-import _ from 'lodash-es';
+import _ from 'lodash';
import { ProblemTypeKeys, RichTextProblems, settingsOlxAttributes } from '../../../data/constants/problem';
export const indexToLetterMap = [...Array(26)].map((val, i) => String.fromCharCode(i + 65));
@@ -719,9 +719,9 @@ export class OLXParser {
if (!toleranceValue || toleranceValue.length === 0) {
settings.tolerance = { value: null, type: 'None' };
} else if (toleranceValue.includes('%')) {
- settings.tolerance = { value: parseInt(toleranceValue.slice(0, -1)), type: 'Percent' };
+ settings.tolerance = { value: parseInt(toleranceValue.slice(0, -1), 10), type: 'Percent' };
} else {
- settings.tolerance = { value: parseInt(toleranceValue), type: 'Number' };
+ settings.tolerance = { value: parseInt(toleranceValue, 10), type: 'Number' };
}
} else {
settings.tolerance = { value: null, type: 'None' };
diff --git a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
index f320cdd827..673763de61 100644
--- a/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
+++ b/src/editors/containers/ProblemEditor/data/ReactStateOLXParser.js
@@ -1,4 +1,4 @@
-import _ from 'lodash-es';
+import _ from 'lodash';
import { XMLParser, XMLBuilder } from 'fast-xml-parser';
import { ProblemTypeKeys } from '../../../data/constants/problem';
import { ToleranceTypes } from '../components/EditProblemView/SettingsWidget/settingsComponents/Tolerance/constants';
diff --git a/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js b/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
index 88fcb7f987..49ddac5324 100644
--- a/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
+++ b/src/editors/containers/ProblemEditor/data/ReactStateSettingsParser.js
@@ -1,5 +1,5 @@
import { XMLParser } from 'fast-xml-parser';
-import _ from 'lodash-es';
+import _ from 'lodash';
import {
ShowAnswerTypesKeys,
@@ -61,7 +61,7 @@ class ReactStateSettingsParser {
const attributeKey = attribute.substring(2);
if (SETTING_KEYS.includes(attributeKey)) {
if (attributeKey === 'max_attempts' || attributeKey === 'weight') {
- rawOlxSettings[attributeKey] = parseInt(olx.problem[attribute]);
+ rawOlxSettings[attributeKey] = parseInt(olx.problem[attribute], 10);
} else {
rawOlxSettings[attributeKey] = olx.problem[attribute];
}
diff --git a/src/editors/containers/ProblemEditor/data/SettingsParser.js b/src/editors/containers/ProblemEditor/data/SettingsParser.js
index 5836e2827b..1c90470675 100644
--- a/src/editors/containers/ProblemEditor/data/SettingsParser.js
+++ b/src/editors/containers/ProblemEditor/data/SettingsParser.js
@@ -1,4 +1,4 @@
-import _ from 'lodash-es';
+import _ from 'lodash';
import { ShowAnswerTypes, RandomizationTypesKeys } from '../../../data/constants/problem';
diff --git a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
index 4a0502f336..2815228969 100644
--- a/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
+++ b/src/editors/containers/ProblemEditor/data/reactStateOLXHelpers.js
@@ -1,6 +1,6 @@
/* eslint-disable import/prefer-default-export */
-import flatten from 'lodash.flatten';
+import { flatten } from 'lodash';
/**
* flattenSubNodes - appends a nodes children to a given array 'subNodes' in a flattened format.
diff --git a/src/editors/containers/ProblemEditor/index.jsx b/src/editors/containers/ProblemEditor/index.jsx
index fcb05d194c..5f342ad1e4 100644
--- a/src/editors/containers/ProblemEditor/index.jsx
+++ b/src/editors/containers/ProblemEditor/index.jsx
@@ -9,7 +9,7 @@ import { selectors, thunkActions } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
import messages from './messages';
-export const ProblemEditor = ({
+const ProblemEditor = ({
onClose,
returnFunction,
// Redux
@@ -79,4 +79,5 @@ export const mapDispatchToProps = {
initializeProblemEditor: thunkActions.problem.initializeProblem,
};
+export const ProblemEditorInternal = ProblemEditor; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ProblemEditor));
diff --git a/src/editors/containers/ProblemEditor/index.test.jsx b/src/editors/containers/ProblemEditor/index.test.jsx
index 6c171b22af..f6866b56a6 100644
--- a/src/editors/containers/ProblemEditor/index.test.jsx
+++ b/src/editors/containers/ProblemEditor/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { Spinner } from '@openedx/paragon';
import { thunkActions, selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
-import { ProblemEditor, mapStateToProps, mapDispatchToProps } from '.';
+import { ProblemEditorInternal as ProblemEditor, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('./components/EditProblemView', () => 'EditProblemView');
jest.mock('./components/SelectTypeModal', () => 'SelectTypeModal');
diff --git a/src/editors/containers/TextEditor/hooks.test.jsx b/src/editors/containers/TextEditor/hooks.test.jsx
index 0580139faf..bac63ab334 100644
--- a/src/editors/containers/TextEditor/hooks.test.jsx
+++ b/src/editors/containers/TextEditor/hooks.test.jsx
@@ -1,5 +1,9 @@
import { keyStore } from '../../utils';
import * as appHooks from '../../hooks';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import * as tinyMceHooks from '../../sharedComponents/TinyMceWidget/hooks';
diff --git a/src/editors/containers/TextEditor/index.jsx b/src/editors/containers/TextEditor/index.jsx
index c349a593e8..830f3b510a 100644
--- a/src/editors/containers/TextEditor/index.jsx
+++ b/src/editors/containers/TextEditor/index.jsx
@@ -18,7 +18,7 @@ import messages from './messages';
import TinyMceWidget from '../../sharedComponents/TinyMceWidget';
import { prepareEditorRef, replaceStaticWithAsset } from '../../sharedComponents/TinyMceWidget/hooks';
-export const TextEditor = ({
+const TextEditor = ({
onClose,
returnFunction,
// redux
@@ -121,4 +121,5 @@ export const mapDispatchToProps = {
initializeEditor: actions.app.initializeEditor,
};
+export const TextEditorInternal = TextEditor; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TextEditor));
diff --git a/src/editors/containers/TextEditor/index.test.jsx b/src/editors/containers/TextEditor/index.test.jsx
index 17e813ac0a..ac337f68f7 100644
--- a/src/editors/containers/TextEditor/index.test.jsx
+++ b/src/editors/containers/TextEditor/index.test.jsx
@@ -1,10 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../testUtils';
+import { formatMessage } from '../../testUtils';
import { actions, selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
-import { TextEditor, mapStateToProps, mapDispatchToProps } from '.';
+import { TextEditorInternal as TextEditor, mapStateToProps, mapDispatchToProps } from '.';
// Per https://github.com/tinymce/tinymce-react/issues/91 React unit testing in JSDOM is not supported by tinymce.
// Consequently, mock the Editor out.
diff --git a/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx b/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
index ade441c325..07167d65ca 100644
--- a/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
+++ b/src/editors/containers/VideoEditor/components/SelectVideoModal.jsx
@@ -6,6 +6,10 @@ import { Button } from '@openedx/paragon';
import { thunkActions } from '../../../data/redux';
import BaseModal from '../../../sharedComponents/BaseModal';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './SelectVideoModal';
export const hooks = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.jsx
index 08ea2acc6d..a7acc05a41 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.jsx
@@ -6,6 +6,10 @@ import { InfoOutline } from '@openedx/paragon/icons';
import messages from './components/messages';
import { ErrorContext } from '../../hooks';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './ErrorSummary';
export const hasNoError = (error) => Object.keys(error[0]).length === 0;
@@ -29,5 +33,3 @@ export const ErrorSummary = () => {
);
};
-
-export default ErrorSummary;
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.jsx
index e644eac856..7a34297aef 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.jsx
@@ -1,8 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import * as module from './ErrorSummary';
+const { ErrorSummary } = module;
+
describe('ErrorSummary', () => {
const errors = {
widgetWithError: [{ err1: 'mSg', err2: 'msG2' }, jest.fn()],
@@ -17,11 +20,11 @@ describe('ErrorSummary', () => {
});
test('snapshots: renders as expected when there are no errors', () => {
jest.spyOn(module, 'showAlert').mockReturnValue(false);
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
test('snapshots: renders as expected when there are errors', () => {
jest.spyOn(module, 'showAlert').mockReturnValue(true);
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
});
});
describe('hasNoError', () => {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.jsx
index 34117ea67c..9545195421 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.jsx
@@ -14,7 +14,7 @@ import messages from './messages';
*
My Widget
*
*/
-export const CollapsibleFormWidget = ({
+const CollapsibleFormWidget = ({
children,
isError,
subtitle,
@@ -70,4 +70,5 @@ CollapsibleFormWidget.propTypes = {
intl: intlShape.isRequired,
};
+export const CollapsibleFormWidgetInternal = CollapsibleFormWidget; // For testing only
export default injectIntl(CollapsibleFormWidget);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.test.jsx
index 91b9523cfe..6cbd4d5b41 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/CollapsibleFormWidget.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
-import { CollapsibleFormWidget } from './CollapsibleFormWidget';
+import { formatMessage } from '../../../../../testUtils';
+import { CollapsibleFormWidgetInternal as CollapsibleFormWidget } from './CollapsibleFormWidget';
describe('CollapsibleFormWidget', () => {
const props = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
index c3fd932be5..ba84d31dfa 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks.js
@@ -2,6 +2,10 @@ import { useEffect, useState } from 'react';
import messages from '../messages';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
const durationMatcher = /^(\d{0,2}):?(\d{0,2})?:?(\d{0,2})?$/i;
@@ -228,13 +232,3 @@ export const valueFromDuration = (duration) => {
const [hours, minutes, seconds] = matches.map(x => parseInt(x, 10) || 0);
return ((hours * 60 + minutes) * 60 + seconds) * 1000;
};
-
-export default {
- durationWidget,
- durationString,
- durationStringFromValue,
- updateDuration,
- onDurationChange,
- onDurationKeyDown,
- valueFromDuration,
-};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.jsx
index e2b692717c..5975edf7ae 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.jsx
@@ -8,7 +8,7 @@ import { injectIntl, intlShape, FormattedMessage } from '@edx/frontend-platform/
import { actions, selectors } from '../../../../../../data/redux';
import { keyStore } from '../../../../../../utils';
import CollapsibleFormWidget from '../CollapsibleFormWidget';
-import hooks from './hooks';
+import * as hooks from './hooks';
import messages from '../messages';
import './index.scss';
@@ -17,7 +17,7 @@ import './index.scss';
* Collapsible Form widget controlling video start and end times
* Also displays the total run time of the video.
*/
-export const DurationWidget = ({
+const DurationWidget = ({
// redux
duration,
updateField,
@@ -100,4 +100,5 @@ export const mapDispatchToProps = {
updateField: actions.video.updateField,
};
+export const DurationWidgetInternal = DurationWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(DurationWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.test.jsx
index f086f25514..4053431075 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { actions, selectors } from '../../../../../../data/redux';
-import { formatMessage } from '../../../../../../../testUtils';
-import { DurationWidget, mapStateToProps, mapDispatchToProps } from '.';
+import { formatMessage } from '../../../../../../testUtils';
+import { DurationWidgetInternal as DurationWidget, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('../../../../../../data/redux', () => ({
actions: {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
index ec14fff5ad..5861715c49 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.jsx
@@ -1,6 +1,10 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { thunkActions } from '../../../../../../data/redux';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const state = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.test.jsx
index a733ff5703..aead6fb96f 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/hooks.test.jsx
@@ -1,7 +1,7 @@
import React from 'react';
import { dispatch } from 'react-redux';
import { thunkActions } from '../../../../../../data/redux';
-import { MockUseState } from '../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../testUtils';
import { keyStore } from '../../../../../../utils';
import * as hooks from './hooks';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
index 35e8f41b77..799c06a0c1 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.jsx
@@ -21,9 +21,9 @@ import { actions, selectors } from '../../../../../../data/redux';
import * as hooks from './hooks';
import messages from './messages';
-import FileInput from '../../../../../../sharedComponents/FileInput';
-import { ErrorAlert } from '../../../../../../sharedComponents/ErrorAlerts/ErrorAlert';
-import { UploadErrorAlert } from '../../../../../../sharedComponents/ErrorAlerts/UploadErrorAlert';
+import { FileInput } from '../../../../../../sharedComponents/FileInput';
+import ErrorAlert from '../../../../../../sharedComponents/ErrorAlerts/ErrorAlert';
+import UploadErrorAlert from '../../../../../../sharedComponents/ErrorAlerts/UploadErrorAlert';
import CollapsibleFormWidget from '../CollapsibleFormWidget';
import { ErrorContext } from '../../../../hooks';
import { RequestKeys } from '../../../../../../data/constants/requests';
@@ -31,7 +31,7 @@ import { RequestKeys } from '../../../../../../data/constants/requests';
/**
* Collapsible Form widget controlling video handouts
*/
-export const HandoutWidget = ({
+const HandoutWidget = ({
// injected
intl,
// redux
@@ -134,4 +134,5 @@ export const mapDispatchToProps = (dispatch) => ({
updateField: (payload) => dispatch(actions.video.updateField(payload)),
});
+export const HandoutWidgetInternal = HandoutWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(HandoutWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.jsx
index cad8e7e168..8ecb7e613f 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/HandoutWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
-import { HandoutWidget, mapStateToProps, mapDispatchToProps } from '.';
+import { HandoutWidgetInternal as HandoutWidget, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('react', () => ({
...jest.requireActual('react'),
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
index 1775df8dbd..236d496311 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.jsx
@@ -17,7 +17,7 @@ import {
import messages from './messages';
import { LicenseTypes } from '../../../../../../data/constants/licenses';
-export const LicenseBlurb = ({
+const LicenseBlurb = ({
license,
details,
}) => (
@@ -48,4 +48,5 @@ LicenseBlurb.propTypes = {
}).isRequired,
};
+export const LicenseBlurbInternal = LicenseBlurb; // For testing only
export default injectIntl(LicenseBlurb);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.jsx
index 7ae07a0012..f55458d859 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseBlurb.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { LicenseBlurb } from './LicenseBlurb';
+import { LicenseBlurbInternal as LicenseBlurb } from './LicenseBlurb';
describe('LicenseBlurb', () => {
const props = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
index cba3e3b3ad..45937efea6 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.jsx
@@ -23,7 +23,7 @@ import { actions } from '../../../../../../data/redux';
import { LicenseLevel, LicenseTypes } from '../../../../../../data/constants/licenses';
import messages from './messages';
-export const LicenseDetails = ({
+const LicenseDetails = ({
license,
details,
level,
@@ -166,4 +166,5 @@ export const mapDispatchToProps = (dispatch) => ({
updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)),
});
+export const LicenseDetailsInternal = LicenseDetails; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(LicenseDetails));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.jsx
index 23a54c3fb3..48e4abdc38 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDetails.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { actions } from '../../../../../../data/redux';
-import { LicenseDetails, mapStateToProps, mapDispatchToProps } from './LicenseDetails';
+import { LicenseDetailsInternal as LicenseDetails, mapStateToProps, mapDispatchToProps } from './LicenseDetails';
jest.mock('react', () => {
const updateState = jest.fn();
@@ -21,18 +22,6 @@ jest.mock('../../../../../../data/redux', () => ({
},
}));
-jest.mock('@openedx/paragon', () => ({
- ...jest.requireActual('@openedx/paragon'),
- CheckboxControl: 'CheckboxControl',
- Stack: 'Stack',
- Icon: 'Icon',
- Form: {
- Group: 'Form.Group',
- Label: 'Form.Label',
- },
- ActionRow: { Spacer: 'ActionRow.Spacer' },
-}));
-
describe('LicenseDetails', () => {
const props = {
license: null,
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
index 435d9fd421..a7799eb746 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.jsx
@@ -15,7 +15,7 @@ import { LicenseTypes } from '../../../../../../data/constants/licenses';
import LicenseBlurb from './LicenseBlurb';
import messages from './messages';
-export const LicenseDisplay = ({
+const LicenseDisplay = ({
license,
details,
licenseDescription,
@@ -53,4 +53,5 @@ LicenseDisplay.propTypes = {
licenseDescription: PropTypes.string.isRequired,
};
+export const LicenseDisplayInternal = LicenseDisplay; // For testing only
export default injectIntl(LicenseDisplay);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.test.jsx
index 21db0c559f..1111694998 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseDisplay.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { LicenseDisplay } from './LicenseDisplay';
+import { LicenseDisplayInternal as LicenseDisplay } from './LicenseDisplay';
jest.mock('react', () => ({
...jest.requireActual('react'),
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
index 30fc329d81..7e468982b9 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.jsx
@@ -15,11 +15,11 @@ import {
import { DeleteOutline } from '@openedx/paragon/icons';
import { actions, selectors } from '../../../../../../data/redux';
-import hooks from './hooks';
+import * as hooks from './hooks';
import messages from './messages';
import { LicenseLevel, LicenseNames, LicenseTypes } from '../../../../../../data/constants/licenses';
-export const LicenseSelector = ({
+const LicenseSelector = ({
license,
level,
// injected
@@ -89,4 +89,5 @@ export const mapDispatchToProps = (dispatch) => ({
updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)),
});
+export const LicenseSelectorInternal = LicenseSelector; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(LicenseSelector));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.jsx
index 7dffedf420..2b6ee9a0ed 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/LicenseSelector.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
-import { LicenseSelector, mapStateToProps, mapDispatchToProps } from './LicenseSelector';
+import { LicenseSelectorInternal as LicenseSelector, mapStateToProps, mapDispatchToProps } from './LicenseSelector';
jest.mock('react', () => {
const updateState = jest.fn();
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/__snapshots__/LicenseDetails.test.jsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/__snapshots__/LicenseDetails.test.jsx.snap
index b062d7fb84..046cc017d3 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/__snapshots__/LicenseDetails.test.jsx.snap
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/__snapshots__/LicenseDetails.test.jsx.snap
@@ -25,7 +25,7 @@ exports[`LicenseDetails snapshots snapshots: renders as expected with level set
className="border-primary-100 border-bottom pb-4"
>
- <[object Object]>
+
@@ -44,7 +44,7 @@ exports[`LicenseDetails snapshots snapshots: renders as expected with level set
checked={true}
disabled={true}
/>
- [object Object]>
+
- <[object Object]>
+
- [object Object]>
+
- <[object Object]>
+
- [object Object]>
+
- <[object Object]>
+
- [object Object]>
+
({
updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)),
});
+export const LicenseWidgetInternal = LicenseWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(LicenseWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.test.jsx
index 823e651660..e7f1836fcc 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/LicenseWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
-import { LicenseWidget, mapStateToProps, mapDispatchToProps } from '.';
+import { LicenseWidgetInternal as LicenseWidget, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('react', () => {
const updateState = jest.fn();
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/constants.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/constants.js
index 3b104e33bb..5c382f9bbe 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/constants.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/constants.js
@@ -1,5 +1,4 @@
+// eslint-disable-next-line import/prefer-default-export
export const analyticsEvents = {
socialSharingSettingChanged: 'edx.social.video_sharing_setting.changed',
};
-
-export default analyticsEvents;
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.jsx
index f1d6db98ce..4b357af3b5 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.jsx
@@ -1,7 +1,7 @@
import { useSelector } from 'react-redux';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import { selectors } from '../../../../../../data/redux';
-import analyticsEvents from './constants';
+import { analyticsEvents } from './constants';
export const useTrackSocialSharingChange = ({ updateField }) => {
const analytics = useSelector(selectors.app.analytics);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.test.jsx
index 987b73f835..a70d8ea838 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/hooks.test.jsx
@@ -1,5 +1,6 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { sendTrackEvent } from '@edx/frontend-platform/analytics';
-import analyticsEvents from './constants';
+import { analyticsEvents } from './constants';
import * as hooks from './hooks';
jest.mock('../../../../../../data/redux', () => ({
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
index 862511642b..57b6e25ac2 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.jsx
@@ -19,7 +19,7 @@ import * as hooks from './hooks';
/**
* Collapsible Form widget controlling video thumbnail
*/
-export const SocialShareWidget = ({
+const SocialShareWidget = ({
// injected
intl,
// redux
@@ -116,4 +116,5 @@ export const mapDispatchToProps = (dispatch) => ({
updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)),
});
+export const SocialShareWidgetInternal = SocialShareWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(SocialShareWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.jsx
index 4335ab7984..2d7fccd76c 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/SocialShareWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
-import { SocialShareWidget, mapStateToProps, mapDispatchToProps } from '.';
+import { SocialShareWidgetInternal as SocialShareWidget, mapStateToProps, mapDispatchToProps } from '.';
import messages from './messages';
jest.mock('react', () => {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/constants.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/constants.js
index 8da5281e0f..17ee797924 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/constants.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/constants.js
@@ -14,7 +14,7 @@ export const MAX_WIDTH = 1280;
export const MAX_HEIGHT = 720;
export const MIN_WIDTH = 640;
export const MIN_HEIGHT = 360;
-// eslint-disable-next-line no-loss-of-precision
+// eslint-disable-next-line no-loss-of-precision, @typescript-eslint/no-loss-of-precision
export const ASPECT_RATIO = 1.7777777777777777777;
export const ASPECT_RATIO_ERROR_MARGIN = 0.1;
export default {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
index 1ece21af09..6277ac4bd5 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.js
@@ -2,6 +2,10 @@ import React from 'react';
import { useDispatch } from 'react-redux';
import { actions, thunkActions } from '../../../../../../data/redux';
import * as constants from './constants';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const state = {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
index ed4b65241e..d59b541fad 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/hooks.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
-import { dispatch } from 'react-redux';
+import { useDispatch } from 'react-redux';
import { actions, thunkActions } from '../../../../../../data/redux';
-import { MockUseState } from '../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../testUtils';
import { keyStore } from '../../../../../../utils';
import * as hooks from './hooks';
@@ -12,15 +13,6 @@ jest.mock('react', () => ({
useCallback: (cb, prereqs) => ({ cb, prereqs }),
}));
-jest.mock('react-redux', () => {
- const dispatchFn = jest.fn();
- return {
- ...jest.requireActual('react-redux'),
- dispatch: dispatchFn,
- useDispatch: jest.fn(() => dispatchFn),
- };
-});
-
jest.mock('../../../../../../data/redux', () => ({
actions: {
video: {
@@ -128,6 +120,7 @@ describe('fileInput', () => {
expect(spies.checkValidSize).toHaveReturnedWith(false);
});
it('dispatches updateField action with the first target file', () => {
+ const dispatch = useDispatch(); // Access the mock 'dispatch()' set up in setupEditorTest
const checkValidSize = true;
spies.checkValidSize = jest.spyOn(hooks, hookKeys.checkValidSize)
.mockReturnValueOnce(checkValidSize);
@@ -142,6 +135,7 @@ describe('fileInput', () => {
});
});
describe('deleteThumbnail', () => {
+ const dispatch = useDispatch(); // Access the mock 'dispatch()' set up in setupEditorTest
const testFile = new File([selectedFileSuccess], 'sOMEUrl.jpg');
hooks.deleteThumbnail({ dispatch })();
expect(dispatch).toHaveBeenNthCalledWith(1, actions.video.updateField({ thumbnail: null }));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
index a0bfa41904..72226c50cf 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.jsx
@@ -24,14 +24,14 @@ import * as hooks from './hooks';
import messages from './messages';
import CollapsibleFormWidget from '../CollapsibleFormWidget';
-import FileInput from '../../../../../../sharedComponents/FileInput';
+import { FileInput } from '../../../../../../sharedComponents/FileInput';
import ErrorAlert from '../../../../../../sharedComponents/ErrorAlerts/ErrorAlert';
import { ErrorContext } from '../../../../hooks';
/**
* Collapsible Form widget controlling video thumbnail
*/
-export const ThumbnailWidget = ({
+const ThumbnailWidget = ({
// injected
intl,
// redux
@@ -143,4 +143,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const ThumbnailWidgetInternal = ThumbnailWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ThumbnailWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx
index 66309718c1..0b761701c6 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/ThumbnailWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { selectors } from '../../../../../../data/redux';
-import { ThumbnailWidget, mapStateToProps, mapDispatchToProps } from '.';
+import { ThumbnailWidgetInternal as ThumbnailWidget, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('react', () => ({
...jest.requireActual('react'),
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.jsx
index bbd3d361b2..21983b45f3 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.jsx
@@ -15,7 +15,7 @@ import { Close } from '@openedx/paragon/icons';
import messages from './messages';
import { thunkActions } from '../../../../../../data/redux';
-export const ImportTranscriptCard = ({
+const ImportTranscriptCard = ({
setOpen,
// redux
importTranscript,
@@ -57,4 +57,5 @@ export const mapDispatchToProps = {
importTranscript: thunkActions.video.importTranscript,
};
+export const ImportTranscriptCardInternal = ImportTranscriptCard; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ImportTranscriptCard));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.jsx
index 977c7571b4..1a55bc98ca 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/ImportTranscriptCard.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { Button, IconButton } from '@openedx/paragon';
import { thunkActions } from '../../../../../../data/redux';
-import * as module from './ImportTranscriptCard';
+import { ImportTranscriptCardInternal as ImportTranscriptCard, mapDispatchToProps, mapStateToProps } from './ImportTranscriptCard';
jest.mock('react', () => ({
...jest.requireActual('react'),
@@ -27,13 +28,13 @@ describe('ImportTranscriptCard', () => {
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
describe('behavior inspection', () => {
beforeEach(() => {
- el = shallow();
+ el = shallow();
});
test('close behavior is linked to IconButton', () => {
expect(el.instance.findByType(IconButton)[0]
@@ -46,12 +47,12 @@ describe('ImportTranscriptCard', () => {
});
describe('mapStateToProps', () => {
it('returns an empty object', () => {
- expect(module.mapStateToProps()).toEqual({});
+ expect(mapStateToProps()).toEqual({});
});
});
describe('mapDispatchToProps', () => {
test('updateField from thunkActions.video.importTranscript', () => {
- expect(module.mapDispatchToProps.importTranscript).toEqual(thunkActions.video.importTranscript);
+ expect(mapDispatchToProps.importTranscript).toEqual(thunkActions.video.importTranscript);
});
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
index 8c94d10fb1..90d3ec235b 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
@@ -15,6 +15,10 @@ import { thunkActions, selectors } from '../../../../../../data/redux';
import { videoTranscriptLanguages } from '../../../../../../data/constants/video';
import { FileInput, fileInput } from '../../../../../../sharedComponents/FileInput';
import messages from './messages';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './LanguageSelector';
export const hooks = {
@@ -45,7 +49,7 @@ export const hooks = {
};
-export const LanguageSelector = ({
+const LanguageSelector = ({
index, // For a unique id for the form control
language,
// Redux
@@ -129,4 +133,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const LanguageSelectorInternal = LanguageSelector; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(LanguageSelector));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
index f45665f35a..0eae896c6f 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.test.jsx
@@ -1,7 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { LanguageSelector } from './LanguageSelector';
-import { formatMessage } from '../../../../../../../testUtils';
+import { LanguageSelectorInternal as LanguageSelector } from './LanguageSelector';
+import { formatMessage } from '../../../../../../testUtils';
const lang1 = 'kLinGon';
const lang1Code = 'kl';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
index 85c1828a39..6300fee194 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.jsx
@@ -20,6 +20,10 @@ import { thunkActions } from '../../../../../../data/redux';
import TranscriptActionMenu from './TranscriptActionMenu';
import LanguageSelector from './LanguageSelector';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './Transcript';
import messages from './messages';
@@ -38,7 +42,7 @@ export const hooks = {
},
};
-export const Transcript = ({
+const Transcript = ({
index,
language,
transcriptUrl,
@@ -120,4 +124,5 @@ export const mapDispatchToProps = {
deleteTranscript: thunkActions.video.deleteTranscript,
};
+export const TranscriptInternal = Transcript; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(Transcript));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
index 6216caefb2..ed16d2f530 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/Transcript.test.jsx
@@ -1,9 +1,12 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import * as module from './Transcript';
-import { MockUseState } from '../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../testUtils';
+
+const Transcript = module.TranscriptInternal;
jest.mock('./LanguageSelector', () => 'LanguageSelector');
jest.mock('./TranscriptActionMenu', () => 'TranscriptActionMenu');
@@ -57,7 +60,7 @@ describe('Transcript Component', () => {
cancelDelete: jest.fn().mockName('cancelDelete'),
}));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with default props: dont show confirm delete, language is blank so delete is shown instead of action menu', () => {
@@ -67,7 +70,7 @@ describe('Transcript Component', () => {
cancelDelete: jest.fn().mockName('cancelDelete'),
}));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with default props: show confirm delete', () => {
@@ -77,7 +80,7 @@ describe('Transcript Component', () => {
cancelDelete: jest.fn().mockName('cancelDelete'),
}));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with transcriptUrl', () => {
@@ -87,7 +90,7 @@ describe('Transcript Component', () => {
cancelDelete: jest.fn().mockName('cancelDelete'),
}));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.jsx
index 553e7f570c..46f51180bc 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.jsx
@@ -9,6 +9,10 @@ import { MoreHoriz } from '@openedx/paragon/icons';
import { thunkActions, selectors } from '../../../../../../data/redux';
import { FileInput, fileInput } from '../../../../../../sharedComponents/FileInput';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './TranscriptActionMenu';
import messages from './messages';
@@ -22,7 +26,7 @@ export const hooks = {
},
};
-export const TranscriptActionMenu = ({
+const TranscriptActionMenu = ({
index,
language,
transcriptUrl,
@@ -85,4 +89,5 @@ export const mapDispatchToProps = {
downloadTranscript: thunkActions.video.downloadTranscript,
};
+export const TranscriptActionMenuInternal = TranscriptActionMenu; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TranscriptActionMenu));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.jsx
index a22eda8a85..b23f5040e8 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/TranscriptActionMenu.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
@@ -5,6 +6,8 @@ import { thunkActions, selectors } from '../../../../../../data/redux';
import * as module from './TranscriptActionMenu';
+const TranscriptActionMenu = module.TranscriptActionMenuInternal;
+
jest.mock('react-redux', () => {
const dispatchFn = jest.fn().mockName('mockUseDispatch');
return {
@@ -71,13 +74,13 @@ describe('TranscriptActionMenu', () => {
test('snapshots: renders as expected with default props: dont show confirm delete', () => {
jest.spyOn(module.hooks, 'replaceFileCallback').mockImplementationOnce(() => jest.fn().mockName('module.hooks.replaceFileCallback'));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with transcriptUrl props: dont show confirm delete', () => {
jest.spyOn(module.hooks, 'replaceFileCallback').mockImplementationOnce(() => jest.fn().mockName('module.hooks.replaceFileCallback'));
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
index d2a56e723c..b734b31ff4 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.jsx
@@ -29,6 +29,10 @@ import CollapsibleFormWidget from '../CollapsibleFormWidget';
import ImportTranscriptCard from './ImportTranscriptCard';
import Transcript from './Transcript';
import { ErrorContext } from '../../../../hooks';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './index';
export const hooks = {
@@ -76,7 +80,7 @@ export const hooks = {
/**
* Collapsible Form widget controlling video transcripts
*/
-export const TranscriptWidget = ({
+const TranscriptWidget = ({
// redux
transcripts,
selectedVideoTranscriptUrls,
@@ -209,4 +213,5 @@ export const mapDispatchToProps = (dispatch) => ({
updateField: (stateUpdate) => dispatch(actions.video.updateField(stateUpdate)),
});
+export const TranscriptWidgetInternal = TranscriptWidget; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TranscriptWidget));
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.test.jsx
index 74353290c3..7e0c54effd 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/index.test.jsx
@@ -1,12 +1,19 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { RequestKeys } from '../../../../../../data/constants/requests';
-import { formatMessage } from '../../../../../../../testUtils';
+import { formatMessage } from '../../../../../../testUtils';
import { actions, selectors } from '../../../../../../data/redux';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './index';
+const TranscriptWidget = module.TranscriptWidgetInternal;
+
jest.mock('react', () => ({
...jest.requireActual('react'),
useContext: jest.fn(() => ({ transcripts: ['error.transcripts', jest.fn().mockName('error.setTranscripts')] })),
@@ -101,47 +108,47 @@ describe('TranscriptWidget', () => {
describe('snapshots', () => {
test('snapshots: renders as expected with default props', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with allowTranscriptImport true', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with transcripts', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with transcript urls', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with transcripts and urls', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with allowTranscriptDownloads true', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshots: renders as expected with showTranscriptByDefault true', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshot: renders ErrorAlert with upload error message', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
test('snapshot: renders ErrorAlert with delete error message', () => {
expect(
- shallow().snapshot,
+ shallow().snapshot,
).toMatchSnapshot();
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget.jsx
index bbe8dd83ae..2647d07c87 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget.jsx
@@ -6,7 +6,7 @@ import React from 'react';
import messages from '../messages';
import { hooks as transcriptHooks } from '../TranscriptWidget';
-export const LanguageNamesWidget = ({ transcripts, intl }) => {
+const LanguageNamesWidget = ({ transcripts, intl }) => {
let icon = ClosedCaptionOff;
const hasTranscripts = transcriptHooks.hasTranscripts(transcripts);
let message = intl.formatMessage(messages.noTranscriptsAdded);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
index 47aa9911bc..0c4a0f089a 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/index.jsx
@@ -11,7 +11,7 @@ import hooks from './hooks';
import LanguageNamesWidget from './LanguageNamesWidget';
import videoThumbnail from '../../../../../../data/images/videoThumbnail.svg';
-export const VideoPreviewWidget = ({
+const VideoPreviewWidget = ({
thumbnail,
videoSource,
transcripts,
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx
index 7bc8d6ad7f..096f98010b 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx
@@ -1,6 +1,6 @@
import { dispatch } from 'react-redux';
import { actions } from '../../../../../../data/redux';
-import { MockUseState } from '../../../../../../../testUtils';
+import { MockUseState } from '../../../../../../testUtils';
import * as requests from '../../../../../../data/redux/thunkActions/requests';
import * as hooks from './hooks';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
index 9726266fad..85045f0810 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
@@ -21,13 +21,13 @@ import * as widgetHooks from '../hooks';
import * as hooks from './hooks';
import messages from './messages';
-import { ErrorAlert } from '../../../../../../sharedComponents/ErrorAlerts/ErrorAlert';
+import ErrorAlert from '../../../../../../sharedComponents/ErrorAlerts/ErrorAlert';
import CollapsibleFormWidget from '../CollapsibleFormWidget';
/**
* Collapsible Form widget controlling video source as well as fallback sources
*/
-export const VideoSourceWidget = ({
+const VideoSourceWidget = ({
// injected
intl,
}) => {
@@ -157,4 +157,5 @@ VideoSourceWidget.propTypes = {
intl: intlShape.isRequired,
};
+export const VideoSourceWidgetInternal = VideoSourceWidget; // For testing only
export default injectIntl(VideoSourceWidget);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.jsx
index a88f9a3fc1..c472e65129 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.test.jsx
@@ -1,9 +1,10 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { dispatch } from 'react-redux';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../../testUtils';
-import { VideoSourceWidget } from '.';
+import { formatMessage } from '../../../../../../testUtils';
+import { VideoSourceWidgetInternal as VideoSourceWidget } from '.';
import * as hooks from './hooks';
jest.mock('react-redux', () => {
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
index a51ffd377b..d0b8503e2b 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.js
@@ -13,6 +13,10 @@ import {
onValue,
onChecked,
} from './handlers';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const selectorKeys = keyStore(selectors.video);
@@ -254,11 +258,3 @@ export const widgetValues = ({ fields, dispatch }) => Object.keys(fields).reduce
}),
{},
);
-
-export default {
- arrayWidget,
- genericWidget,
- objectWidget,
- selectorKeys,
- widgetValues,
-};
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
index c5acb0c646..ebfa493729 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/hooks.test.js
@@ -1,9 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
+
import { useEffect } from 'react';
import { useSelector } from 'react-redux';
import { keyStore } from '../../../../../utils';
import { actions, selectors } from '../../../../../data/redux';
-import { MockUseState } from '../../../../../../testUtils';
+import { MockUseState } from '../../../../../testUtils';
import * as handlers from './handlers';
import * as hooks from './hooks';
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.jsx
index 138ba0ab3a..5f01ec92cb 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.jsx
@@ -8,7 +8,7 @@ import {
} from '@edx/frontend-platform/i18n';
// import VideoPreview from './components/VideoPreview';
-import ErrorSummary from './ErrorSummary';
+import { ErrorSummary } from './ErrorSummary';
import DurationWidget from './components/DurationWidget';
import HandoutWidget from './components/HandoutWidget';
import LicenseWidget from './components/LicenseWidget';
@@ -20,7 +20,7 @@ import './index.scss';
import SocialShareWidget from './components/SocialShareWidget';
import messages from '../../messages';
-export const VideoSettingsModal = ({
+const VideoSettingsModal = ({
onReturn,
isLibrary,
}) => (
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.scss b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.scss
index 28185d48c6..119b04dfba 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.scss
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.scss
@@ -1,6 +1,6 @@
-.video-settings-modal {
- .video-preview {
- }
- .video-controls {
- }
-}
+// .video-settings-modal {
+// .video-preview {
+// }
+// .video-controls {
+// }
+// }
diff --git a/src/editors/containers/VideoEditor/hooks.js b/src/editors/containers/VideoEditor/hooks.js
index 392f47d9be..c046888879 100644
--- a/src/editors/containers/VideoEditor/hooks.js
+++ b/src/editors/containers/VideoEditor/hooks.js
@@ -2,6 +2,10 @@ import { useState, createContext } from 'react';
import { thunkActions } from '../../data/redux';
import { StrictDict } from '../../utils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
export const ErrorContext = createContext();
diff --git a/src/editors/containers/VideoEditor/hooks.test.js b/src/editors/containers/VideoEditor/hooks.test.js
index 5ee6652102..32a8df46d8 100644
--- a/src/editors/containers/VideoEditor/hooks.test.js
+++ b/src/editors/containers/VideoEditor/hooks.test.js
@@ -1,7 +1,11 @@
import { dispatch } from 'react-redux';
import { thunkActions } from '../../data/redux';
-import { MockUseState } from '../../../testUtils';
+import { MockUseState } from '../../testUtils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
jest.mock('react', () => ({
diff --git a/src/editors/containers/VideoEditor/index.jsx b/src/editors/containers/VideoEditor/index.jsx
index 6bd0236459..633e51f9f2 100644
--- a/src/editors/containers/VideoEditor/index.jsx
+++ b/src/editors/containers/VideoEditor/index.jsx
@@ -15,7 +15,7 @@ import VideoEditorModal from './components/VideoEditorModal';
import { ErrorContext, errorsHook, fetchVideoContent } from './hooks';
import messages from './messages';
-export const VideoEditor = ({
+const VideoEditor = ({
onClose,
returnFunction,
// injected
@@ -81,4 +81,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const VideoEditorInternal = VideoEditor; // For testing only
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(VideoEditor));
diff --git a/src/editors/containers/VideoEditor/index.test.jsx b/src/editors/containers/VideoEditor/index.test.jsx
index fd59b97eb5..99c1f157a4 100644
--- a/src/editors/containers/VideoEditor/index.test.jsx
+++ b/src/editors/containers/VideoEditor/index.test.jsx
@@ -1,10 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../testUtils';
+import { formatMessage } from '../../testUtils';
import { selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
-import { VideoEditor, mapStateToProps, mapDispatchToProps } from '.';
+import { VideoEditorInternal as VideoEditor, mapStateToProps, mapDispatchToProps } from '.';
jest.mock('../EditorContainer', () => 'EditorContainer');
jest.mock('./components/VideoEditorModal', () => 'VideoEditorModal');
diff --git a/src/editors/containers/VideoGallery/hooks.js b/src/editors/containers/VideoGallery/hooks.js
index d52a1cf316..648db7a641 100644
--- a/src/editors/containers/VideoGallery/hooks.js
+++ b/src/editors/containers/VideoGallery/hooks.js
@@ -1,6 +1,9 @@
import React from 'react';
import { useSelector } from 'react-redux';
-
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import messages from './messages';
import * as appHooks from '../../hooks';
@@ -211,10 +214,3 @@ export const useVideoProps = ({ videos }) => {
selectBtnProps,
};
};
-
-export default {
- useVideoProps,
- buildVideos,
- useCancelHandler,
- useVideoUploadHandler,
-};
diff --git a/src/editors/containers/VideoGallery/index.jsx b/src/editors/containers/VideoGallery/index.jsx
index 8973a09521..5f5a8a8ca8 100644
--- a/src/editors/containers/VideoGallery/index.jsx
+++ b/src/editors/containers/VideoGallery/index.jsx
@@ -2,14 +2,14 @@ import React, { useEffect } from 'react';
import { Image } from '@openedx/paragon';
import { useSelector } from 'react-redux';
import { selectors } from '../../data/redux';
-import hooks from './hooks';
+import * as hooks from './hooks';
import SelectionModal from '../../sharedComponents/SelectionModal';
import { acceptedImgKeys } from './utils';
import messages from './messages';
import { RequestKeys } from '../../data/constants/requests';
import videoThumbnail from '../../data/images/videoThumbnail.svg';
-export const VideoGallery = () => {
+const VideoGallery = () => {
const rawVideos = useSelector(selectors.app.videos);
const isLoaded = useSelector(
(state) => selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchVideos }),
diff --git a/src/editors/containers/VideoGallery/index.test.jsx b/src/editors/containers/VideoGallery/index.test.jsx
index 3abae625ed..79771c90d8 100644
--- a/src/editors/containers/VideoGallery/index.test.jsx
+++ b/src/editors/containers/VideoGallery/index.test.jsx
@@ -7,7 +7,7 @@ import {
act, fireEvent, render, screen,
} from '@testing-library/react';
-import { VideoGallery } from './index';
+import VideoGallery from './index';
jest.unmock('react-redux');
jest.unmock('@edx/frontend-platform/i18n');
diff --git a/src/editors/containers/VideoGallery/messages.js b/src/editors/containers/VideoGallery/messages.js
index c0c582c359..e26dd63db3 100644
--- a/src/editors/containers/VideoGallery/messages.js
+++ b/src/editors/containers/VideoGallery/messages.js
@@ -1,4 +1,4 @@
-export const messages = {
+const messages = {
// Gallery
emptyGalleryLabel: {
id: 'authoring.selectvideomodal.emptyGalleryLabel',
diff --git a/src/editors/containers/VideoUploadEditor/hooks.js b/src/editors/containers/VideoUploadEditor/hooks.js
index e0f3f38475..a2774d9c60 100644
--- a/src/editors/containers/VideoUploadEditor/hooks.js
+++ b/src/editors/containers/VideoUploadEditor/hooks.js
@@ -1,3 +1,7 @@
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { selectors, thunkActions } from '../../data/redux';
import store from '../../data/store';
diff --git a/src/editors/containers/VideoUploadEditor/index.jsx b/src/editors/containers/VideoUploadEditor/index.jsx
index 8aabeb5430..ae2be7b5fb 100644
--- a/src/editors/containers/VideoUploadEditor/index.jsx
+++ b/src/editors/containers/VideoUploadEditor/index.jsx
@@ -5,7 +5,7 @@ import './index.scss';
import messages from './messages';
import { VideoUploader } from './VideoUploader';
-export const VideoUploadEditor = () => {
+const VideoUploadEditor = () => {
const [loading, setLoading] = React.useState(false);
const intl = useIntl();
diff --git a/src/editors/containers/VideoUploadEditor/index.scss b/src/editors/containers/VideoUploadEditor/index.scss
index 2c0565c6c3..4e27f44d12 100644
--- a/src/editors/containers/VideoUploadEditor/index.scss
+++ b/src/editors/containers/VideoUploadEditor/index.scss
@@ -1,5 +1,5 @@
.dropzone-middle {
- border: 2px dashed #ccc;
+ border: 2px dashed #CCCCCC;
&.active {
border: 2px solid #262626; /* change color when active */
@@ -12,7 +12,6 @@
}
.video-id-prompt {
-
input::placeholder {
color: #454545;
// color: #5E35B1;
@@ -34,6 +33,6 @@
}
.prompt-button {
- background: rgba(239, 234, 247, 0.70);
+ background: rgba(239 234 247 / .70);
}
}
diff --git a/src/editors/data/constants/advancedOlxTemplates/circuitschematic.js b/src/editors/data/constants/advancedOlxTemplates/circuitschematic.js
index 032f0b0727..e3d5eb6ada 100644
--- a/src/editors/data/constants/advancedOlxTemplates/circuitschematic.js
+++ b/src/editors/data/constants/advancedOlxTemplates/circuitschematic.js
@@ -4,7 +4,7 @@
// display_name: Circuit Schematic Builder
// markdown: !!null
// data: |
-export const circuitSchematic = `
+const circuitSchematic = `
Circuit schematic problems allow students to create virtual circuits by
arranging elements such as voltage sources, capacitors, resistors, and
diff --git a/src/editors/data/constants/advancedOlxTemplates/customgrader.js b/src/editors/data/constants/advancedOlxTemplates/customgrader.js
index 227d02c084..f24c59263b 100644
--- a/src/editors/data/constants/advancedOlxTemplates/customgrader.js
+++ b/src/editors/data/constants/advancedOlxTemplates/customgrader.js
@@ -4,7 +4,7 @@
// display_name: Custom Python-Evaluated Input
// markdown: !!null
// data: |
-export const customGrader = `
+const customGrader = `
In custom Python-evaluated input (also called "write-your-own-grader"
problems), the grader uses a Python script that you create and embed in
diff --git a/src/editors/data/constants/advancedOlxTemplates/formularesponse.js b/src/editors/data/constants/advancedOlxTemplates/formularesponse.js
index b77a166ae8..72aaa62c65 100644
--- a/src/editors/data/constants/advancedOlxTemplates/formularesponse.js
+++ b/src/editors/data/constants/advancedOlxTemplates/formularesponse.js
@@ -4,7 +4,7 @@
// display_name: Math Expression Input
// markdown: !!null
// data: |
-export const formulaResponse = `
+const formulaResponse = `
You can use this template as a guide to the OLX markup to use for math expression problems. Edit this component to replace the example with your own assessment.
In an image mapped input problem, also known as a "pointing on a picture" problem, students click inside a defined region in an image. You define this region by including coordinates in the body of the problem. You can define one rectangular region,
multiple rectangular regions, or one non-rectangular region. For more information, see
diff --git a/src/editors/data/constants/advancedOlxTemplates/jsinput_response.js b/src/editors/data/constants/advancedOlxTemplates/jsinput_response.js
index 6ebaa1565a..34e6f6e55c 100644
--- a/src/editors/data/constants/advancedOlxTemplates/jsinput_response.js
+++ b/src/editors/data/constants/advancedOlxTemplates/jsinput_response.js
@@ -5,7 +5,7 @@
// markdown: !!null
// showanswer: never
// data: |
-export const jsInputResponse = `
+const jsInputResponse = `
In these problems (also called custom JavaScript problems or JS Input
problems), you add a problem or tool that uses JavaScript in Studio.
diff --git a/src/editors/data/constants/advancedOlxTemplates/problem_with_hint.js b/src/editors/data/constants/advancedOlxTemplates/problem_with_hint.js
index 8ee6c867a9..442b0cc3d7 100644
--- a/src/editors/data/constants/advancedOlxTemplates/problem_with_hint.js
+++ b/src/editors/data/constants/advancedOlxTemplates/problem_with_hint.js
@@ -4,7 +4,7 @@
// display_name: Problem with Adaptive Hint
// markdown: !!null
// data: |
-export const problemWithHint = `
+const problemWithHint = `
Problem With Adaptive Hint
This problem demonstrates a question with hints, based on using the hintfn method.
diff --git a/src/editors/data/constants/analyticsEvt.js b/src/editors/data/constants/analyticsEvt.js
index 1b201956d3..1fef2fa7d1 100644
--- a/src/editors/data/constants/analyticsEvt.js
+++ b/src/editors/data/constants/analyticsEvt.js
@@ -1,4 +1,4 @@
-export const analyticsEvt = {
+const analyticsEvt = {
editorSaveClick: 'edx.ui.authoring.editor.save',
editorCancelClick: 'edx.ui.authoring.editor.cancel',
videoGalleryCancelClick: 'edx.ui.authoring.videogallery.cancel',
diff --git a/src/editors/data/constants/basicOlxTemplates/dropdown.js b/src/editors/data/constants/basicOlxTemplates/dropdown.js
index 4988b43e2d..e66e0d1f0d 100644
--- a/src/editors/data/constants/basicOlxTemplates/dropdown.js
+++ b/src/editors/data/constants/basicOlxTemplates/dropdown.js
@@ -1,5 +1,5 @@
/* eslint-disable */
-export const dropdown = `
+const dropdown = `
diff --git a/src/editors/data/constants/basicOlxTemplates/numeric.js b/src/editors/data/constants/basicOlxTemplates/numeric.js
index dfaae48a0d..5b7a915c9c 100644
--- a/src/editors/data/constants/basicOlxTemplates/numeric.js
+++ b/src/editors/data/constants/basicOlxTemplates/numeric.js
@@ -1,5 +1,5 @@
/* eslint-disable */
-export const numeric = `
+const numeric = `
diff --git a/src/editors/data/constants/basicOlxTemplates/singleSelect.js b/src/editors/data/constants/basicOlxTemplates/singleSelect.js
index 08daf32d03..ea0e370366 100644
--- a/src/editors/data/constants/basicOlxTemplates/singleSelect.js
+++ b/src/editors/data/constants/basicOlxTemplates/singleSelect.js
@@ -1,5 +1,5 @@
/* eslint-disable */
-export const singleSelect = `
+const singleSelect = `
diff --git a/src/editors/data/constants/tinyMCE.js b/src/editors/data/constants/tinyMCE.js
index f7edbe273e..a6e40203a5 100644
--- a/src/editors/data/constants/tinyMCE.js
+++ b/src/editors/data/constants/tinyMCE.js
@@ -74,10 +74,3 @@ export const plugins = listKeyStore([
]);
export const textToSpeechIcon = '';
-
-export default StrictDict({
- buttons,
- commands,
- plugins,
- textToSpeechIcon,
-});
diff --git a/src/editors/data/redux/app/selectors.js b/src/editors/data/redux/app/selectors.js
index c9d23c2e07..9976eee19f 100644
--- a/src/editors/data/redux/app/selectors.js
+++ b/src/editors/data/redux/app/selectors.js
@@ -1,6 +1,10 @@
import { createSelector } from 'reselect';
import { blockTypes } from '../../constants/app';
import * as urls from '../../services/cms/urls';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './selectors';
export const appSelector = (state) => state.app;
diff --git a/src/editors/data/redux/game/selectors.js b/src/editors/data/redux/game/selectors.js
index 6cba1a7c3d..736d49f93b 100644
--- a/src/editors/data/redux/game/selectors.js
+++ b/src/editors/data/redux/game/selectors.js
@@ -1,4 +1,8 @@
import { createSelector } from 'reselect';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './selectors';
export const gameState = (state) => state.game;
diff --git a/src/editors/data/redux/index.js b/src/editors/data/redux/index.js
index 05811bbf24..84e5648bda 100644
--- a/src/editors/data/redux/index.js
+++ b/src/editors/data/redux/index.js
@@ -8,7 +8,6 @@ import * as video from './video';
import * as problem from './problem';
import * as game from './game';
-/* eslint-disable import/no-cycle */
export { default as thunkActions } from './thunkActions';
const modules = {
diff --git a/src/editors/data/redux/problem/reducers.js b/src/editors/data/redux/problem/reducers.js
index c61dfb240f..42e1f7c57c 100644
--- a/src/editors/data/redux/problem/reducers.js
+++ b/src/editors/data/redux/problem/reducers.js
@@ -1,4 +1,4 @@
-import _ from 'lodash-es';
+import _ from 'lodash';
import { createSlice } from '@reduxjs/toolkit';
import { indexToLetterMap } from '../../../containers/ProblemEditor/data/OLXParser';
import { StrictDict } from '../../../utils';
diff --git a/src/editors/data/redux/problem/selectors.js b/src/editors/data/redux/problem/selectors.js
index efd327ee48..1ba3c3ea0b 100644
--- a/src/editors/data/redux/problem/selectors.js
+++ b/src/editors/data/redux/problem/selectors.js
@@ -1,4 +1,8 @@
import { createSelector } from 'reselect';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './selectors';
export const problemState = (state) => state.problem;
diff --git a/src/editors/data/redux/requests/selectors.js b/src/editors/data/redux/requests/selectors.js
index d66cf1384e..c9b318bcbe 100644
--- a/src/editors/data/redux/requests/selectors.js
+++ b/src/editors/data/redux/requests/selectors.js
@@ -1,5 +1,9 @@
import { StrictDict } from '../../../utils';
import { RequestStates } from '../../constants/requests';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './selectors';
export const requestStatus = (state, { requestKey }) => state.requests[requestKey];
diff --git a/src/editors/data/redux/thunkActions/app.js b/src/editors/data/redux/thunkActions/app.js
index a248279d21..fa50c91a06 100644
--- a/src/editors/data/redux/thunkActions/app.js
+++ b/src/editors/data/redux/thunkActions/app.js
@@ -1,10 +1,20 @@
import { StrictDict, camelizeKeys } from '../../../utils';
-/* eslint-disable import/no-cycle */
-import { actions } from '..';
import * as requests from './requests';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './app';
+import { actions as appActions } from '../app';
+import { actions as requestsActions } from '../requests';
import { RequestKeys } from '../../constants/requests';
+// Similar to `import { actions } from '..';` but avoid circular imports:
+const actions = {
+ app: appActions,
+ requests: requestsActions,
+};
+
export const fetchBlock = () => (dispatch) => {
dispatch(requests.fetchBlock({
onSuccess: (response) => {
diff --git a/src/editors/data/redux/thunkActions/index.js b/src/editors/data/redux/thunkActions/index.js
index ec9542fd74..b787e23cff 100644
--- a/src/editors/data/redux/thunkActions/index.js
+++ b/src/editors/data/redux/thunkActions/index.js
@@ -1,6 +1,5 @@
import { StrictDict } from '../../../utils';
-/* eslint-disable import/no-cycle */
import app from './app';
import video from './video';
import problem from './problem';
diff --git a/src/editors/data/redux/thunkActions/problem.js b/src/editors/data/redux/thunkActions/problem.js
index 16bebedf62..62de4f44a9 100644
--- a/src/editors/data/redux/thunkActions/problem.js
+++ b/src/editors/data/redux/thunkActions/problem.js
@@ -1,6 +1,5 @@
-import _ from 'lodash-es';
-/* eslint-disable import/no-cycle */
-import { actions } from '..';
+import _ from 'lodash';
+import { actions as problemActions } from '../problem';
import * as requests from './requests';
import { OLXParser } from '../../../containers/ProblemEditor/data/OLXParser';
import { parseSettings } from '../../../containers/ProblemEditor/data/SettingsParser';
@@ -10,6 +9,9 @@ import { blankProblemOLX } from '../../../containers/ProblemEditor/data/mockData
import { camelizeKeys } from '../../../utils';
import { fetchEditorContent } from '../../../containers/ProblemEditor/components/EditProblemView/hooks';
+// Similar to `import { actions, selectors } from '..';` but avoid circular imports:
+const actions = { problem: problemActions };
+
export const switchToAdvancedEditor = () => (dispatch, getState) => {
const state = getState();
const editorObject = fetchEditorContent({ format: '' });
diff --git a/src/editors/data/redux/thunkActions/problem.test.js b/src/editors/data/redux/thunkActions/problem.test.js
index da1f0ad477..828547b5b4 100644
--- a/src/editors/data/redux/thunkActions/problem.test.js
+++ b/src/editors/data/redux/thunkActions/problem.test.js
@@ -1,5 +1,11 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import { actions } from '..';
-import * as module from './problem';
+import {
+ initializeProblem,
+ switchToAdvancedEditor,
+ fetchAdvancedSettings,
+ loadProblem,
+} from './problem';
import { checkboxesOLXWithFeedbackAndHintsOLX, advancedProblemOlX, blankProblemOLX } from '../../../containers/ProblemEditor/data/mockData/olxTestData';
import { ProblemTypeKeys } from '../../constants/problem';
@@ -7,13 +13,11 @@ const mockOlx = 'SOmEVALue';
const mockBuildOlx = jest.fn(() => mockOlx);
jest.mock('../../../containers/ProblemEditor/data/ReactStateOLXParser', () => jest.fn().mockImplementation(() => ({ buildOLX: mockBuildOlx })));
-jest.mock('..', () => ({
+jest.mock('../problem', () => ({
actions: {
- problem: {
- load: () => {},
- setEnableTypeSelection: () => {},
- updateField: (args) => args,
- },
+ load: () => {},
+ setEnableTypeSelection: () => {},
+ updateField: (args) => args,
},
}));
@@ -48,31 +52,31 @@ describe('problem thunkActions', () => {
jest.restoreAllMocks();
});
test('initializeProblem visual Problem :', () => {
- module.initializeProblem(blockValue)(dispatch);
+ initializeProblem(blockValue)(dispatch);
expect(dispatch).toHaveBeenCalled();
});
test('switchToAdvancedEditor visual Problem', () => {
- module.switchToAdvancedEditor()(dispatch, getState);
+ switchToAdvancedEditor()(dispatch, getState);
expect(dispatch).toHaveBeenCalledWith(
actions.problem.updateField({ problemType: ProblemTypeKeys.ADVANCED, rawOLX: mockOlx }),
);
});
describe('fetchAdvanceSettings', () => {
it('dispatches fetchAdvanceSettings action', () => {
- module.fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
+ fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
[[dispatchedAction]] = dispatch.mock.calls;
expect(dispatchedAction.fetchAdvanceSettings).not.toEqual(undefined);
});
it('dispatches actions.problem.updateField and loadProblem on success', () => {
dispatch.mockClear();
- module.fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
+ fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
[[dispatchedAction]] = dispatch.mock.calls;
dispatchedAction.fetchAdvanceSettings.onSuccess({ data: { key: 'test', max_attempts: 1 } });
expect(dispatch).toHaveBeenCalledWith(actions.problem.load());
});
it('calls loadProblem on failure', () => {
dispatch.mockClear();
- module.fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
+ fetchAdvancedSettings({ rawOLX, rawSettings })(dispatch);
[[dispatchedAction]] = dispatch.mock.calls;
dispatchedAction.fetchAdvanceSettings.onFailure();
expect(dispatch).toHaveBeenCalledWith(actions.problem.load());
@@ -81,12 +85,12 @@ describe('problem thunkActions', () => {
describe('loadProblem', () => {
test('initializeProblem advanced Problem', () => {
rawOLX = advancedProblemOlX.rawOLX;
- module.loadProblem({ rawOLX, rawSettings, defaultSettings })(dispatch);
+ loadProblem({ rawOLX, rawSettings, defaultSettings })(dispatch);
expect(dispatch).toHaveBeenCalledWith(actions.problem.load());
});
test('initializeProblem blank Problem', () => {
rawOLX = blankProblemOLX.rawOLX;
- module.loadProblem({ rawOLX, rawSettings, defaultSettings })(dispatch);
+ loadProblem({ rawOLX, rawSettings, defaultSettings })(dispatch);
expect(dispatch).toHaveBeenCalledWith(actions.problem.setEnableTypeSelection());
});
});
diff --git a/src/editors/data/redux/thunkActions/requests.js b/src/editors/data/redux/thunkActions/requests.js
index f419c9a4bb..46f9d1a03a 100644
--- a/src/editors/data/redux/thunkActions/requests.js
+++ b/src/editors/data/redux/thunkActions/requests.js
@@ -1,12 +1,20 @@
import { StrictDict } from '../../../utils';
import { RequestKeys } from '../../constants/requests';
-/* eslint-disable import/no-cycle */
-import { actions, selectors } from '..';
import api, { loadImages } from '../../services/cms/api';
+import { actions as requestsActions } from '../requests';
+import { selectors as appSelectors } from '../app';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './requests';
+// Similar to `import { actions, selectors } from '..';` but avoid circular imports:
+const actions = { requests: requestsActions };
+const selectors = { app: appSelectors };
+
/**
* Wrapper around a network request promise, that sends actions to the redux store to
* track the state of that promise.
diff --git a/src/editors/data/redux/thunkActions/video.js b/src/editors/data/redux/thunkActions/video.js
index 8a54b68179..352d989737 100644
--- a/src/editors/data/redux/thunkActions/video.js
+++ b/src/editors/data/redux/thunkActions/video.js
@@ -1,11 +1,19 @@
-/* eslint-disable import/no-cycle */
-import _, { isEmpty } from 'lodash-es';
-import { actions, selectors } from '..';
+import _, { isEmpty } from 'lodash';
import { removeItemOnce } from '../../../utils';
import * as requests from './requests';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './video';
import { valueFromDuration } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks';
import { parseYoutubeId } from '../../services/cms/api';
+import { selectors as appSelectors } from '../app';
+import { actions as videoActions, selectors as videoSelectors } from '../video';
+
+// Similar to `import { actions, selectors } from '..';` but avoid circular imports:
+const actions = { video: videoActions };
+const selectors = { app: appSelectors, video: videoSelectors };
export const loadVideoData = (selectedVideoId, selectedVideoUrl) => (dispatch, getState) => {
const state = getState();
diff --git a/src/editors/data/redux/thunkActions/video.test.js b/src/editors/data/redux/thunkActions/video.test.js
index 6e53c87d90..75a668d0bc 100644
--- a/src/editors/data/redux/thunkActions/video.test.js
+++ b/src/editors/data/redux/thunkActions/video.test.js
@@ -2,23 +2,23 @@ import { actions } from '..';
import keyStore from '../../../utils/keyStore';
import * as thunkActions from './video';
-jest.mock('..', () => ({
+jest.mock('../video', () => ({
+ ...jest.requireActual('../video'),
actions: {
- video: {
- load: (args) => ({ load: args }),
- updateField: (args) => ({ updateField: args }),
- },
+ load: (args) => ({ load: args }),
+ updateField: (args) => ({ updateField: args }),
},
selectors: {
- app: {
- courseDetails: (state) => ({ courseDetails: state }),
- videos: (state) => ({ videos: state.app.videos }),
- },
- video: {
- videoId: (state) => ({ videoId: state }),
- videoSettings: (state) => ({ videoSettings: state }),
- getTranscriptDownloadUrl: (state) => ({ getTranscriptDownloadUrl: state }),
- },
+ videoId: (state) => ({ videoId: state }),
+ videoSettings: (state) => ({ videoSettings: state }),
+ getTranscriptDownloadUrl: (state) => ({ getTranscriptDownloadUrl: state }),
+ },
+}));
+jest.mock('../app', () => ({
+ ...jest.requireActual('../app'),
+ selectors: {
+ courseDetails: (state) => ({ courseDetails: state }),
+ videos: (state) => ({ videos: state.app.videos }),
},
}));
jest.mock('./requests', () => ({
diff --git a/src/editors/data/redux/video/selectors.js b/src/editors/data/redux/video/selectors.js
index 77a740ca1e..f71c014cf7 100644
--- a/src/editors/data/redux/video/selectors.js
+++ b/src/editors/data/redux/video/selectors.js
@@ -4,6 +4,10 @@ import { keyStore } from '../../../utils';
import { videoTranscriptLanguages } from '../../constants/video';
import { initialState } from './reducer';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './selectors';
import * as AppSelectors from '../app/selectors';
import { downloadVideoTranscriptURL, downloadVideoHandoutUrl, mediaTranscriptURL } from '../../services/cms/urls';
diff --git a/src/editors/data/services/cms/api.js b/src/editors/data/services/cms/api.js
index 38abad7154..7d732c15d4 100644
--- a/src/editors/data/services/cms/api.js
+++ b/src/editors/data/services/cms/api.js
@@ -1,6 +1,10 @@
import { camelizeKeys } from '../../../utils';
import * as urls from './urls';
import { get, post, deleteObject } from './utils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './api';
import * as mockApi from './mockApi';
import { durationStringFromValue } from '../../../containers/VideoEditor/components/VideoSettingsModal/components/DurationWidget/hooks';
diff --git a/src/editors/data/services/cms/api.test.js b/src/editors/data/services/cms/api.test.js
index 116efbf627..7abec953cc 100644
--- a/src/editors/data/services/cms/api.test.js
+++ b/src/editors/data/services/cms/api.test.js
@@ -84,9 +84,9 @@ describe('cms api', () => {
it('should call get with normal accept header for prod', async () => {
process.env.NODE_ENV = 'production';
process.env.MFE_NAME = 'frontend-app-library-authoring';
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const { apiMethods } = await import('./api');
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
@@ -96,9 +96,9 @@ describe('cms api', () => {
it('should call get with normal accept header for course-authoring', async () => {
process.env.NODE_ENV = 'development';
process.env.MFE_NAME = 'frontend-app-course-authoring';
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const { apiMethods } = await import('./api');
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
@@ -108,9 +108,9 @@ describe('cms api', () => {
it('should call get with special accept header "*/*" for course-authoring', async () => {
process.env.NODE_ENV = 'development';
process.env.MFE_NAME = 'frontend-app-library-authoring';
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const { apiMethods } = await import('./api');
- // eslint-disable-next-line no-shadow
+ // eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
diff --git a/src/editors/data/services/cms/mockApi.js b/src/editors/data/services/cms/mockApi.js
index 5c4440b3ec..ca50e0c0a6 100644
--- a/src/editors/data/services/cms/mockApi.js
+++ b/src/editors/data/services/cms/mockApi.js
@@ -1,7 +1,7 @@
/* istanbul ignore file */
import * as urls from './urls';
-const mockPromise = (returnValue) => new Promise(resolve => resolve(returnValue));
+const mockPromise = (returnValue) => new Promise(resolve => { resolve(returnValue); });
// TODO: update to return block data appropriate per block ID, which will equal block type
// eslint-disable-next-line
diff --git a/src/editors/data/store.js b/src/editors/data/store.js
index 4e73ca33ad..a10b1ba28f 100755
--- a/src/editors/data/store.js
+++ b/src/editors/data/store.js
@@ -1,6 +1,6 @@
import * as redux from 'redux';
import thunkMiddleware from 'redux-thunk';
-import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
+import { composeWithDevToolsLogOnlyInProduction } from '@redux-devtools/extension';
import { createLogger } from 'redux-logger';
import reducer, { actions, selectors } from './redux';
@@ -12,7 +12,7 @@ export const createStore = () => {
const store = redux.createStore(
reducer,
- composeWithDevTools(redux.applyMiddleware(...middleware)),
+ composeWithDevToolsLogOnlyInProduction(redux.applyMiddleware(...middleware)),
);
/**
diff --git a/src/editors/data/store.test.js b/src/editors/data/store.test.js
index 0a221d6799..6b8c851d94 100644
--- a/src/editors/data/store.test.js
+++ b/src/editors/data/store.test.js
@@ -1,6 +1,6 @@
import { applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
-import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction';
+import { composeWithDevToolsLogOnlyInProduction } from '@redux-devtools/extension';
import { createLogger } from 'redux-logger';
import rootReducer, { actions, selectors } from './redux';
@@ -22,8 +22,8 @@ jest.mock('redux', () => ({
applyMiddleware: (...middleware) => ({ applied: middleware }),
createStore: (reducer, middleware) => ({ reducer, middleware }),
}));
-jest.mock('redux-devtools-extension/logOnlyInProduction', () => ({
- composeWithDevTools: (middleware) => ({ withDevTools: middleware }),
+jest.mock('@redux-devtools/extension', () => ({
+ composeWithDevToolsLogOnlyInProduction: (middleware) => ({ withDevTools: middleware }),
}));
describe('store aggregator module', () => {
@@ -37,7 +37,7 @@ describe('store aggregator module', () => {
describe('middleware', () => {
it('exports thunk and logger middleware, composed and applied with dev tools', () => {
expect(createStore().middleware).toEqual(
- composeWithDevTools(applyMiddleware(thunkMiddleware, createLogger())),
+ composeWithDevToolsLogOnlyInProduction(applyMiddleware(thunkMiddleware, createLogger())),
);
});
});
diff --git a/src/editors/example.jsx b/src/editors/example.jsx
index f0c65a6e47..98d238f688 100644
--- a/src/editors/example.jsx
+++ b/src/editors/example.jsx
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable import/extensions */
/* eslint-disable import/no-unresolved */
/**
@@ -16,6 +17,10 @@ import { Spinner } from '@openedx/paragon';
import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import EditorContainer from '../EditorContainer';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from '..';
import { actions, selectors } from '../../data/redux';
import { RequestKeys } from '../../data/constants/requests';
diff --git a/src/editors/hooks.js b/src/editors/hooks.js
index d2488ad757..c0d1b70a87 100644
--- a/src/editors/hooks.js
+++ b/src/editors/hooks.js
@@ -4,6 +4,10 @@ import { sendTrackEvent } from '@edx/frontend-platform/analytics';
import analyticsEvt from './data/constants/analyticsEvt';
import { actions, thunkActions } from './data/redux';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { RequestKeys } from './data/constants/requests';
diff --git a/src/editors/setupEditorTest.js b/src/editors/setupEditorTest.js
new file mode 100644
index 0000000000..54b23ca0ab
--- /dev/null
+++ b/src/editors/setupEditorTest.js
@@ -0,0 +1,122 @@
+// These additional mocks and setup are required for some tests in src/editors/
+// and are imported on an as-needed basis.
+// eslint-disable-next-line import/no-extraneous-dependencies
+import 'jest-canvas-mock';
+
+jest.mock('@edx/frontend-platform/i18n', () => {
+ const i18n = jest.requireActual('@edx/frontend-platform/i18n');
+ const PropTypes = jest.requireActual('prop-types');
+ return {
+ ...i18n,
+ intlShape: PropTypes.shape({
+ formatMessage: PropTypes.func,
+ }),
+ defineMessages: m => m,
+ getLocale: () => 'getLocale',
+ FormattedDate: () => 'FormattedDate',
+ FormattedMessage: () => 'FormattedMessage',
+ FormattedTime: () => 'FormattedTime',
+ };
+});
+
+jest.mock('@openedx/paragon', () => jest.requireActual('./testUtils').mockNestedComponents({
+ Alert: {
+ Heading: 'Alert.Heading',
+ },
+ AlertModal: 'AlertModal',
+ ActionRow: {
+ Spacer: 'ActionRow.Spacer',
+ },
+ Badge: 'Badge',
+ Button: 'Button',
+ ButtonGroup: 'ButtonGroup',
+ Collapsible: {
+ Advanced: 'Advanced',
+ Body: 'Body',
+ Trigger: 'Trigger',
+ Visible: 'Visible',
+ },
+ Card: {
+ Header: 'Card.Header',
+ Section: 'Card.Section',
+ Footer: 'Card.Footer',
+ Body: 'Card.Body',
+ },
+ CheckboxControl: 'CheckboxControl',
+ Col: 'Col',
+ Container: 'Container',
+ Dropdown: {
+ Item: 'Dropdown.Item',
+ Menu: 'Dropdown.Menu',
+ Toggle: 'Dropdown.Toggle',
+ },
+ ErrorContext: {
+ Provider: 'ErrorContext.Provider',
+ },
+ Hyperlink: 'Hyperlink',
+ Icon: 'Icon',
+ IconButton: 'IconButton',
+ IconButtonWithTooltip: 'IconButtonWithTooltip',
+ Image: 'Image',
+ MailtoLink: 'MailtoLink',
+ ModalDialog: {
+ Footer: 'ModalDialog.Footer',
+ Header: 'ModalDialog.Header',
+ Title: 'ModalDialog.Title',
+ Body: 'ModalDialog.Body',
+ CloseButton: 'ModalDialog.CloseButton',
+ },
+ Form: {
+ Checkbox: 'Form.Checkbox',
+ Control: {
+ Feedback: 'Form.Control.Feedback',
+ },
+ Group: 'Form.Group',
+ Label: 'Form.Label',
+ Text: 'Form.Text',
+ Row: 'Form.Row',
+ Radio: 'Radio',
+ RadioSet: 'RadioSet',
+ },
+ OverlayTrigger: 'OverlayTrigger',
+ Tooltip: 'Tooltip',
+ FullscreenModal: 'FullscreenModal',
+ Row: 'Row',
+ Scrollable: 'Scrollable',
+ SelectableBox: {
+ Set: 'SelectableBox.Set',
+ },
+
+ Spinner: 'Spinner',
+ Stack: 'Stack',
+ Toast: 'Toast',
+ Truncate: 'Truncate',
+ useWindowSize: { height: '500px' },
+}));
+
+jest.mock('@openedx/paragon/icons', () => ({
+ Close: jest.fn().mockName('icons.Close'),
+ Edit: jest.fn().mockName('icons.Edit'),
+ Locked: jest.fn().mockName('icons.Locked'),
+ Unlocked: jest.fn().mockName('icons.Unlocked'),
+}));
+
+// Mock react-redux hooks
+// unmock for integration tests
+jest.mock('react-redux', () => {
+ const dispatch = jest.fn((...args) => ({ dispatch: args })).mockName('react-redux.dispatch');
+ return {
+ connect: (mapStateToProps, mapDispatchToProps) => (component) => ({
+ mapStateToProps,
+ mapDispatchToProps,
+ component,
+ }),
+ useDispatch: jest.fn(() => dispatch),
+ useSelector: jest.fn((selector) => ({ useSelector: selector })),
+ };
+});
+
+// Mock the plugins repo so jest will stop complaining about ES6 syntax
+jest.mock('frontend-components-tinymce-advanced-plugins', () => ({
+ a11ycheckerCss: '',
+}));
diff --git a/src/editors/sharedComponents/BaseModal/index.jsx b/src/editors/sharedComponents/BaseModal/index.jsx
index dd1bef7484..74639dd54d 100644
--- a/src/editors/sharedComponents/BaseModal/index.jsx
+++ b/src/editors/sharedComponents/BaseModal/index.jsx
@@ -10,7 +10,7 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
import messages from './messages';
-export const BaseModal = ({
+const BaseModal = ({
isOpen,
close,
title,
diff --git a/src/editors/sharedComponents/BaseModal/index.test.jsx b/src/editors/sharedComponents/BaseModal/index.test.jsx
index 1afd1662c2..cca9a4b57d 100644
--- a/src/editors/sharedComponents/BaseModal/index.test.jsx
+++ b/src/editors/sharedComponents/BaseModal/index.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
diff --git a/src/editors/sharedComponents/CodeEditor/index.jsx b/src/editors/sharedComponents/CodeEditor/index.jsx
index eeeacafd37..29a4ed2daf 100644
--- a/src/editors/sharedComponents/CodeEditor/index.jsx
+++ b/src/editors/sharedComponents/CodeEditor/index.jsx
@@ -11,7 +11,7 @@ import './index.scss';
import * as hooks from './hooks';
-export const CodeEditor = ({
+const CodeEditor = ({
innerRef,
value,
lang,
@@ -53,4 +53,5 @@ CodeEditor.propTypes = {
lang: PropTypes.string.isRequired,
};
+export const CodeEditorInternal = CodeEditor; // For testing only
export default injectIntl(CodeEditor);
diff --git a/src/editors/sharedComponents/CodeEditor/index.test.jsx b/src/editors/sharedComponents/CodeEditor/index.test.jsx
index d0827754ca..0760f8e0d1 100644
--- a/src/editors/sharedComponents/CodeEditor/index.test.jsx
+++ b/src/editors/sharedComponents/CodeEditor/index.test.jsx
@@ -1,14 +1,17 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { EditorState } from '@codemirror/state';
import { EditorView } from '@codemirror/view';
import { html } from '@codemirror/lang-html';
-import { formatMessage, MockUseState } from '../../../testUtils';
+import { formatMessage, MockUseState } from '../../testUtils';
import alphanumericMap from './constants';
import * as module from './index';
import * as hooks from './hooks';
+const CodeEditor = module.CodeEditorInternal;
+
jest.mock('@codemirror/view');
jest.mock('react', () => ({
@@ -171,7 +174,7 @@ describe('CodeEditor', () => {
test('Renders and calls Hooks ', () => {
jest.spyOn(hooks, 'prepareShowBtnEscapeHTML').mockImplementation(() => ({ showBtnEscapeHTML: true, hideBtn: mockHideBtn }));
// Note: ref won't show up as it is not acutaly a DOM attribute.
- expect(shallow().snapshot).toMatchSnapshot();
+ expect(shallow().snapshot).toMatchSnapshot();
expect(hooks.createCodeMirrorDomNode).toHaveBeenCalled();
});
});
diff --git a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.jsx b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.jsx
index 9b5bdadc65..3e3ef935aa 100644
--- a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.jsx
@@ -33,7 +33,7 @@ export const hooks = {
},
};
-export const ErrorAlert = ({
+const ErrorAlert = ({
dismissError,
hideHeading,
isError,
diff --git a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.jsx b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.jsx
index f8d8f7b3ce..a8b1f0504b 100644
--- a/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/ErrorAlert.test.jsx
@@ -1,9 +1,8 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import * as module from './ErrorAlert';
-import { MockUseState } from '../../../testUtils';
-
-const { ErrorAlert } = module;
+import ErrorAlert, { hooks } from './ErrorAlert';
+import { MockUseState } from '../../testUtils';
jest.mock('react', () => ({
...jest.requireActual('react'),
@@ -12,7 +11,7 @@ jest.mock('react', () => ({
useCallback: (cb, prereqs) => ({ cb, prereqs }),
}));
-const state = new MockUseState(module.hooks);
+const state = new MockUseState(hooks);
let hook;
const testValue = 'testVALUE';
@@ -33,7 +32,7 @@ describe('ErrorAlert component', () => {
isError: testValue,
};
beforeEach(() => {
- hook = module.hooks.dismissalHooks(props);
+ hook = hooks.dismissalHooks(props);
});
it('returns isDismissed value, initialized to false', () => {
expect(state.stateVals.isDismissed).toEqual(hook.isDismissed);
@@ -61,7 +60,7 @@ describe('ErrorAlert component', () => {
props = {
dismissError: jest.fn(),
};
- jest.spyOn(module.hooks, 'dismissalHooks').mockImplementation(() => ({
+ jest.spyOn(hooks, 'dismissalHooks').mockImplementation(() => ({
isDismissed: false,
dismissAlert: jest.fn().mockName('dismissAlert'),
}));
diff --git a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
index d098c76780..e8a8167174 100644
--- a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.jsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
import ErrorAlert from './ErrorAlert';
-export const FetchErrorAlert = ({
+const FetchErrorAlert = ({
message,
isFetchError,
}) => (
diff --git a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.test.jsx b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.test.jsx
index c7f365b5ac..2a849ba417 100644
--- a/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.test.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/FetchErrorAlert.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { FetchErrorAlert } from './FetchErrorAlert';
+import FetchErrorAlert from './FetchErrorAlert';
jest.mock('../../data/redux', () => ({
selectors: {
diff --git a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.jsx b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.jsx
index 9119c4627a..3348515635 100644
--- a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.jsx
@@ -4,7 +4,7 @@ import { FormattedMessage } from '@edx/frontend-platform/i18n';
import ErrorAlert from './ErrorAlert';
-export const UploadErrorAlert = ({
+const UploadErrorAlert = ({
message,
isUploadError,
}) => (
diff --git a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx
index d3afb4b7aa..09c8a7df57 100644
--- a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx
+++ b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx
@@ -1,6 +1,7 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { UploadErrorAlert } from './UploadErrorAlert';
+import UploadErrorAlert from './UploadErrorAlert';
jest.mock('../../data/redux', () => ({
selectors: {
diff --git a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
index d09a6a5cb5..e00552b1aa 100644
--- a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
+++ b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.jsx
@@ -14,7 +14,7 @@ import { selectors } from '../../data/redux';
* An error page that displays a generic message for unexpected errors. Also contains a "Try
* Again" button to refresh the page.
*/
-export const ErrorPage = ({
+const ErrorPage = ({
message,
studioEndpointUrl,
learningContextId,
@@ -86,4 +86,5 @@ export const mapStateToProps = (state) => ({
unitData: selectors.app.unitUrl(state),
});
+export const ErrorPageInternal = ErrorPage; // For testing only
export default injectIntl(connect(mapStateToProps)(ErrorPage));
diff --git a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.test.jsx b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.test.jsx
index 4c7d6e0857..139f6c98e1 100644
--- a/src/editors/sharedComponents/ErrorBoundary/ErrorPage.test.jsx
+++ b/src/editors/sharedComponents/ErrorBoundary/ErrorPage.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { selectors } from '../../data/redux';
-import { formatMessage } from '../../../testUtils';
-import { ErrorPage, mapStateToProps } from './ErrorPage';
+import { formatMessage } from '../../testUtils';
+import { ErrorPageInternal as ErrorPage, mapStateToProps } from './ErrorPage';
jest.mock('../../data/redux', () => ({
selectors: {
diff --git a/src/editors/sharedComponents/ExpandableTextArea/index.jsx b/src/editors/sharedComponents/ExpandableTextArea/index.jsx
index cf9025c5f1..a2f30d66d8 100644
--- a/src/editors/sharedComponents/ExpandableTextArea/index.jsx
+++ b/src/editors/sharedComponents/ExpandableTextArea/index.jsx
@@ -4,7 +4,7 @@ import TinyMceWidget from '../TinyMceWidget';
import { prepareEditorRef } from '../TinyMceWidget/hooks';
import './index.scss';
-export const ExpandableTextArea = ({
+const ExpandableTextArea = ({
value,
setContent,
error,
diff --git a/src/editors/sharedComponents/ExpandableTextArea/index.scss b/src/editors/sharedComponents/ExpandableTextArea/index.scss
index 0a5c5820dc..39659be1f5 100644
--- a/src/editors/sharedComponents/ExpandableTextArea/index.scss
+++ b/src/editors/sharedComponents/ExpandableTextArea/index.scss
@@ -1,25 +1,29 @@
.expandable-mce {
-
.error {
outline: 2px solid #CA3A2F;
}
+
.mce-content-body {
padding: 10px;
+
p {
margin: 0;
}
+
blockquote {
margin: 16px 40px;
}
}
- *[contentEditable=false] {
+ *[contentEditable="false"] {
outline: 1px solid #D7D3D1;
}
- *[contentEditable=true] {
+
+ *[contentEditable="true"] {
outline: 1px solid #707070;
+
&:focus, &:active {
- outline: 2px solid #000;
+ outline: 2px solid #000000;
}
}
}
diff --git a/src/editors/sharedComponents/FileInput/index.jsx b/src/editors/sharedComponents/FileInput/index.jsx
index e926e857e3..f265db4d44 100644
--- a/src/editors/sharedComponents/FileInput/index.jsx
+++ b/src/editors/sharedComponents/FileInput/index.jsx
@@ -40,5 +40,3 @@ FileInput.propTypes = {
]),
}).isRequired,
};
-
-export default FileInput;
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
index 75d4f35f0f..5b06c6f8f2 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.jsx
@@ -16,7 +16,7 @@ import messages from './messages';
* @param {func} setValue - update alt-text value
* @param {string} value - current alt-text value
*/
-export const AltTextControls = ({
+const AltTextControls = ({
isDecorative,
setIsDecorative,
setValue,
@@ -70,4 +70,5 @@ AltTextControls.propTypes = {
intl: intlShape.isRequired,
};
+export const AltTextControlsInternal = AltTextControls; // For testing only
export default injectIntl(AltTextControls);
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.test.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.test.jsx
index 9c2163feff..36780669d5 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.test.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/AltTextControls.test.jsx
@@ -1,8 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../testUtils';
-import { AltTextControls } from './AltTextControls';
+import { formatMessage } from '../../../testUtils';
+import { AltTextControlsInternal as AltTextControls } from './AltTextControls';
jest.mock('./hooks', () => ({
onInputChange: (handler) => ({ 'hooks.onInputChange': handler }),
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
index e6dc0f85b0..c05ec4faeb 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.jsx
@@ -11,7 +11,7 @@ import {
} from '@openedx/paragon/icons';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
-import hooks from './hooks';
+import * as hooks from './hooks';
import messages from './messages';
/**
@@ -24,7 +24,7 @@ import messages from './messages';
* @param {func} updateDimensions - update dimensions callback
* @param {obj} value - local dimension values { height, width }
*/
-export const DimensionControls = ({
+const DimensionControls = ({
isLocked,
lock,
setHeight,
@@ -89,4 +89,5 @@ DimensionControls.propTypes = ({
intl: intlShape.isRequired,
});
+export const DimensionControlsInternal = DimensionControls; // For testing only
export default injectIntl(DimensionControls);
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.test.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.test.jsx
index 9525c8fe54..0cf9a6d279 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.test.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/DimensionControls.test.jsx
@@ -1,3 +1,4 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React, { useEffect } from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import * as paragon from '@openedx/paragon';
@@ -6,12 +7,12 @@ import * as icons from '@openedx/paragon/icons';
import {
fireEvent, render, screen, waitFor,
} from '@testing-library/react';
-import { formatMessage } from '../../../../testUtils';
-import { DimensionControls } from './DimensionControls';
-import hooks from './hooks';
+import { formatMessage } from '../../../testUtils';
+import { DimensionControlsInternal as DimensionControls } from './DimensionControls';
+import * as hooks from './hooks';
const WrappedDimensionControls = () => {
- const dimensions = hooks.dimensions('altText');
+ const dimensions = hooks.dimensionHooks('altText');
useEffect(() => {
dimensions.onImgLoad({ })({ target: { naturalWidth: 1517, naturalHeight: 803 } });
@@ -21,7 +22,7 @@ const WrappedDimensionControls = () => {
};
const UnlockedDimensionControls = () => {
- const dimensions = hooks.dimensions('altText');
+ const dimensions = hooks.dimensionHooks('altText');
useEffect(() => {
dimensions.onImgLoad({ })({ target: { naturalWidth: 1517, naturalHeight: 803 } });
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
index 25ca32e865..c67d63f404 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.js
@@ -1,6 +1,10 @@
import React from 'react';
import { StrictDict } from '../../../utils';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
// Simple wrappers for useState to allow easy mocking for tests.
@@ -334,12 +338,3 @@ export const onSaveClick = ({
});
}
};
-
-export default {
- altText: altTextHooks,
- dimensions: dimensionHooks,
- onCheckboxChange,
- onInputChange,
- onSaveClick,
- checkFormValidation,
-};
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
index 932577cc4c..bcac2ef658 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/hooks.test.js
@@ -1,6 +1,6 @@
import React from 'react';
import { StrictDict } from '../../../utils';
-import { MockUseState } from '../../../../testUtils';
+import { MockUseState } from '../../../testUtils';
import * as hooks from './hooks';
jest.mock('react', () => ({
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
index a4257f1f0f..da0073f514 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.jsx
@@ -6,7 +6,7 @@ import { ArrowBackIos } from '@openedx/paragon/icons';
import { FormattedMessage, injectIntl, intlShape } from '@edx/frontend-platform/i18n';
import './index.scss';
-import hooks from './hooks';
+import * as hooks from './hooks';
import messages from './messages';
import BaseModal from '../../BaseModal';
import AltTextControls from './AltTextControls';
@@ -23,7 +23,7 @@ import ErrorAlert from '../../ErrorAlerts/ErrorAlert';
* @param {func} saveToEditor - save the current settings to the editor
* @param {func} returnToSelection - return to image selection
*/
-export const ImageSettingsModal = ({
+const ImageSettingsModal = ({
close,
isOpen,
returnToSelection,
@@ -32,8 +32,8 @@ export const ImageSettingsModal = ({
// inject
intl,
}) => {
- const altText = hooks.altText(selection.altText);
- const dimensions = hooks.dimensions(altText);
+ const altText = hooks.altTextHooks(selection.altText);
+ const dimensions = hooks.dimensionHooks(altText);
const onSaveClick = hooks.onSaveClick({
altText,
dimensions: dimensions.value,
@@ -102,4 +102,5 @@ ImageSettingsModal.propTypes = {
// inject
intl: intlShape.isRequired,
};
+export const ImageSettingsModalInternal = ImageSettingsModal; // For testing only
export default injectIntl(ImageSettingsModal);
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.scss b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.scss
index 9ccb573a62..d50b5e81d1 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.scss
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.scss
@@ -1,6 +1,7 @@
.img-settings-form-container {
.img-settings-thumbnail-container {
width: 282px;
+
.img-settings-thumbnail {
margin-left: 32px;
max-height: 250px;
@@ -11,17 +12,21 @@
hr {
width: 1px;
}
+
.img-settings-form-controls {
width: 375px;
margin: 0 24px;
+
.dimension-input {
width: 145px;
margin-right: 15px;
display: inline-block;
}
+
.img-settings-control-label {
font-size: 1rem;
}
+
.decorative-control-label label {
font-size: .75rem;
}
diff --git a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.test.jsx b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.test.jsx
index 56a94ebc73..f6d378ccfa 100644
--- a/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.test.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/ImageSettingsModal/index.test.jsx
@@ -1,14 +1,15 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../testUtils';
-import { ImageSettingsModal } from '.';
+import { formatMessage } from '../../../testUtils';
+import { ImageSettingsModalInternal as ImageSettingsModal } from '.';
jest.mock('./AltTextControls', () => 'AltTextControls');
jest.mock('./DimensionControls', () => 'DimensionControls');
jest.mock('./hooks', () => ({
- altText: () => ({
+ altTextHooks: () => ({
error: {
show: true,
dismiss: jest.fn(),
@@ -16,7 +17,7 @@ jest.mock('./hooks', () => ({
isDecorative: false,
value: 'alternative Taxes',
}),
- dimensions: () => ({
+ dimensionHooks: () => ({
onImgLoad: jest.fn(
(selection) => ({ 'hooks.dimensions.onImgLoad.callback': { selection } }),
).mockName('hooks.dimensions.onImgLoad'),
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
index 801f9c0dc3..92a1f513ef 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.js
@@ -2,6 +2,10 @@ import React from 'react';
import { useDispatch } from 'react-redux';
import { thunkActions } from '../../../data/redux';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from './hooks';
import { sortFunctions, sortKeys, sortMessages } from './utils';
import messages from './messages';
@@ -177,7 +181,3 @@ export const imgHooks = ({
selectBtnProps,
};
};
-
-export default {
- imgHooks,
-};
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
index 2f560e994c..4029bd9f0d 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/hooks.test.js
@@ -1,7 +1,7 @@
import React from 'react';
import { dispatch } from 'react-redux';
-import { MockUseState } from '../../../../testUtils';
+import { MockUseState } from '../../../testUtils';
import { keyStore } from '../../../utils';
import { thunkActions } from '../../../data/redux';
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.jsx b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.jsx
index 2624331004..81e4802cb7 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.jsx
@@ -1,13 +1,13 @@
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
-import hooks from './hooks';
+import * as hooks from './hooks';
import { acceptedImgKeys } from './utils';
import SelectionModal from '../../SelectionModal';
import messages from './messages';
import { RequestKeys } from '../../../data/constants/requests';
import { selectors } from '../../../data/redux';
-export const SelectImageModal = ({
+const SelectImageModal = ({
isOpen,
close,
setSelection,
@@ -84,4 +84,5 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
+export const SelectImageModalInternal = SelectImageModal; // For testing only
export default connect(mapStateToProps, mapDispatchToProps)(SelectImageModal);
diff --git a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.test.jsx b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.test.jsx
index 4b52b3afaa..0bd810d280 100644
--- a/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.test.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/SelectImageModal/index.test.jsx
@@ -1,10 +1,10 @@
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../testUtils';
+import { formatMessage } from '../../../testUtils';
import SelectionModal from '../../SelectionModal';
-import hooks from './hooks';
-import { SelectImageModal } from '.';
+import * as hooks from './hooks';
+import { SelectImageModalInternal as SelectImageModal } from '.';
const mockImage = {
displayName: 'DALLĀ·E 2023-03-10.png',
diff --git a/src/editors/sharedComponents/ImageUploadModal/index.jsx b/src/editors/sharedComponents/ImageUploadModal/index.jsx
index 80af029a70..b657265ea5 100644
--- a/src/editors/sharedComponents/ImageUploadModal/index.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/index.jsx
@@ -1,10 +1,15 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import PropTypes from 'prop-types';
import { injectIntl } from '@edx/frontend-platform/i18n';
-import tinyMCEKeys from '../../data/constants/tinyMCE';
+import * as tinyMCEKeys from '../../data/constants/tinyMCE';
import ImageSettingsModal from './ImageSettingsModal';
import SelectImageModal from './SelectImageModal';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from '.';
import { updateImageDimensions } from '../TinyMceWidget/hooks';
@@ -55,6 +60,7 @@ export const updateImagesRef = ({
images: images.current, url: selection.externalUrl, height, width,
});
+ // eslint-disable-next-line no-param-reassign
images.current = imageAlreadyExists ? mappedImages : [...images.current, newImage];
};
@@ -114,7 +120,7 @@ export const hooks = {
propsString,
};
-export const ImageUploadModal = ({
+const ImageUploadModal = ({
// eslint-disable-next-line
editorRef,
isOpen,
@@ -187,4 +193,5 @@ ImageUploadModal.propTypes = {
editorType: PropTypes.string,
};
+export const ImageUploadModalInternal = ImageUploadModal; // For testing only
export default injectIntl(ImageUploadModal);
diff --git a/src/editors/sharedComponents/ImageUploadModal/index.test.jsx b/src/editors/sharedComponents/ImageUploadModal/index.test.jsx
index d0e3f860b3..b9b8fbc2bd 100644
--- a/src/editors/sharedComponents/ImageUploadModal/index.test.jsx
+++ b/src/editors/sharedComponents/ImageUploadModal/index.test.jsx
@@ -3,15 +3,18 @@ import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { keyStore } from '../../utils';
-import tinyMCEKeys from '../../data/constants/tinyMCE';
-
+import * as tinyMCEKeys from '../../data/constants/tinyMCE';
+// This 'module' self-import hack enables mocking during tests.
+// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
+// should be re-thought and cleaned up to avoid this pattern.
+// eslint-disable-next-line import/no-self-import
import * as module from '.';
import * as tinyMceHooks from '../TinyMceWidget/hooks';
jest.mock('./ImageSettingsModal', () => 'ImageSettingsModal');
jest.mock('./SelectImageModal', () => 'SelectImageModal');
-const { ImageUploadModal } = module;
+const { ImageUploadModalInternal: ImageUploadModal } = module;
const hookKeys = keyStore(module.hooks);
const settings = {
diff --git a/src/editors/sharedComponents/RawEditor/index.jsx b/src/editors/sharedComponents/RawEditor/index.jsx
index 1f507f3ab1..d6cccca65c 100644
--- a/src/editors/sharedComponents/RawEditor/index.jsx
+++ b/src/editors/sharedComponents/RawEditor/index.jsx
@@ -11,7 +11,7 @@ function getValue(content) {
return content.data?.data;
}
-export const RawEditor = ({
+const RawEditor = ({
editorRef,
content,
lang,
diff --git a/src/editors/sharedComponents/RawEditor/index.test.jsx b/src/editors/sharedComponents/RawEditor/index.test.jsx
index 848e5070e1..8b68afaf30 100644
--- a/src/editors/sharedComponents/RawEditor/index.test.jsx
+++ b/src/editors/sharedComponents/RawEditor/index.test.jsx
@@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import '@testing-library/jest-dom/extend-expect';
-import { RawEditor } from '.';
+import RawEditor from '.';
jest.unmock('@openedx/paragon');
diff --git a/src/editors/sharedComponents/SelectionModal/Gallery.jsx b/src/editors/sharedComponents/SelectionModal/Gallery.jsx
index 9124ce80d1..1e01a109fb 100644
--- a/src/editors/sharedComponents/SelectionModal/Gallery.jsx
+++ b/src/editors/sharedComponents/SelectionModal/Gallery.jsx
@@ -13,7 +13,7 @@ import messages from './messages';
import GalleryCard from './GalleryCard';
import GalleryLoadMoreButton from './GalleryLoadMoreButton';
-export const Gallery = ({
+const Gallery = ({
galleryIsEmpty,
searchIsEmpty,
displayList,
diff --git a/src/editors/sharedComponents/SelectionModal/Gallery.test.jsx b/src/editors/sharedComponents/SelectionModal/Gallery.test.jsx
index bddbe37768..e4ba05be25 100644
--- a/src/editors/sharedComponents/SelectionModal/Gallery.test.jsx
+++ b/src/editors/sharedComponents/SelectionModal/Gallery.test.jsx
@@ -3,7 +3,7 @@ import { shallow } from '@edx/react-unit-test-utils';
import { IntlProvider } from '@edx/frontend-platform/i18n';
-import { Gallery } from './Gallery';
+import Gallery from './Gallery';
jest.mock('../../data/redux', () => ({
selectors: {
diff --git a/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx b/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
index 6e73c9fb2d..e1864b3991 100644
--- a/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
+++ b/src/editors/sharedComponents/SelectionModal/GalleryCard.jsx
@@ -14,7 +14,7 @@ import messages from './messages';
import { formatDuration } from '../../utils';
import LanguageNamesWidget from '../../containers/VideoEditor/components/VideoSettingsModal/components/VideoPreviewWidget/LanguageNamesWidget';
-export const GalleryCard = ({
+const GalleryCard = ({
asset,
thumbnailFallback,
}) => {
diff --git a/src/editors/sharedComponents/SelectionModal/GalleryCard.test.jsx b/src/editors/sharedComponents/SelectionModal/GalleryCard.test.jsx
index b98ae6eeee..6cd930edf3 100644
--- a/src/editors/sharedComponents/SelectionModal/GalleryCard.test.jsx
+++ b/src/editors/sharedComponents/SelectionModal/GalleryCard.test.jsx
@@ -1,15 +1,9 @@
+import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
import { shallow } from '@edx/react-unit-test-utils';
import { Image } from '@openedx/paragon';
-import { GalleryCard } from './GalleryCard';
-
-jest.mock('@openedx/paragon', () => ({
- ...jest.requireActual('@openedx/paragon'),
- Badge: 'Badge',
- SelectableBox: 'SelectableBox',
- Image: 'Image',
-}));
+import GalleryCard from './GalleryCard';
describe('GalleryCard component', () => {
const asset = {
diff --git a/src/editors/sharedComponents/SelectionModal/SearchSort.jsx b/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
index ac9576faa5..a2470edc57 100644
--- a/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
+++ b/src/editors/sharedComponents/SelectionModal/SearchSort.jsx
@@ -14,7 +14,7 @@ import messages from './messages';
import './index.scss';
import { sortKeys, sortMessages } from '../../containers/VideoGallery/utils';
-export const SearchSort = ({
+const SearchSort = ({
searchString,
onSearchChange,
clearSearchString,
diff --git a/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx b/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
index 17c1d39f2e..8757d74e02 100644
--- a/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
+++ b/src/editors/sharedComponents/SelectionModal/SearchSort.test.jsx
@@ -9,7 +9,7 @@ import { IntlProvider } from '@edx/frontend-platform/i18n';
import {
filterKeys, filterMessages, sortKeys, sortMessages,
} from '../../containers/VideoGallery/utils';
-import { SearchSort } from './SearchSort';
+import SearchSort from './SearchSort';
import messages from './messages';
jest.unmock('react-redux');
diff --git a/src/editors/sharedComponents/SelectionModal/__snapshots__/GalleryCard.test.jsx.snap b/src/editors/sharedComponents/SelectionModal/__snapshots__/GalleryCard.test.jsx.snap
index 0dbc28b4d2..f14a235f3e 100644
--- a/src/editors/sharedComponents/SelectionModal/__snapshots__/GalleryCard.test.jsx.snap
+++ b/src/editors/sharedComponents/SelectionModal/__snapshots__/GalleryCard.test.jsx.snap
@@ -59,12 +59,7 @@ exports[`GalleryCard component snapshot with duration badge 1`] = `