Skip to content

Commit 95521d3

Browse files
Cleanups for the video editor [FC-0062] (#1318)
* refactor: cleanups to video editor code * test: ignore coverage of blank default data
1 parent 64d718d commit 95521d3

File tree

12 files changed

+106
-189
lines changed

12 files changed

+106
-189
lines changed

src/editors/containers/VideoEditor/__snapshots__/index.test.jsx.snap

Lines changed: 0 additions & 50 deletions
This file was deleted.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`VideoEditor snapshots renders as expected with default behavior 1`] = `
4+
<ErrorContext.Provider
5+
value="hooks.errorsHook.error"
6+
>
7+
<EditorContainer
8+
onClose={[MockFunction props.onClose]}
9+
validateEntry={[MockFunction validateEntry]}
10+
>
11+
<div
12+
className="video-editor"
13+
>
14+
<VideoEditorModal
15+
isLibrary={
16+
{
17+
"useSelector": [MockFunction],
18+
}
19+
}
20+
/>
21+
</div>
22+
</EditorContainer>
23+
</ErrorContext.Provider>
24+
`;
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import React from 'react';
22
import { useDispatch, useSelector } from 'react-redux';
3-
import PropTypes from 'prop-types';
43
import * as appHooks from '../../../hooks';
54
import { thunkActions, selectors } from '../../../data/redux';
65
import VideoSettingsModal from './VideoSettingsModal';
7-
// import SelectVideoModal from './SelectVideoModal';
6+
7+
interface Props {
8+
isLibrary: boolean;
9+
}
810

911
export const {
1012
navigateTo,
@@ -21,9 +23,7 @@ export const hooks = {
2123
},
2224
};
2325

24-
const VideoEditorModal = ({
25-
close,
26-
isOpen,
26+
const VideoEditorModal: React.FC<Props> = ({
2727
isLibrary,
2828
}) => {
2929
const dispatch = useDispatch();
@@ -34,8 +34,6 @@ const VideoEditorModal = ({
3434
hooks.initialize(dispatch, selectedVideoId, selectedVideoUrl);
3535
return (
3636
<VideoSettingsModal {...{
37-
close,
38-
isOpen,
3937
onReturn,
4038
isLibrary,
4139
}}
@@ -44,11 +42,4 @@ const VideoEditorModal = ({
4442
// TODO: add logic to show SelectVideoModal if no selection
4543
};
4644

47-
VideoEditorModal.defaultProps = {
48-
};
49-
VideoEditorModal.propTypes = {
50-
close: PropTypes.func.isRequired,
51-
isOpen: PropTypes.bool.isRequired,
52-
isLibrary: PropTypes.bool.isRequired,
53-
};
5445
export default VideoEditorModal;

src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.jsx renamed to src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.test.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import 'CourseAuthoring/editors/setupEditorTest';
22
import React from 'react';
33
import { shallow } from '@edx/react-unit-test-utils';
44

5-
import * as module from './ErrorSummary';
5+
import * as mod from './ErrorSummary';
66

7-
const { ErrorSummary } = module;
7+
const { ErrorSummary } = mod;
88

99
describe('ErrorSummary', () => {
1010
const errors = {
@@ -19,30 +19,30 @@ describe('ErrorSummary', () => {
1919
jest.spyOn(React, 'useContext').mockReturnValueOnce({});
2020
});
2121
test('snapshots: renders as expected when there are no errors', () => {
22-
jest.spyOn(module, 'showAlert').mockReturnValue(false);
22+
jest.spyOn(mod, 'showAlert').mockReturnValue(false);
2323
expect(shallow(<ErrorSummary />).snapshot).toMatchSnapshot();
2424
});
2525
test('snapshots: renders as expected when there are errors', () => {
26-
jest.spyOn(module, 'showAlert').mockReturnValue(true);
26+
jest.spyOn(mod, 'showAlert').mockReturnValue(true);
2727
expect(shallow(<ErrorSummary />).snapshot).toMatchSnapshot();
2828
});
2929
});
3030
describe('hasNoError', () => {
3131
it('returns true', () => {
32-
expect(module.hasNoError(errors.widgetWithError)).toEqual(false);
32+
expect(mod.hasNoError(errors.widgetWithError)).toEqual(false);
3333
});
3434
it('returns false', () => {
35-
expect(module.hasNoError(errors.widgetWithNoError)).toEqual(true);
35+
expect(mod.hasNoError(errors.widgetWithNoError)).toEqual(true);
3636
});
3737
});
3838
describe('showAlert', () => {
3939
it('returns true', () => {
40-
jest.spyOn(module, 'hasNoError').mockReturnValue(false);
41-
expect(module.showAlert(errors)).toEqual(true);
40+
jest.spyOn(mod, 'hasNoError').mockReturnValue(false);
41+
expect(mod.showAlert(errors)).toEqual(true);
4242
});
4343
it('returns false', () => {
44-
jest.spyOn(module, 'hasNoError').mockReturnValue(true);
45-
expect(module.showAlert(errors)).toEqual(false);
44+
jest.spyOn(mod, 'hasNoError').mockReturnValue(true);
45+
expect(mod.showAlert(errors)).toEqual(false);
4646
});
4747
});
4848
});

src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.jsx renamed to src/editors/containers/VideoEditor/components/VideoSettingsModal/ErrorSummary.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,17 @@ import { InfoOutline } from '@openedx/paragon/icons';
66

77
import messages from './components/messages';
88
import { ErrorContext } from '../../hooks';
9-
// This 'module' self-import hack enables mocking during tests.
10-
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
11-
// should be re-thought and cleaned up to avoid this pattern.
12-
// eslint-disable-next-line import/no-self-import
13-
import * as module from './ErrorSummary';
149

1510
export const hasNoError = (error) => Object.keys(error[0]).length === 0;
1611

17-
export const showAlert = (errors) => !Object.values(errors).every(module.hasNoError);
12+
export const showAlert = (errors) => !Object.values(errors).every(hasNoError);
1813

1914
export const ErrorSummary = () => {
2015
const errors = React.useContext(ErrorContext);
2116
return (
2217
<Alert
2318
icon={InfoOutline}
24-
show={module.showAlert(errors)}
19+
show={showAlert(errors)}
2520
variant="danger"
2621
>
2722
<Alert.Heading>

src/editors/containers/VideoEditor/components/VideoSettingsModal/index.jsx renamed to src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
import React from 'react';
2-
import PropTypes from 'prop-types';
32
import { Button, Icon } from '@openedx/paragon';
43
import { ArrowBackIos } from '@openedx/paragon/icons';
5-
import {
6-
FormattedMessage,
7-
injectIntl,
8-
} from '@edx/frontend-platform/i18n';
4+
import { FormattedMessage } from '@edx/frontend-platform/i18n';
95

106
// import VideoPreview from './components/VideoPreview';
117
import { ErrorSummary } from './ErrorSummary';
@@ -20,7 +16,12 @@ import './index.scss';
2016
import SocialShareWidget from './components/SocialShareWidget';
2117
import messages from '../../messages';
2218

23-
const VideoSettingsModal = ({
19+
interface Props {
20+
onReturn: () => void;
21+
isLibrary: boolean;
22+
}
23+
24+
const VideoSettingsModal: React.FC<Props> = ({
2425
onReturn,
2526
isLibrary,
2627
}) => (
@@ -54,9 +55,4 @@ const VideoSettingsModal = ({
5455
</>
5556
);
5657

57-
VideoSettingsModal.propTypes = {
58-
onReturn: PropTypes.func.isRequired,
59-
isLibrary: PropTypes.func.isRequired,
60-
};
61-
62-
export default injectIntl(VideoSettingsModal);
58+
export default VideoSettingsModal;
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
import { dispatch } from 'react-redux';
21
import { thunkActions } from '../../data/redux';
32
import { MockUseState } from '../../testUtils';
43

5-
// This 'module' self-import hack enables mocking during tests.
6-
// See src/editors/decisions/0005-internal-editor-testability-decisions.md. The whole approach to how hooks are tested
7-
// should be re-thought and cleaned up to avoid this pattern.
8-
// eslint-disable-next-line import/no-self-import
9-
import * as module from './hooks';
4+
import * as hooks from './hooks';
105

116
jest.mock('react', () => ({
127
...jest.requireActual('react'),
@@ -15,14 +10,12 @@ jest.mock('react', () => ({
1510
useCallback: (cb, prereqs) => ({ cb, prereqs }),
1611
}));
1712

18-
jest.mock('react-redux', () => {
19-
const dispatchFn = jest.fn();
20-
return {
21-
...jest.requireActual('react-redux'),
22-
dispatch: dispatchFn,
23-
useDispatch: jest.fn(() => dispatchFn),
24-
};
25-
});
13+
const mockDispatchFn = jest.fn();
14+
jest.mock('react-redux', () => ({
15+
...jest.requireActual('react-redux'),
16+
dispatch: mockDispatchFn,
17+
useDispatch: jest.fn(() => mockDispatchFn),
18+
}));
2619

2720
jest.mock('../../data/redux', () => ({
2821
thunkActions: {
@@ -32,7 +25,7 @@ jest.mock('../../data/redux', () => ({
3225
},
3326
}));
3427

35-
const state = new MockUseState(module);
28+
const state = new MockUseState(hooks);
3629

3730
let hook;
3831

@@ -62,47 +55,47 @@ describe('VideoEditorHooks', () => {
6255
field2: 'field2msg',
6356
};
6457
test('error: state values', () => {
65-
expect(module.errorsHook().error.duration).toEqual([
58+
expect(hooks.errorsHook().error.duration).toEqual([
6659
state.stateVals[state.keys.durationErrors],
6760
state.setState[state.keys.durationErrors],
6861
]);
69-
expect(module.errorsHook().error.handout).toEqual([
62+
expect(hooks.errorsHook().error.handout).toEqual([
7063
state.stateVals[state.keys.handoutErrors],
7164
state.setState[state.keys.handoutErrors],
7265
]);
73-
expect(module.errorsHook().error.license).toEqual([
66+
expect(hooks.errorsHook().error.license).toEqual([
7467
state.stateVals[state.keys.licenseErrors],
7568
state.setState[state.keys.licenseErrors],
7669
]);
77-
expect(module.errorsHook().error.thumbnail).toEqual([
70+
expect(hooks.errorsHook().error.thumbnail).toEqual([
7871
state.stateVals[state.keys.thumbnailErrors],
7972
state.setState[state.keys.thumbnailErrors],
8073
]);
81-
expect(module.errorsHook().error.transcripts).toEqual([
74+
expect(hooks.errorsHook().error.transcripts).toEqual([
8275
state.stateVals[state.keys.transcriptsErrors],
8376
state.setState[state.keys.transcriptsErrors],
8477
]);
85-
expect(module.errorsHook().error.videoSource).toEqual([
78+
expect(hooks.errorsHook().error.videoSource).toEqual([
8679
state.stateVals[state.keys.videoSourceErrors],
8780
state.setState[state.keys.videoSourceErrors],
8881
]);
8982
});
9083
describe('validateEntry', () => {
9184
test('validateEntry: returns true if all validation calls are true', () => {
92-
hook = module.errorsHook();
85+
hook = hooks.errorsHook();
9386
expect(hook.validateEntry()).toEqual(true);
9487
});
9588
test('validateEntry: returns false if any validation calls are false', () => {
9689
state.mockVal(state.keys.durationErrors, fakeDurationError);
97-
hook = module.errorsHook();
90+
hook = hooks.errorsHook();
9891
expect(hook.validateEntry()).toEqual(false);
9992
});
10093
});
10194
});
10295
describe('fetchVideoContent', () => {
10396
it('equals dispatch(thunkActions.video.saveVideoData())', () => {
104-
hook = module.fetchVideoContent()({ dispatch });
105-
expect(hook).toEqual(dispatch(thunkActions.video.saveVideoData()));
97+
hook = hooks.fetchVideoContent()({ dispatch: mockDispatchFn });
98+
expect(hook).toEqual(mockDispatchFn(thunkActions.video.saveVideoData()));
10699
});
107100
});
108101
});

0 commit comments

Comments
 (0)