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 31fa88ca6..1a7ea9f03 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.jsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Container,
@@ -19,34 +19,35 @@ const HintRow = ({
images,
isLibrary,
learningContextId,
- // injected
- intl,
-}) => (
-
-
-
-
-
-
-
-
-);
+}) => {
+ const intl = useIntl();
+ return (
+
+
+
+
+
+
+
+
+ );
+};
HintRow.propTypes = {
value: PropTypes.string.isRequired,
@@ -56,9 +57,6 @@ HintRow.propTypes = {
images: PropTypes.shape({}).isRequired,
learningContextId: PropTypes.string.isRequired,
isLibrary: PropTypes.bool.isRequired,
- // injected
- intl: intlShape.isRequired,
};
-export const HintRowInternal = HintRow; // For testing only
-export default injectIntl(HintRow);
+export default 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
deleted file mode 100644
index 89ec54b23..000000000
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.jsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import 'CourseAuthoring/editors/setupEditorTest';
-import React from 'react';
-import { shallow } from '@edx/react-unit-test-utils';
-import { formatMessage } from '../../../../../../testUtils';
-import { HintRowInternal as HintRow } from './HintRow';
-
-describe('HintRow', () => {
- const props = {
- value: 'hint_1',
- handleChange: jest.fn(),
- handleDelete: jest.fn(),
- id: '0',
- intl: { formatMessage },
- images: {},
- isLibrary: false,
- learningContextId: 'course+org+run',
- };
-
- describe('snapshot', () => {
- test('snapshot: renders hints row', () => {
- expect(shallow().snapshot).toMatchSnapshot();
- });
- });
-});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx
new file mode 100644
index 000000000..b16fcfd87
--- /dev/null
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/HintRow.test.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import {
+ render, screen, initializeMocks, fireEvent,
+} from '@src/testUtils';
+import HintRow from './HintRow';
+
+jest.mock('../../../../../../sharedComponents/ExpandableTextArea', () => 'ExpandableTextArea');
+
+describe('HintRow', () => {
+ const props = {
+ value: 'hint_1',
+ handleChange: jest.fn(),
+ handleDelete: jest.fn(),
+ id: '0',
+ images: {},
+ isLibrary: false,
+ learningContextId: 'course+org+run',
+ };
+
+ beforeEach(() => {
+ initializeMocks();
+ });
+
+ test('renders hints row', () => {
+ render();
+ expect(screen.getByPlaceholderText('Hint')).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Delete answer' })).toBeInTheDocument();
+ });
+
+ test('calls handleDelete when button is clicked', () => {
+ render();
+ expect(screen.getByRole('button', { name: 'Delete answer' })).toBeInTheDocument();
+ fireEvent.click(screen.getByRole('button', { name: 'Delete answer' }));
+ expect(props.handleDelete).toHaveBeenCalled();
+ });
+});
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintRow.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintRow.test.jsx.snap
deleted file mode 100644
index b557d1dc1..000000000
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintRow.test.jsx.snap
+++ /dev/null
@@ -1,34 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`HintRow snapshot snapshot: renders hints row 1`] = `
-
-
-
-
-
-
-
-
-`;
diff --git a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintsCard.test.jsx.snap b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintsCard.test.jsx.snap
index 7e7fe0fc0..64eff3fdc 100644
--- a/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintsCard.test.jsx.snap
+++ b/src/editors/containers/ProblemEditor/components/EditProblemView/SettingsWidget/settingsComponents/__snapshots__/HintsCard.test.jsx.snap
@@ -9,14 +9,14 @@ exports[`HintsCard snapshot snapshot: renders hints setting card multiple hints
summary=" {count, plural, =0 {} other {(+# more)}}"
title="Hints"
>
-
-
- {
widgetWithError: [{ err1: 'mSg', err2: 'msG2' }, jest.fn()],
widgetWithNoError: [{}, jest.fn()],
};
+ beforeEach(() => {
+ initializeMocks();
+ });
+
afterEach(() => {
jest.restoreAllMocks();
});
- describe('render', () => {
- beforeEach(() => {
- jest.spyOn(React, 'useContext').mockReturnValueOnce({});
- });
- test('snapshots: renders as expected when there are no errors', () => {
+
+ describe('renders', () => {
+ jest.spyOn(React, 'useContext').mockReturnValueOnce({});
+ test('renders as expected when there are no errors', () => {
jest.spyOn(mod, 'showAlert').mockReturnValue(false);
- expect(shallow().snapshot).toMatchSnapshot();
+ render();
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
});
+
test('snapshots: renders as expected when there are errors', () => {
jest.spyOn(mod, 'showAlert').mockReturnValue(true);
- expect(shallow().snapshot).toMatchSnapshot();
+ render();
+ expect(screen.getByRole('alert')).toBeInTheDocument();
});
});
+
describe('hasNoError', () => {
it('returns true', () => {
expect(mod.hasNoError(errors.widgetWithError)).toEqual(false);
@@ -35,6 +43,7 @@ describe('ErrorSummary', () => {
expect(mod.hasNoError(errors.widgetWithNoError)).toEqual(true);
});
});
+
describe('showAlert', () => {
it('returns true', () => {
jest.spyOn(mod, 'hasNoError').mockReturnValue(false);
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/__snapshots__/ErrorSummary.test.tsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/__snapshots__/ErrorSummary.test.tsx.snap
deleted file mode 100644
index 88baf91bd..000000000
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/__snapshots__/ErrorSummary.test.tsx.snap
+++ /dev/null
@@ -1,45 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`ErrorSummary render snapshots: renders as expected when there are errors 1`] = `
-
-
-
-
-
-
-
-
-`;
-
-exports[`ErrorSummary render snapshots: renders as expected when there are no errors 1`] = `
-
-
-
-
-
-
-
-
-`;
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 90d3ec235..ad441c562 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/LanguageSelector.jsx
@@ -10,16 +10,11 @@ import {
import { Check } from '@openedx/paragon/icons';
import { connect, useDispatch } from 'react-redux';
-import { injectIntl, intlShape } from '@edx/frontend-platform/i18n';
+import { useIntl } from '@edx/frontend-platform/i18n';
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 = {
onSelectLanguage: ({
@@ -54,13 +49,11 @@ const LanguageSelector = ({
language,
// Redux
openLanguages, // Only allow those languages not already associated with a transcript to be selected
- // intl
- intl,
-
}) => {
+ const intl = useIntl();
const [localLang, setLocalLang] = React.useState(language);
const input = fileInput({ onAddFile: hooks.addFileCallback({ dispatch: useDispatch(), localLang }) });
- const onLanguageChange = module.hooks.onSelectLanguage({
+ const onLanguageChange = hooks.onSelectLanguage({
dispatch: useDispatch(), languageBeforeChange: localLang, setLocalLang, triggerupload: input.click,
});
@@ -124,7 +117,6 @@ LanguageSelector.propTypes = {
openLanguages: PropTypes.arrayOf(PropTypes.string),
index: PropTypes.number.isRequired,
language: PropTypes.string.isRequired,
- intl: intlShape.isRequired,
};
export const mapStateToProps = (state) => ({
@@ -134,4 +126,4 @@ export const mapStateToProps = (state) => ({
export const mapDispatchToProps = {};
export const LanguageSelectorInternal = LanguageSelector; // For testing only
-export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(LanguageSelector));
+export default 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 0eae896c6..3fc95017b 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,8 +1,9 @@
-import 'CourseAuthoring/editors/setupEditorTest';
import React from 'react';
-import { shallow } from '@edx/react-unit-test-utils';
-import { LanguageSelectorInternal as LanguageSelector } from './LanguageSelector';
-import { formatMessage } from '../../../../../../testUtils';
+import {
+ render, screen, initializeMocks, fireEvent,
+} from '@src/testUtils';
+import LanguageSelector from './LanguageSelector';
+import { selectors } from '../../../../../../data/redux';
const lang1 = 'kLinGon';
const lang1Code = 'kl';
@@ -21,25 +22,37 @@ jest.mock('../../../../../../data/constants/video', () => ({
describe('LanguageSelector', () => {
const props = {
- intl: { formatMessage },
onSelect: jest.fn().mockName('props.OnSelect'),
- title: 'tITle',
+ index: 1,
language: lang1Code,
openLanguages: [[lang2Code, lang2], [lang3Code, lang3]],
-
};
- describe('snapshot', () => {
- test('transcript option', () => {
- expect(
- shallow().snapshot,
- ).toMatchSnapshot();
- });
+ beforeEach(() => {
+ initializeMocks();
});
- describe('snapshots -- no', () => {
- test('transcripts no Open Languages, all should be disabled', () => {
- expect(
- shallow().snapshot,
- ).toMatchSnapshot();
- });
+
+ test('renders component with selected language', () => {
+ const { video } = selectors;
+ jest.spyOn(video, 'openLanguages').mockReturnValue(props.openLanguages);
+ const { container } = render();
+ expect(screen.getByRole('button', { name: 'Languages' })).toBeInTheDocument();
+ expect(screen.getByText(lang1)).toBeInTheDocument();
+ expect(container.querySelector('input.upload[type="file"]')).toBeInTheDocument();
+ });
+
+ test('renders component with no selection', () => {
+ const { video } = selectors;
+ jest.spyOn(video, 'openLanguages').mockReturnValue(props.openLanguages);
+ render();
+ expect(screen.getByText('Select Language')).toBeInTheDocument();
+ });
+
+ test('transcripts no Open Languages, all dropdown items should be disabled', () => {
+ const { video } = selectors;
+ jest.spyOn(video, 'openLanguages').mockReturnValue([]);
+ const { container } = render();
+ fireEvent.click(screen.getByRole('button', { name: 'Languages' }));
+ const disabledItems = container.querySelectorAll('.disabled.dropdown-item');
+ expect(disabledItems.length).toBe(3);
});
});
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/LanguageSelector.test.jsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/LanguageSelector.test.jsx.snap
deleted file mode 100644
index 281e71184..000000000
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/LanguageSelector.test.jsx.snap
+++ /dev/null
@@ -1,111 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`LanguageSelector snapshot transcript option 1`] = `
-
-
-
-
- kLinGon
-
-
-
-
-
-
- kLinGon
-
-
-
- eLvIsh
-
-
- sImLisH
-
-
-
-
-
-`;
-
-exports[`LanguageSelector snapshots -- no transcripts no Open Languages, all should be disabled 1`] = `
-
-
-
-
- kLinGon
-
-
-
-
-
-
- kLinGon
-
-
-
- eLvIsh
-
-
- sImLisH
-
-
-
-
-
-`;
diff --git a/src/editors/sharedComponents/BaseModal/__snapshots__/index.test.jsx.snap b/src/editors/sharedComponents/BaseModal/__snapshots__/index.test.jsx.snap
deleted file mode 100644
index f76ae5cea..000000000
--- a/src/editors/sharedComponents/BaseModal/__snapshots__/index.test.jsx.snap
+++ /dev/null
@@ -1,53 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`BaseModal ImageUploadModal template component snapshot 1`] = `
-
-
-
- props.title node
-
-
-
-
- props.children node
-
-
-
-
-
- props.footerAction node
-
-
-
-
-
- props.confirmAction node
-
-
-
-`;
diff --git a/src/editors/sharedComponents/BaseModal/index.test.jsx b/src/editors/sharedComponents/BaseModal/index.test.jsx
deleted file mode 100644
index cca9a4b57..000000000
--- a/src/editors/sharedComponents/BaseModal/index.test.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import 'CourseAuthoring/editors/setupEditorTest';
-import React from 'react';
-import { shallow } from '@edx/react-unit-test-utils';
-
-import BaseModal from '.';
-
-describe('BaseModal ImageUploadModal template component', () => {
- test('snapshot', () => {
- const props = {
- isOpen: true,
- close: jest.fn().mockName('props.close'),
- title: 'props.title node',
- children: 'props.children node',
- confirmAction: 'props.confirmAction node',
- footerAction: 'props.footerAction node',
- };
- expect(shallow().snapshot).toMatchSnapshot();
- });
-});
diff --git a/src/editors/sharedComponents/BaseModal/index.test.tsx b/src/editors/sharedComponents/BaseModal/index.test.tsx
new file mode 100644
index 000000000..6d3fb5d0b
--- /dev/null
+++ b/src/editors/sharedComponents/BaseModal/index.test.tsx
@@ -0,0 +1,41 @@
+import React from 'react';
+import { render, screen, initializeMocks } from '@src/testUtils';
+
+import BaseModal from '.';
+
+const props = {
+ isOpen: true,
+ close: jest.fn().mockName('props.close'),
+ title: 'title node',
+ children: 'children node',
+ confirmAction: 'confirmAction node',
+ footerAction: 'footerAction node',
+};
+
+describe('BaseModal', () => {
+ beforeEach(() => {
+ initializeMocks();
+ });
+
+ test('renders component with all elements', () => {
+ render();
+ expect(screen.getByText(props.title)).toBeInTheDocument();
+ expect(screen.getByText(props.children)).toBeInTheDocument();
+ const confirmAction = screen.getByText((content) => content.includes(props.confirmAction));
+ expect(confirmAction).toBeInTheDocument();
+ const footerAction = screen.getByText((content) => content.includes(props.footerAction));
+ expect(footerAction).toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Cancel' })).toBeInTheDocument();
+ });
+
+ test('does not render cancel buton when hideCancelButton is true', () => {
+ render();
+ expect(screen.queryByRole('button', { name: 'Cancel' })).not.toBeInTheDocument();
+ });
+
+ test('does not render footerAction node when not provided', () => {
+ render();
+ const footerAction = screen.queryByText((content) => content.includes(props.footerAction));
+ expect(footerAction).not.toBeInTheDocument();
+ });
+});
diff --git a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx
deleted file mode 100644
index 09c8a7df5..000000000
--- a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.jsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'CourseAuthoring/editors/setupEditorTest';
-import React from 'react';
-import { shallow } from '@edx/react-unit-test-utils';
-import UploadErrorAlert from './UploadErrorAlert';
-
-jest.mock('../../data/redux', () => ({
- selectors: {
- requests: {
- isFailed: jest.fn((state, params) => ({ isFailed: { state, params } })),
- },
- },
-}));
-
-describe('UploadErrorAlert', () => {
- describe('Snapshots', () => {
- test('snapshot: is ErrorAlert with Message error (ErrorAlert)', () => {
- expect(shallow().snapshot).toMatchSnapshot();
- });
- });
-});
diff --git a/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.tsx b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.tsx
new file mode 100644
index 000000000..9671239a0
--- /dev/null
+++ b/src/editors/sharedComponents/ErrorAlerts/UploadErrorAlert.test.tsx
@@ -0,0 +1,32 @@
+import React from 'react';
+import { render, screen, initializeMocks } from '@src/testUtils';
+import UploadErrorAlert from './UploadErrorAlert';
+
+const errorMessage = {
+ id: 'error.errorTitle',
+ defaultMessage: 'Example error message',
+ description: 'Title of message presented to user when something goes wrong',
+};
+
+const defaultProps = {
+ isUploadError: true,
+ message: errorMessage,
+};
+
+describe('UploadErrorAlert', () => {
+ beforeEach(() => {
+ initializeMocks();
+ });
+
+ test('renders the error message', () => {
+ render();
+ expect(screen.queryByRole('alert')).toBeInTheDocument();
+ expect(screen.getByText(errorMessage.defaultMessage)).toBeInTheDocument();
+ });
+
+ test('does not render the error message when isUploadError is false', () => {
+ render();
+ expect(screen.queryByRole('alert')).not.toBeInTheDocument();
+ expect(screen.queryByText(errorMessage.defaultMessage)).not.toBeInTheDocument();
+ });
+});
diff --git a/src/editors/sharedComponents/ErrorAlerts/__snapshots__/UploadErrorAlert.test.jsx.snap b/src/editors/sharedComponents/ErrorAlerts/__snapshots__/UploadErrorAlert.test.jsx.snap
deleted file mode 100644
index 68f5d8b3d..000000000
--- a/src/editors/sharedComponents/ErrorAlerts/__snapshots__/UploadErrorAlert.test.jsx.snap
+++ /dev/null
@@ -1,11 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`UploadErrorAlert Snapshots snapshot: is ErrorAlert with Message error (ErrorAlert) 1`] = `
-
-
-
-`;