fix: Fixing the accessing of undefined variables in video

Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
This commit is contained in:
Farhaan Bukhsh
2023-08-16 17:20:19 +05:30
parent f822d95d6a
commit b7a04e17da
7 changed files with 91 additions and 77 deletions

View File

@@ -26,10 +26,11 @@ const URLUploader = () => {
);
};
export const VideoUploader = ({ onUpload, setLoading }) => {
const [textInputValue, settextInputValue] = React.useState('');
export const VideoUploader = ({ setLoading }) => {
const [textInputValue, setTextInputValue] = React.useState('');
const onURLUpload = hooks.onVideoUpload();
const intl = useIntl();
const dispatch = useDispatch();
const handleProcessUpload = ({ fileData }) => {
dispatch(thunkActions.video.uploadVideo({
@@ -53,7 +54,7 @@ export const VideoUploader = ({ onUpload, setLoading }) => {
aria-label={intl.formatMessage(messages.pasteURL)}
aria-describedby="basic-addon2"
borderless
onChange={(event) => { settextInputValue(event.target.value); }}
onChange={(event) => { setTextInputValue(event.target.value); }}
/>
<div className="justify-content-center align-self-center bg-light rounded-circle p-0 x-small url-submit-button">
<IconButton
@@ -71,7 +72,6 @@ export const VideoUploader = ({ onUpload, setLoading }) => {
};
VideoUploader.propTypes = {
onUpload: PropTypes.func.isRequired,
setLoading: PropTypes.func.isRequired,
};

View File

@@ -1,6 +1,5 @@
import React from 'react';
import * as module from './hooks';
import { selectors } from '../../data/redux';
import { selectors, thunkActions } from '../../data/redux';
import store from '../../data/store';
import * as appHooks from '../../hooks';
@@ -8,29 +7,6 @@ export const {
navigateTo,
} = appHooks;
export const state = {
// eslint-disable-next-line react-hooks/rules-of-hooks
loading: (val) => React.useState(val),
// eslint-disable-next-line react-hooks/rules-of-hooks
textInputValue: (val) => React.useState(val),
};
export const uploadEditor = () => {
const [loading, setLoading] = module.state.loading(false);
return {
loading,
setLoading,
};
};
export const uploader = () => {
const [textInputValue, settextInputValue] = module.state.textInputValue('');
return {
textInputValue,
settextInputValue,
};
};
export const postUploadRedirect = (storeState) => {
const learningContextId = selectors.app.learningContextId(storeState);
const blockId = selectors.app.blockId(storeState);
@@ -42,9 +18,21 @@ export const onVideoUpload = () => {
return module.postUploadRedirect(storeState);
};
export const useUploadVideo = async ({
dispatch,
supportedFiles,
setLoadSpinner,
postUploadRedirectFunction,
}) => {
dispatch(thunkActions.video.uploadVideo({
supportedFiles,
setLoadSpinner,
postUploadRedirectFunction,
}));
};
export default {
postUploadRedirect,
uploadEditor,
uploader,
onVideoUpload,
useUploadVideo,
};

View File

@@ -1,27 +0,0 @@
import * as hooks from './hooks';
import { MockUseState } from '../../../testUtils';
const state = new MockUseState(hooks);
describe('Video Upload Editor hooks', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('state hooks', () => {
state.testGetter(state.keys.loading);
});
describe('using state', () => {
beforeEach(() => { state.mock(); });
afterEach(() => { state.restore(); });
describe('Hooks for Video Upload', () => {
beforeEach(() => {
hooks.uploadEditor();
hooks.uploader();
});
it('initialize state with correct values', () => {
expect(state.stateVals.loading).toEqual(false);
});
});
});
});

View File

@@ -5,20 +5,14 @@ import {
Icon, IconButton, Spinner,
} from '@edx/paragon';
import { Close } from '@edx/paragon/icons';
import { connect } from 'react-redux';
import { thunkActions } from '../../data/redux';
import './index.scss';
import * as hooks from './hooks';
import messages from './messages';
import * as editorHooks from '../EditorContainer/hooks';
import { VideoUploader } from './VideoUploader';
import * as editorHooks from '../EditorContainer/hooks';
export const VideoUploadEditor = (
{
onClose,
// Redux states
uploadVideo,
},
) => {
const [loading, setLoading] = React.useState(false);
@@ -37,7 +31,7 @@ export const VideoUploadEditor = (
onClick={handleCancel}
/>
</div>
<VideoUploader onUpload={uploadVideo} setLoading={setLoading} />
<VideoUploader setLoading={setLoading} />
</div>
) : (
<div className="text-center p-6">
@@ -54,13 +48,6 @@ export const VideoUploadEditor = (
VideoUploadEditor.propTypes = {
onClose: PropTypes.func.isRequired,
uploadVideo: PropTypes.func.isRequired,
};
export const mapStateToProps = () => ({});
export const mapDispatchToProps = {
uploadVideo: thunkActions.video.uploadVideo,
};
export default connect(mapStateToProps, mapDispatchToProps)(VideoUploadEditor);
export default VideoUploadEditor;

View File

@@ -1,5 +1,9 @@
import React from 'react';
import { IntlProvider } from '@edx/frontend-platform/i18n';
import { initializeMockApp } from '@edx/frontend-platform';
import { AppProvider } from '@edx/frontend-platform/react';
import { configureStore } from '@reduxjs/toolkit';
import { render, fireEvent } from '@testing-library/react';
import '@testing-library/jest-dom';
import VideoUploadEditor from '.';

View File

@@ -11,10 +11,16 @@ export const loadVideoData = (selectedVideoId, selectedVideoUrl) => (dispatch, g
const state = getState();
const blockValueData = state.app.blockValue.data;
let rawVideoData = blockValueData.metadata ? blockValueData.metadata : {};
if (selectedVideoId != null) {
const rawVideos = Object.values(selectors.app.videos(state));
const selectedVideo = rawVideos.find(video => video.edx_video_id === selectedVideoId);
if (selectedVideo) {
const rawVideos = Object.values(selectors.app.videos(state));
if (selectedVideoId !== undefined && selectedVideoId !== null) {
const selectedVideo = _.find(rawVideos, video => {
if (_.has(video, 'edx_video_id')) {
return video.edx_video_id === selectedVideoId;
}
return false;
});
if (selectedVideo !== undefined && selectedVideo !== null) {
rawVideoData = {
edx_video_id: selectedVideo.edx_video_id,
thumbnail: selectedVideo.course_video_image_url,

View File

@@ -88,6 +88,7 @@ const testState = {
const testVideosState = {
edx_video_id: mockSelectedVideoId,
thumbnail: 'thumbnail',
course_video_image_url: 'course_video_image_url',
duration: 60,
transcripts: ['es'],
transcript_urls: { es: 'url' },
@@ -262,6 +263,61 @@ describe('video thunkActions', () => {
noDerivatives: true,
shareAlike: false,
},
thumbnail: testVideosState.course_video_image_url,
});
});
it('dispatches actions.video.load with different selectedVideoId', () => {
getState = jest.fn(() => ({
app: {
blockId: 'soMEBloCk',
studioEndpointUrl: 'soMEeNDPoiNT',
blockValue: { data: { metadata: {} } },
courseDetails: { data: { license: null } },
studioView: { data: { html: 'sOMeHTml' } },
videos: testVideosState,
},
}));
thunkActions.loadVideoData('ThisIsAVideoId2', null)(dispatch, getState);
[
[dispatchedLoad],
[dispatchedAction1],
[dispatchedAction2],
] = dispatch.mock.calls;
expect(dispatchedLoad.load).toEqual({
videoSource: 'videOsOurce',
videoId: 'videOiD',
fallbackVideos: 'fALLbACKvIDeos',
allowVideoDownloads: undefined,
transcripts: testMetadata.transcripts,
selectedVideoTranscriptUrls: testMetadata.transcript_urls,
allowTranscriptDownloads: undefined,
allowVideoSharing: {
level: 'course',
value: true,
},
showTranscriptByDefault: undefined,
duration: {
startTime: testMetadata.start_time,
stopTime: 0,
total: 0,
},
handout: undefined,
licenseType: 'liCENSEtyPe',
licenseDetails: {
attribution: true,
noncommercial: true,
noDerivatives: true,
shareAlike: false,
},
videoSharingEnabledForCourse: undefined,
videoSharingLearnMoreLink: undefined,
courseLicenseType: 'liCENSEtyPe',
courseLicenseDetails: {
attribution: true,
noncommercial: true,
noDerivatives: true,
shareAlike: false,
},
thumbnail: undefined,
});
});