,
+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 5d16dbf71..f5392abf8 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 0f540c74e..e89b39b82 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 18ead54a0..044c773f2 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 d2f09629b..fa19e6068 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 c9e821daf..34ca5ba63 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 bee812eff..a6186050a 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 2b717d411..60de6e1cc 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 1025e1ad3..186bc9d78 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 a427eb1e6..4711b76cf 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 aa55253f8..f3d0e60ae 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 e6c223bef..c742c7a60 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 000000000..f504cf063
--- /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 4376ab38d..20c2f2d56 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 97f3f72df..aaa78980a 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 bf2ca571d..32d64e52c 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 65619c46c..99361275a 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 bacd05f25..fe51bcd33 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 929000c2b..66c170585 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 d47c19554..0d202841d 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 62ac756a3..d64801c07 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 7bc686955..869828202 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 1e63ce80c..8e3f017bc 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 0672d5b27..6366e1c75 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 caae0263d..72b8a0e20 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 c2e4d4649..e73534f5b 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 f568257a6..5c80cbce7 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 c0068955a..5360fdb7d 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 b6e0f9ad7..e14c3bad0 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 bac86c98a..8ac30a31c 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 862b3b214..7ef58f6d9 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 2b1efbe96..1a5d547cb 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 1445c0cdd..c52933af2 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 46653ced1..1f99057ac 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 13a850af0..7fb51bf49 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 0d7b423f6..b1e9585cf 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 6aa791c6a..9614e635f 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 4e3045262..c7e865212 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 86298d5d9..16bdbab9a 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 6e22712c2..062330c19 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 5580975bf..a0ecde82a 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 6602eb1ae..c867da970 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 2c5bc6960..a11f9ea27 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 d04d94bec..929bedb24 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 e7c3074e7..5c9c1a17e 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 a76fef422..1fb8fa6a8 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 8b636c0a8..2576025a9 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 32be62ce1..6c858b736 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 ec4cee441..ad6d2705a 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 9a95851a5..a432a5730 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 cd4f8a77b..c168392b3 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 d866353bb..5d5c98d52 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 af5befed9..f24152c64 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 9d1ebff4c..53e232cbc 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 ea29dd2f4..93be2e266 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 71956ee54..4dbe89c00 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 91728e55a..14adde6d3 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 3fe4a7ff4..531be7bad 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 b3c7c1d67..2c5219524 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 7f8e8b733..55817d51a 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 e0d22b587..3d7673ec9 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 de29ba8ff..cdb399d91 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 e1c3e8998..3105445b6 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 28c5e8fef..888488895 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 cd202f555..dc4cf2cb1 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 8dac761f5..d3438f619 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 ef132a253..1413f092e 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 5802d6d11..d3c46314f 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 60dc03447..d7710313c 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 e95fcbce7..29d8e922c 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 0d06ab63b..eb2690194 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 ae1c850e1..dae004510 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 2828b037c..90454579e 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 9f16c8a8d..b9d59f27f 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 28e159b8c..33032b529 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 46de822d5..614a73639 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 cdb57f651..150a2f39b 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 d0ba299ee..d429128cc 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 aa6808196..75137b505 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 f64fa1b30..bd914dec9 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 cad93083a..ec8bc78ec 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 a34c14df0..3902fd965 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 6a11b3f71..642e14995 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 fe3a4d7b0..11f38473b 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 e05a4ae4b..64d922906 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 95d58efef..1c14750eb 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 6a40796ce..a55d025ba 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 677dc4988..733f87a1a 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 2a9e14236..c00cd02d4 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 8f05c8332..f747783f5 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 3bdd2088e..ec2e3a51a 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 6dda14eaa..d60061ddd 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 f385f1b6f..978b35e7c 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 bca710bd2..7077c18a5 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 6db9965d4..36cf961fc 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 8fcf860a2..e58d731af 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 e6463db98..7482f843e 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 ef70a3613..d25c028aa 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 2970c87b3..e0582b5fb 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 e39100edb..828dc4be0 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 8347aff4e..4574c1b79 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 0a3d0ff6a..e9a12348f 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 f320cdd82..673763de6 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 88fcb7f98..49ddac532 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 5836e2827..1c9047067 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 4a0502f33..281522896 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 fcb05d194..5f342ad1e 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 6c171b22a..f6866b56a 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 0580139fa..bac63ab33 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 c349a593e..830f3b510 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 17e813ac0..ac337f68f 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 ade441c32..07167d65c 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 08ea2acc6..a7acc05a4 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 e644eac85..7a34297ae 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 34117ea67..954519542 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 91b9523cf..6cbd4d5b4 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 c3fd932be..ba84d31df 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 e2b692717..5975edf7a 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 f086f2551..405343107 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 ec14fff5a..5861715c4 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 a733ff570..aead6fb96 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 35e8f41b7..799c06a0c 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 cad8e7e16..8ecb7e613 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 1775df8db..236d49631 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 7ae07a001..f55458d85 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 cba3e3b3a..45937efea 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 23a54c3fb..48e4abdc3 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 435d9fd42..a7799eb74 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 21db0c559..111169499 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 30fc329d8..7e468982b 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 7dffedf42..2b6ee9a0e 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 b062d7fb8..046cc017d 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 823e65166..e7f1836fc 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 3b104e33b..5c382f9bb 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 f1d6db98c..4b357af3b 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 987b73f83..a70d8ea83 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 862511642..57b6e25ac 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 4335ab798..2d7fccd76 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 8da5281e0..17ee79792 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 1ece21af0..6277ac4bd 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 ed4b65241..d59b541fa 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 a0bfa4190..72226c50c 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 66309718c..0b761701c 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 bbd3d361b..21983b45f 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 977c7571b..1a55bc98c 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 8c94d10fb..90d3ec235 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 f45665f35..0eae896c6 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 85c1828a3..6300fee19 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 6216caefb..ed16d2f53 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 553e7f570..46f51180b 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 a22eda8a8..b23f5040e 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 d2a56e723..b734b31ff 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 74353290c..7e0c54eff 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 bbe8dd83a..2647d07c8 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 47aa9911b..0c4a0f089 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 7bc8d6ad7..096f98010 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 9726266fa..85045f081 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 a88f9a3fc..c472e6512 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 a51ffd377..d0b8503e2 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 c5acb0c64..ebfa49372 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 138ba0ab3..5f01ec92c 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 28185d48c..119b04dfb 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 392f47d9b..c04688887 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 5ee665210..32a8df46d 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 6bd023645..633e51f9f 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 fd59b97eb..99c1f157a 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 d52a1cf31..648db7a64 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 8973a0952..5f5a8a8ca 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 3abae625e..79771c90d 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 c0c582c35..e26dd63db 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 e0f3f3847..a2774d9c6 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 8aabeb543..ae2be7b5f 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 2c0565c6c..4e27f44d1 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 032f0b072..e3d5eb6ad 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 227d02c08..f24c59263 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 b77a166ae..72aaa62c6 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 6ebaa1565..34e6f6e55 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 8ee6c867a..442b0cc3d 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 1b201956d..1fef2fa7d 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 4988b43e2..e66e0d1f0 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 dfaae48a0..5b7a915c9 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 08daf32d0..ea0e37036 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 f7edbe273..a6e40203a 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 c9d23c2e0..9976eee19 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 6cba1a7c3..736d49f93 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 05811bbf2..84e5648bd 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 c61dfb240..42e1f7c57 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 efd327ee4..1ba3c3ea0 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 d66cf1384..c9b318bcb 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 a248279d2..fa50c91a0 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 ec9542fd7..b787e23cf 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 16bebedf6..62de4f44a 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 da1f0ad47..828547b5b 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 f419c9a4b..46f9d1a03 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 8a54b6817..352d98973 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 6e53c87d9..75a668d0b 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 77a740ca1..f71c014cf 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 38abad715..7d732c15d 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 116efbf62..7abec953c 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 5c4440b3e..ca50e0c0a 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 4e73ca33a..a10b1ba28 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 0a221d679..6b8c851d9 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 f0c65a6e4..98d238f68 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 d2488ad75..c0d1b70a8 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 000000000..54b23ca0a
--- /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 dd1bef748..74639dd54 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 1afd1662c..cca9a4b57 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 eeeacafd3..29a4ed2da 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 d0827754c..0760f8e0d 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 9b5bdadc6..3e3ef935a 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 f8d8f7b3c..a8b1f0504 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 d098c7678..e8a816717 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 c7f365b5a..2a849ba41 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 9119c4627..334851563 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 d3afb4b7a..09c8a7df5 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 d09a6a5cb..e00552b1a 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 4c7d6e085..139f6c98e 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 cf9025c5f..a2f30d66d 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 0a5c5820d..39659be1f 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 e926e857e..f265db4d4 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 75d4f35f0..5b06c6f8f 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 9c2163fef..36780669d 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 e6dc0f85b..c05ec4fae 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 9525c8fe5..0cf9a6d27 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 25ca32e86..c67d63f40 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 932577cc4..bcac2ef65 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 a4257f1f0..da0073f51 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 9ccb573a6..d50b5e81d 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 56a94ebc7..f6d378ccf 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 801f9c0dc..92a1f513e 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 2f560e994..4029bd9f0 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 262433100..81e4802cb 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 4b52b3afa..0bd810d28 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 80af029a7..b657265ea 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 d0e3f860b..b9b8fbc2b 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 1f507f3ab..d6cccca65 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 848e5070e..8b68afaf3 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 9124ce80d..1e01a109f 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 bddbe3776..e4ba05be2 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 6e73c9fb2..e1864b399 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 b98ae6eee..6cd930edf 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 ac9576faa..a2470edc5 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 17c1d39f2..8757d74e0 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 0dbc28b4d..f14a235f3 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`] = `