From 7a356175e7c0af6b37669b9e2c1c7dd0bac2ea6c Mon Sep 17 00:00:00 2001
From: Kristin Aoki <42981026+KristinAoki@users.noreply.github.com>
Date: Tue, 29 Nov 2022 15:23:14 -0500
Subject: [PATCH] feat: update onBlur to set state to default values (#148)
---
.../__snapshots__/index.test.jsx.snap | 165 +++++++-----------
.../components/TranscriptWidget/index.jsx | 30 ++--
.../__snapshots__/index.test.jsx.snap | 62 +++----
.../components/VideoSourceWidget/hooks.js | 25 ---
.../components/VideoSourceWidget/hooks.jsx | 66 +++++++
.../VideoSourceWidget/hooks.test.jsx | 100 +++++++++++
.../components/VideoSourceWidget/index.jsx | 59 +++----
7 files changed, 286 insertions(+), 221 deletions(-)
delete mode 100644 src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.js
create mode 100644 src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.jsx
create mode 100644 src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/index.test.jsx.snap b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/index.test.jsx.snap
index 42bfab5c7..69c8f379e 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/index.test.jsx.snap
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/TranscriptWidget/__snapshots__/index.test.jsx.snap
@@ -38,12 +38,12 @@ exports[`TranscriptWidget component snapshots snapshot: renders ErrorAlert with
index={0}
language="en"
/>
-
@@ -54,24 +54,15 @@ exports[`TranscriptWidget component snapshots snapshot: renders ErrorAlert with
/>
-
-
-
- }
- placement="right"
- >
-
-
-
+
+
+
-
@@ -165,24 +156,15 @@ exports[`TranscriptWidget component snapshots snapshot: renders ErrorAlert with
/>
-
-
-
- }
- placement="right"
- >
-
-
-
+
+
+
-
@@ -272,24 +254,15 @@ exports[`TranscriptWidget component snapshots snapshots: renders as expected wit
/>
-
-
-
- }
- placement="right"
- >
-
-
-
+
+
+
-
@@ -443,24 +416,15 @@ exports[`TranscriptWidget component snapshots snapshots: renders as expected wit
/>
-
-
-
- }
- placement="right"
- >
-
-
-
+
+
+
-
@@ -550,24 +514,15 @@ exports[`TranscriptWidget component snapshots snapshots: renders as expected wit
/>
-
-
-
- }
- placement="right"
- >
-
-
-
+
+
+
))}
-
+
updateField({ allowTranscriptDownloads: e.target.checked })}
>
-
-
-
- )}
- >
-
-
-
+
+
+
@@ -35,32 +35,21 @@ exports[`VideoSourceWidget snapshots snapshots: renders as expected with default
/>
-
-
-
- }
- placement="top"
- >
-
-
+
-
-
-
-
- }
- placement="top"
- >
-
-
-
+ iconAs="Icon"
+ key="top"
+ tooltipContent="Allow learners to download versions of this video in
+ different formats if they cannot use the edX video player or do not have
+ access to YouTube."
+ tooltipPlacement="top"
+ />
+
+
(videoUrl) => {
- const updatedFallbackVideos = [];
- let firstOccurence = true;
- fallbackVideos.forEach(item => {
- if (item === videoUrl && firstOccurence) {
- firstOccurence = false;
- } else {
- updatedFallbackVideos.push(item);
- }
- });
- dispatch(actions.video.updateField({ fallbackVideos: updatedFallbackVideos }));
-};
-
-export default { deleteFallbackVideo };
diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.jsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.jsx
new file mode 100644
index 000000000..a16306935
--- /dev/null
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.jsx
@@ -0,0 +1,66 @@
+import { actions } from '../../../../../../data/redux';
+import { isEdxVideo } from '../../../../../../data/services/cms/api';
+
+/**
+ * updateVideoType({ dispatch })({e, source})
+ * updateVideoType takes the current onBlur event, the current object of the video
+ * source, and dispatch method, and updates the redux value for all the fields to
+ * their default values except videoId, fallbackVideos, videoType, and handouts.
+ * @param {event} e - object for onBlur event
+ * @param {func} dispatch - redux dispatch method
+ * @param {object} source - object for the Video Source field functions and values
+ */
+export const updateVideoType = ({ dispatch }) => ({ e, source }) => {
+ source.onBlur(e);
+ let videoType;
+ let videoId;
+ if (isEdxVideo(source.local)) {
+ videoType = 'edxVideo';
+ videoId = source.local;
+ } else if (source.local.includes('youtu.be')) {
+ videoType = 'youtube';
+ videoId = '';
+ } else {
+ videoType = 'html5source';
+ videoId = '';
+ }
+ dispatch(actions.video.updateField({
+ videoId,
+ videoType,
+ allowVideoDownloads: false,
+ thumbnail: null,
+ transcripts: [],
+ allowTranscriptDownloads: false,
+ showTranscriptByDefault: false,
+ duration: {
+ startTime: '00:00:00',
+ stopTime: '00:00:00',
+ total: '00:00:00',
+ },
+ licenseType: null,
+ }));
+};
+
+/**
+ * deleteFallbackVideo({ fallbackVideos, dispatch })(videoUrl)
+ * deleteFallbackVideo takes the current array of fallback videos, string of
+ * deleted video URL and dispatch method, and updates the redux value for
+ * fallbackVideos.
+ * @param {array} fallbackVideos - array of current fallback videos
+ * @param {func} dispatch - redux dispatch method
+ * @param {string} videoUrl - string of the video URL for the fallabck video that needs to be deleted
+ */
+export const deleteFallbackVideo = ({ fallbackVideos, dispatch }) => (videoUrl) => {
+ const updatedFallbackVideos = [];
+ let firstOccurence = true;
+ fallbackVideos.forEach(item => {
+ if (item === videoUrl && firstOccurence) {
+ firstOccurence = false;
+ } else {
+ updatedFallbackVideos.push(item);
+ }
+ });
+ dispatch(actions.video.updateField({ fallbackVideos: updatedFallbackVideos }));
+};
+
+export default { deleteFallbackVideo };
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
new file mode 100644
index 000000000..1205ac8b9
--- /dev/null
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/hooks.test.jsx
@@ -0,0 +1,100 @@
+import { dispatch } from 'react-redux';
+import { actions } from '../../../../../../data/redux';
+import * as hooks from './hooks';
+
+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: {
+ updateField: jest.fn(),
+ },
+ },
+}));
+
+describe('VideoEditorHandout hooks', () => {
+ describe('updateVideoType', () => {
+ const sourceEdxVideo = {
+ onBlur: jest.fn(),
+ local: '06b1503a-7df4-4e72-b970-326e02dbcbe4',
+ };
+ const sourceYouTube = {
+ onBlur: jest.fn(),
+ local: 'youtu.be',
+ };
+ const sourceHtml5Source = {
+ onBlur: jest.fn(),
+ local: 'sOMEranDomfILe.mp4',
+ };
+ const mockState = {
+ videoId: '',
+ videoType: '',
+ allowVideoDownloads: false,
+ thumbnail: null,
+ transcripts: [],
+ allowTranscriptDownloads: false,
+ showTranscriptByDefault: false,
+ duration: {
+ startTime: '00:00:00',
+ stopTime: '00:00:00',
+ total: '00:00:00',
+ },
+ licenseType: null,
+ };
+ it('returns dispatches updateField action with default state and edxVideo Id', () => {
+ hooks.updateVideoType({ dispatch })({ e: { target: { value: sourceEdxVideo.local } }, source: sourceEdxVideo });
+ expect(dispatch).toHaveBeenCalledWith(
+ actions.video.updateField({
+ ...mockState,
+ videoId: sourceEdxVideo.local,
+ videoType: 'edxVideo',
+ }),
+ );
+ });
+ it('returns dispatches updateField action with default state and YouTube video', () => {
+ hooks.updateVideoType({ dispatch })({
+ e: { target: { value: sourceYouTube.local } },
+ source: sourceYouTube,
+ });
+ expect(dispatch).toHaveBeenCalledWith(
+ actions.video.updateField({
+ ...mockState,
+ videoId: sourceYouTube.local,
+ }),
+ );
+ });
+ it('returns dispatches updateField action with default state and html5source video', () => {
+ hooks.updateVideoType({ dispatch })({
+ e: { target: { value: sourceHtml5Source.local } },
+ source: sourceHtml5Source,
+ });
+ expect(dispatch).toHaveBeenCalledWith(
+ actions.video.updateField({
+ ...mockState,
+ videoId: sourceHtml5Source.local,
+ }),
+ );
+ });
+ });
+
+ describe('deleteFallbackVideo', () => {
+ const videoUrl = 'sOmERAndoMuRl1';
+ const fallbackVideos = ['sOmERAndoMuRl1', 'sOmERAndoMuRl2', 'sOmERAndoMuRl1', ''];
+ const updatedFallbackVideos = ['sOmERAndoMuRl2', 'sOmERAndoMuRl1', ''];
+ it('returns dispatches updateField action with updatedFallbackVideos', () => {
+ hooks.deleteFallbackVideo({ fallbackVideos, dispatch })(videoUrl);
+ expect(dispatch).toHaveBeenCalledWith(
+ actions.video.updateField({
+ fallbackVideos: updatedFallbackVideos,
+ }),
+ );
+ });
+ });
+});
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 add9674f7..11cf3bbf6 100644
--- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
+++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/components/VideoSourceWidget/index.jsx
@@ -4,10 +4,9 @@ import PropTypes from 'prop-types';
import {
Form,
- IconButton,
+ IconButtonWithTooltip,
+ ActionRow,
Icon,
- OverlayTrigger,
- Tooltip,
Button,
} from '@edx/paragon';
import { Delete, Info, Add } from '@edx/paragon/icons';
@@ -47,6 +46,7 @@ export const VideoSourceWidget = ({
},
});
const deleteFallbackVideo = module.deleteFallbackVideo({ fallbackVideos: fallbackVideos.formValue, dispatch });
+ const updateVideoType = module.updateVideoType({ dispatch });
return (
updateVideoType({ e, source })}
value={source.local}
/>
@@ -68,32 +68,25 @@ export const VideoSourceWidget = ({
{fallbackVideos.formValue.map((videoUrl, index) => (
-
+
-
-
-
- )}
- >
- deleteFallbackVideo(videoUrl)}
- />
-
+ deleteFallbackVideo(videoUrl)}
+ />
))}
-
+
-
-
-
- )}
- >
-
-
-
+ tooltipPlacement="top"
+ tooltipContent={intl.formatMessage(messages.tooltipMessage)}
+ src={Info}
+ iconAs={Icon}
+ alt={intl.formatMessage(messages.tooltipMessage)}
+ />
+
+
);
};
-VideoSourceWidget.defaultProps = {
-};
VideoSourceWidget.propTypes = {
// injected
intl: intlShape.isRequired,