diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx new file mode 100644 index 000000000..296d59c89 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx @@ -0,0 +1,116 @@ +import { render, waitFor, act } from '@testing-library/react'; +import { configureStore } from '@reduxjs/toolkit'; +import { MemoryRouter } from 'react-router-dom'; +import { AppProvider } from '@edx/frontend-platform/react'; +import { IntlProvider } from '@edx/frontend-platform/i18n'; +import { initializeMockApp } from '@edx/frontend-platform'; +import VideoEditorModal from './VideoEditorModal'; +import { thunkActions } from '../../../data/redux'; + +jest.mock('../../../data/redux', () => ({ + ...jest.requireActual('../../../data/redux'), + thunkActions: { + video: { + loadVideoData: jest + .fn() + .mockImplementation(() => ({ type: 'MOCK_ACTION' })), + }, + }, +})); + +describe('VideoUploader', () => { + let store; + + beforeEach(async () => { + store = configureStore({ + reducer: (state, action) => (action && action.newState ? action.newState : state), + preloadedState: { + app: { + videos: [], + learningContextId: 'course-v1:test+test+test', + blockId: 'some-block-id', + courseDetails: {}, + }, + requests: { + uploadAsset: { status: 'inactive' }, + uploadTranscript: { status: 'inactive' }, + deleteTranscript: { status: 'inactive' }, + fetchVideos: { status: 'inactive' }, + }, + video: { + videoSource: '', + videoId: '', + fallbackVideos: ['', ''], + allowVideoDownloads: false, + allowVideoSharing: { level: 'block', value: false }, + thumbnail: null, + transcripts: [], + transcriptHandlerUrl: '', + selectedVideoTranscriptUrls: {}, + allowTranscriptDownloads: false, + duration: { + startTime: '00:00:00', + stopTime: '00:00:00', + total: '00:00:00', + }, + }, + }, + }); + initializeMockApp({ + authenticatedUser: { + userId: 3, + username: 'test-user', + administrator: true, + roles: [], + }, + }); + }); + + const renderComponent = async () => render( + + + + + + + , + ); + + it('should render the component and call loadVideoData with correct parameters', async () => { + await renderComponent(); + await waitFor(() => { + expect(thunkActions.video.loadVideoData).toHaveBeenCalledWith( + 'id_1', + 'https://video.com', + ); + }); + }); + + it('should call loadVideoData again when isLoaded state changes', async () => { + await renderComponent(); + await waitFor(() => { + expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(2); + }); + + act(() => { + store.dispatch({ + type: 'UPDATE_STATE', + newState: { + ...store.getState(), + requests: { + ...store.getState().requests, + fetchVideos: { status: 'completed' }, // isLoaded = true + }, + }, + }); + }); + + await waitFor(() => { + expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(3); + }); + }); +}); diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx index 14801f56e..66f95b0ab 100644 --- a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx +++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx @@ -1,8 +1,10 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; +import { useLocation } from 'react-router-dom'; import * as appHooks from '../../../hooks'; import { thunkActions, selectors } from '../../../data/redux'; import VideoSettingsModal from './VideoSettingsModal'; +import { RequestKeys } from '../../../data/constants/requests'; interface Props { isLibrary: boolean; @@ -27,11 +29,19 @@ const VideoEditorModal: React.FC = ({ isLibrary, }) => { const dispatch = useDispatch(); - const searchParams = new URLSearchParams(document.location.search); + const location = useLocation(); + const searchParams = new URLSearchParams(location.search); const selectedVideoId = searchParams.get('selectedVideoId'); const selectedVideoUrl = searchParams.get('selectedVideoUrl'); const onReturn = hooks.useReturnToGallery(); - hooks.initialize(dispatch, selectedVideoId, selectedVideoUrl); + const isLoaded = useSelector( + (state) => selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchVideos }), + ); + + useEffect(() => { + hooks.initialize(dispatch, selectedVideoId, selectedVideoUrl); + }, [isLoaded, dispatch, selectedVideoId, selectedVideoUrl]); + return (