`;
-exports[`VideoUploader renders without errors 1`] = `
+exports[`VideoUploader snapshots renders as expected with error message 1`] = `
-
+
-
-
-
-
-
-
- FormattedMessage
-
-
- FormattedMessage
-
-
-
-
- OR
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+ OR
+
+
+
+
+
+
`;
+
+exports[`VideoUploaderEdirtor snapshots renders as expected with default behavior 1`] = `
+
+
+
+`;
diff --git a/src/editors/containers/VideoUploadEditor/hooks.test.js b/src/editors/containers/VideoUploadEditor/hooks.test.js
index c1ef806df..23dc1e519 100644
--- a/src/editors/containers/VideoUploadEditor/hooks.test.js
+++ b/src/editors/containers/VideoUploadEditor/hooks.test.js
@@ -1,92 +1,31 @@
-import hooks from './hooks';
-import * as requests from '../../data/redux/thunkActions/requests';
+import * as hooks from './hooks';
+import { MockUseState } from '../../../testUtils';
-jest.mock('../../data/redux/thunkActions/requests');
-
-describe('uploadVideo', () => {
- const dispatch = jest.fn();
- const supportedFiles = [
- new File(['content1'], 'file1.mp4', { type: 'video/mp4' }),
- new File(['content2'], 'file2.mov', { type: 'video/quicktime' }),
- ];
+const state = new MockUseState(hooks);
+describe('Video Upload Editor hooks', () => {
beforeEach(() => {
- jest.resetAllMocks();
- jest.restoreAllMocks();
+ jest.clearAllMocks();
});
-
- it('should dispatch uploadVideo action with correct data and onSuccess callback', async () => {
- requests.uploadVideo.mockImplementation(() => 'requests.uploadVideo');
- const data = {
- files: [
- { file_name: 'file1.mp4', content_type: 'video/mp4' },
- { file_name: 'file2.mov', content_type: 'video/quicktime' },
- ],
- };
-
- await hooks.uploadVideo({ dispatch, supportedFiles });
-
- expect(requests.uploadVideo).toHaveBeenCalledWith({ data, onSuccess: expect.any(Function) });
- expect(dispatch).toHaveBeenCalledWith('requests.uploadVideo');
+ describe('state hooks', () => {
+ state.testGetter(state.keys.loading);
+ state.testGetter(state.keys.errorMessage);
+ state.testGetter(state.keys.textInputValue);
});
+ describe('using state', () => {
+ beforeEach(() => { state.mock(); });
+ afterEach(() => { state.restore(); });
- it('should call fetch with correct arguments for each file', async () => {
- const mockResponseData = { success: true };
- const mockFetchResponse = Promise.resolve({ data: mockResponseData });
- global.fetch = jest.fn().mockImplementation(() => mockFetchResponse);
- const response = {
- files: [
- { file_name: 'file1.mp4', upload_url: 'http://example.com/put_video1' },
- { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' },
- ],
- };
- const mockRequestResponse = { data: response };
- requests.uploadVideo.mockImplementation(async ({ onSuccess }) => {
- await onSuccess(mockRequestResponse);
+ describe('Hooks for Video Upload', () => {
+ beforeEach(() => {
+ hooks.uploadEditor();
+ hooks.uploader();
+ });
+ it('initialize state with correct values', () => {
+ expect(state.stateVals.loading).toEqual(false);
+ expect(state.stateVals.errorMessage).toEqual(null);
+ expect(state.stateVals.textInputValue).toEqual('');
+ });
});
-
- await hooks.uploadVideo({ dispatch, supportedFiles });
-
- expect(fetch).toHaveBeenCalledTimes(2);
- response.files.forEach(({ upload_url: uploadUrl }, index) => {
- expect(fetch.mock.calls[index][0]).toEqual(uploadUrl);
- });
- supportedFiles.forEach((file, index) => {
- expect(fetch.mock.calls[index][1].body.get('uploaded-file')).toBe(file);
- });
- });
-
- it('should log an error if fetch failed to upload a file', async () => {
- const error = new Error('Uh-oh!');
- global.fetch = jest.fn().mockRejectedValue(error);
- const response = {
- files: [
- { file_name: 'file1.mp4', upload_url: 'http://example.com/put_video1' },
- { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' },
- ],
- };
- const mockRequestResponse = { data: response };
- requests.uploadVideo.mockImplementation(async ({ onSuccess }) => {
- await onSuccess(mockRequestResponse);
- });
-
- await hooks.uploadVideo({ dispatch, supportedFiles });
- });
-
- it('should log an error if file object is not found in supportedFiles array', () => {
- const response = {
- files: [
- { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' },
- ],
- };
- const mockRequestResponse = { data: response };
- const spyConsoleError = jest.spyOn(console, 'error');
- requests.uploadVideo.mockImplementation(({ onSuccess }) => {
- onSuccess(mockRequestResponse);
- });
-
- hooks.uploadVideo({ dispatch, supportedFiles: [supportedFiles[0]] });
-
- expect(spyConsoleError).toHaveBeenCalledWith('Could not find file object with name "file2.mov" in supportedFiles array.');
});
});
diff --git a/src/editors/containers/VideoUploadEditor/index.test.jsx b/src/editors/containers/VideoUploadEditor/index.test.jsx
index 8f256e457..3b6e97c90 100644
--- a/src/editors/containers/VideoUploadEditor/index.test.jsx
+++ b/src/editors/containers/VideoUploadEditor/index.test.jsx
@@ -1,142 +1,37 @@
import React from 'react';
-import { IntlProvider } from '@edx/frontend-platform/i18n';
-import { render, fireEvent, act } from '@testing-library/react';
import '@testing-library/jest-dom';
+import { shallow } from 'enzyme';
import VideoUploadEditor, { VideoUploader } from '.';
-import * as hooks from './hooks';
-import * as appHooks from '../../hooks';
-
-const mockDispatch = jest.fn();
-const mockOnUpload = jest.fn();
-
-jest.mock('react-redux', () => ({
- useDispatch: () => mockDispatch,
-}));
-jest.mock('../../hooks', () => ({
- ...jest.requireActual('../../hooks'),
- navigateTo: jest.fn((args) => ({ navigateTo: args })),
-}));
+import { formatMessage } from '../../../testUtils';
const defaultEditorProps = {
- intl: {},
+ onClose: jest.fn().mockName('props.onClose'),
+ intl: { formatMessage },
+ uploadVideo: jest.fn(),
};
const defaultUploaderProps = {
- onUpload: mockOnUpload,
- errorMessage: '',
- intl: {},
+ onUpload: jest.fn(),
+ errorMessage: null,
+ intl: { formatMessage },
};
-const renderEditorComponent = (props = defaultEditorProps) => render(
-
-
- ,
-);
-
-const renderUploaderComponent = (props = defaultUploaderProps) => render(
-
-
- ,
-);
-
-describe('VideoUploadEditor', () => {
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- it('renders without errors', () => {
- const { container } = renderEditorComponent();
- expect(container).toMatchSnapshot();
- });
-
- it('updates the input field value when user types', () => {
- const { getByPlaceholderText } = renderEditorComponent();
- const input = getByPlaceholderText('Paste your video ID or URL');
-
- fireEvent.change(input, { target: { value: 'test value' } });
- expect(input.value).toBe('test value');
- });
-
- it('click on the save button', () => {
- const { getByPlaceholderText, getByTestId } = renderEditorComponent();
- const testValue = 'test vale';
- const input = getByPlaceholderText('Paste your video ID or URL');
- fireEvent.change(input, { target: { value: testValue } });
- const button = getByTestId('inputSaveButton');
- fireEvent.click(button);
- expect(appHooks.navigateTo).toHaveBeenCalled();
- });
-
- it('shows error message with unsupported files', async () => {
- const { getByTestId, findByText } = renderEditorComponent();
- const fileInput = getByTestId('fileInput');
-
- const unsupportedFile = new File(['(⌐□_□)'], 'unsupported.avi', { type: 'video/avi' });
- fireEvent.change(fileInput, { target: { files: [unsupportedFile] } });
-
- const errorMsg = await findByText('Video must be an MP4 or MOV file');
- expect(errorMsg).toBeInTheDocument();
- });
-
- it('calls uploadVideo with supported files', async () => {
- const uploadVideoSpy = jest.spyOn(hooks, 'uploadVideo');
- const { container } = renderEditorComponent();
- const dropzone = container.querySelector('.dropzone-middle');
-
- const supportedFile = new File(['(⌐□_□)'], 'supported.mp4', { type: 'video/mp4' });
-
- await act(async () => {
- fireEvent.drop(dropzone, {
- dataTransfer: {
- files: [supportedFile],
- types: ['Files'],
- },
- });
- });
-
- expect(uploadVideoSpy).toHaveBeenCalledWith(expect.objectContaining({
- dispatch: mockDispatch,
- supportedFiles: expect.arrayContaining([
- expect.objectContaining({
- name: supportedFile.name,
- type: supportedFile.type,
- size: supportedFile.size,
- }),
- ]),
- }));
- });
-});
-
describe('VideoUploader', () => {
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- it('renders without errors', () => {
- const { container } = renderUploaderComponent();
- expect(container).toMatchSnapshot();
- });
-
- it('renders with an error message', () => {
- const errorMessage = 'Video must be an MP4 or MOV file';
- const { getByText } = renderUploaderComponent({ ...defaultUploaderProps, errorMessage });
- expect(getByText(errorMessage)).toBeInTheDocument();
- });
-
- it('calls the onUpload function when a supported file is dropped', async () => {
- const { container } = renderUploaderComponent();
- const dropzone = container.querySelector('.dropzone-middle');
- const file = new File(['(⌐□_□)'], 'video.mp4', { type: 'video/mp4' });
-
- await act(async () => {
- fireEvent.drop(dropzone, {
- dataTransfer: {
- files: [file],
- types: ['Files'],
- },
- });
+ describe('snapshots', () => {
+ test('renders as expected with default behavior', () => {
+ expect(shallow(
)).toMatchSnapshot();
+ });
+ test('renders as expected with error message', () => {
+ const defaultUploaderPropsWithError = { ...defaultUploaderProps, errorMessages: 'Some Error' };
+ expect(shallow(
)).toMatchSnapshot();
+ });
+ });
+});
+
+describe('VideoUploaderEdirtor', () => {
+ describe('snapshots', () => {
+ test('renders as expected with default behavior', () => {
+ expect(shallow(
)).toMatchSnapshot();
});
-
- expect(mockOnUpload).toHaveBeenCalledWith(file);
});
});
diff --git a/src/editors/data/redux/thunkActions/video.js b/src/editors/data/redux/thunkActions/video.js
index 194ae5668..3e2c10ed5 100644
--- a/src/editors/data/redux/thunkActions/video.js
+++ b/src/editors/data/redux/thunkActions/video.js
@@ -388,7 +388,6 @@ export const uploadVideo = ({ supportedFiles, setLoadSpinner, postUploadRedirect
const edxVideoId = fileObj.edx_video_id;
const uploadUrl = fileObj.upload_url;
const uploadFile = supportedFiles.find((file) => file.name === fileName);
-
if (!uploadFile) {
console.error(`Could not find file object with name "${fileName}" in supportedFiles array.`);
return;
diff --git a/src/editors/data/redux/thunkActions/video.test.js b/src/editors/data/redux/thunkActions/video.test.js
index 841cb2b36..a8b0b177f 100644
--- a/src/editors/data/redux/thunkActions/video.test.js
+++ b/src/editors/data/redux/thunkActions/video.test.js
@@ -32,6 +32,7 @@ jest.mock('./requests', () => ({
checkTranscriptsForImport: (args) => ({ checkTranscriptsForImport: args }),
importTranscript: (args) => ({ importTranscript: args }),
fetchVideoFeatures: (args) => ({ fetchVideoFeatures: args }),
+ uploadVideo: (args) => ({ uploadVideo: args }),
}));
jest.mock('../../../utils', () => ({
@@ -669,3 +670,79 @@ describe('video thunkActions', () => {
});
});
});
+
+describe('uploadVideo', () => {
+ let dispatch;
+ let setLoadSpinner;
+ let postUploadRedirect;
+ let dispatchedAction;
+ const supportedFiles = [
+ new File(['content1'], 'file1.mp4', { type: 'video/mp4' }),
+ new File(['content2'], 'file2.mov', { type: 'video/quicktime' }),
+ ];
+
+ beforeEach(() => {
+ dispatch = jest.fn((action) => ({ dispatch: action }));
+ setLoadSpinner = jest.fn();
+ postUploadRedirect = jest.fn();
+ jest.resetAllMocks();
+ jest.restoreAllMocks();
+ });
+
+ it('dispatch uploadVideo action with right data', async () => {
+ const data = {
+ files: [
+ { file_name: 'file1.mp4', content_type: 'video/mp4' },
+ { file_name: 'file2.mov', content_type: 'video/quicktime' },
+ ],
+ };
+
+ thunkActions.uploadVideo({ supportedFiles, setLoadSpinner, postUploadRedirect })(dispatch);
+ [[dispatchedAction]] = dispatch.mock.calls;
+ expect(dispatchedAction.uploadVideo).not.toEqual(undefined);
+ expect(setLoadSpinner).toHaveBeenCalled();
+ expect(dispatchedAction.uploadVideo.data).toEqual(data);
+ });
+
+ it('should call fetch with correct arguments for each file', async () => {
+ const mockResponseData = { success: true };
+ const mockFetchResponse = Promise.resolve({ data: mockResponseData });
+ global.fetch = jest.fn().mockImplementation(() => mockFetchResponse);
+ const response = {
+ files: [
+ { file_name: 'file1.mp4', upload_url: 'http://example.com/put_video1' },
+ { file_name: 'file2.mov', upload_url: 'http://example.com/put_video2' },
+ ],
+ };
+ const mockRequestResponse = { data: response };
+ thunkActions.uploadVideo({ supportedFiles, setLoadSpinner, postUploadRedirect })(dispatch);
+ [[dispatchedAction]] = dispatch.mock.calls;
+
+ dispatchedAction.uploadVideo.onSuccess(mockRequestResponse);
+
+ expect(fetch).toHaveBeenCalledTimes(2);
+ response.files.forEach(({ upload_url: uploadUrl }, index) => {
+ expect(fetch.mock.calls[index][0]).toEqual(uploadUrl);
+ });
+ supportedFiles.forEach((file, index) => {
+ expect(fetch.mock.calls[index][1].body.get('uploaded-file')).toBe(file);
+ });
+ });
+
+ it('should log an error if file object is not found in supportedFiles array', () => {
+ const mockResponseData = { success: true };
+ const mockFetchResponse = Promise.resolve({ data: mockResponseData });
+ global.fetch = jest.fn().mockImplementation(() => mockFetchResponse);
+ const response = {
+ files: [
+ { file_name: 'file2.gif', upload_url: 'http://example.com/put_video2' },
+ ],
+ };
+ const mockRequestResponse = { data: response };
+ const spyConsoleError = jest.spyOn(console, 'error');
+
+ thunkActions.uploadVideo({ supportedFiles: [supportedFiles[0]], setLoadSpinner, postUploadRedirect })(dispatch);
+ dispatchedAction.uploadVideo.onSuccess(mockRequestResponse);
+ expect(spyConsoleError).toHaveBeenCalledWith('Could not find file object with name "file2.gif" in supportedFiles array.');
+ });
+});