diff --git a/src/course-unit/CourseUnit.test.jsx b/src/course-unit/CourseUnit.test.jsx index 0ae5c382d4..ba3b93fb91 100644 --- a/src/course-unit/CourseUnit.test.jsx +++ b/src/course-unit/CourseUnit.test.jsx @@ -64,6 +64,8 @@ import sidebarMessages from './sidebar/messages'; import messages from './messages'; import { mockWaffleFlags } from '../data/apiHooks.mock'; +import { getApiWaffleFlagsUrl } from '../data/api'; + let axiosMock; let store; let queryClient; @@ -158,6 +160,12 @@ describe('', () => { axiosMock .onGet(getContentTaxonomyTagsCountApiUrl(blockId)) .reply(200, 17); + axiosMock.onGet(getApiWaffleFlagsUrl()).reply(200, { + waffle_flags: { + 'studio.enable_new_video_uploads_page': true, + 'studio.enable_new_text_editor': false, + }, + }); }); it('render CourseUnit component correctly', async () => { diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx index 296d59c89f..37b34517f0 100644 --- a/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx +++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.test.tsx @@ -1,87 +1,58 @@ -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 { thunkActions } from '@src/editors/data/redux'; +import { initializeMocks, waitFor, act } from '@src/testUtils'; +import editorRender, { getEditorStore, PartialEditorState } from '@src/editors/editorTestRender'; 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' })), +thunkActions.video.loadVideoData = jest.fn().mockImplementation(() => ({ type: 'MOCK_ACTION' })); + +const initialState: PartialEditorState = { + app: { + videos: [], + learningContextId: 'course-v1:test+test+test', + blockId: 'some-block-id', + courseDetails: {}, + }, + requests: { + uploadAsset: { status: 'inactive', response: {} as any }, + uploadTranscript: { status: 'inactive', response: {} as any }, + deleteTranscript: { status: 'inactive', response: {} as any }, + fetchVideos: { status: 'inactive', response: {} as any }, + }, + video: { + videoSource: '', + videoId: '', + fallbackVideos: ['', ''], + allowVideoDownloads: false, + allowVideoSharing: { level: 'block', value: false }, + thumbnail: null, + transcripts: [], + selectedVideoTranscriptUrls: {}, + allowTranscriptDownloads: false, + duration: { + startTime: '00:00:00', + stopTime: '00:00:00', + total: '00:00:00', }, }, -})); +}; 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: [], - }, - }); + initializeMocks(); }); - const renderComponent = async () => render( - - - - - - - , + const renderComponent = () => editorRender( + , + { + routerProps: { + initialEntries: ['/some/path?selectedVideoId=id_1&selectedVideoUrl=https://video.com'], + }, + initialState, + }, ); it('should render the component and call loadVideoData with correct parameters', async () => { - await renderComponent(); + renderComponent(); await waitFor(() => { expect(thunkActions.video.loadVideoData).toHaveBeenCalledWith( 'id_1', @@ -91,10 +62,11 @@ describe('VideoUploader', () => { }); it('should call loadVideoData again when isLoaded state changes', async () => { - await renderComponent(); + renderComponent(); await waitFor(() => { - expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(2); + expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(1); }); + const store = getEditorStore(); act(() => { store.dispatch({ @@ -110,7 +82,7 @@ describe('VideoUploader', () => { }); await waitFor(() => { - expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(3); + expect(thunkActions.video.loadVideoData).toHaveBeenCalledTimes(2); }); }); }); diff --git a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx index 55d36c3556..05c2b4cebf 100644 --- a/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx +++ b/src/editors/containers/VideoEditor/components/VideoEditorModal.tsx @@ -1,6 +1,7 @@ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { useLocation } from 'react-router-dom'; +import { useWaffleFlags } from '@src/data/apiHooks'; import * as appHooks from '../../../hooks'; import { thunkActions, selectors } from '../../../data/redux'; import VideoSettingsModal from './VideoSettingsModal'; @@ -41,6 +42,7 @@ const VideoEditorModal: React.FC = ({ const isLoaded = useSelector( (state) => selectors.requests.isFinished(state, { requestKey: RequestKeys.fetchVideos }), ); + const { useNewVideoUploadsPage } = useWaffleFlags(); useEffect(() => { hooks.initialize(dispatch, selectedVideoId, selectedVideoUrl); @@ -51,6 +53,7 @@ const VideoEditorModal: React.FC = ({ onReturn: onSettingsReturn, isLibrary, onClose, + useNewVideoUploadsPage, }} /> ); diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.test.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.test.tsx new file mode 100644 index 0000000000..012ebd3328 --- /dev/null +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.test.tsx @@ -0,0 +1,60 @@ +import { + screen, fireEvent, initializeMocks, +} from '@src/testUtils'; +import editorRender from '@src/editors/editorTestRender'; +import VideoSettingsModal from '.'; + +const defaultProps = { + onReturn: jest.fn(), + isLibrary: false, + onClose: jest.fn(), + useNewVideoUploadsPage: true, +}; + +const renderComponent = (overrideProps = {}) => { + const customInitialState = { + app: { + videos: [], + learningContextId: 'course-v1:test+test+test', + blockId: 'some-block-id', + courseDetails: {}, + }, + }; + + initializeMocks(); + + return { + ...editorRender( + , + { initialState: customInitialState }, + ), + }; +}; + +describe('', () => { + beforeEach(async () => { + window.scrollTo = jest.fn(); + }); + + it('renders back button when useNewVideoUploadsPage is true and isLibrary is false', () => { + renderComponent(); + expect(screen.getByRole('button', { name: /replace video/i })).toBeInTheDocument(); + }); + + it('does not render back button when isLibrary is true', () => { + renderComponent({ isLibrary: true }); + expect(screen.queryByRole('button', { name: /replace video/i })).not.toBeInTheDocument(); + }); + + it('calls onReturn when back button is clicked', () => { + renderComponent(); + fireEvent.click(screen.getByRole('button', { name: /replace video/i })); + expect(defaultProps.onReturn).toHaveBeenCalled(); + }); + + it('calls onClose if onReturn is not provided', () => { + renderComponent({ onReturn: null }); + fireEvent.click(screen.getByRole('button', { name: /replace video/i })); + expect(defaultProps.onClose).toHaveBeenCalled(); + }); +}); diff --git a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx index 3718b3ca54..88fa08c750 100644 --- a/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx +++ b/src/editors/containers/VideoEditor/components/VideoSettingsModal/index.tsx @@ -21,20 +21,22 @@ interface Props { onReturn: () => void; isLibrary: boolean; onClose?: (() => void) | null; + useNewVideoUploadsPage?: boolean; } const VideoSettingsModal: React.FC = ({ onReturn, isLibrary, onClose, + useNewVideoUploadsPage, }) => ( <> - {!isLibrary && ( + {!isLibrary && useNewVideoUploadsPage && (