fix: Added tests for video upload
Signed-off-by: Farhaan Bukhsh <farhaan@opencraft.com>
This commit is contained in:
@@ -1,166 +1,227 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`VideoUploadEditor renders without errors 1`] = `
|
||||
exports[`VideoUploader snapshots renders as expected with default behavior 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="marked-area"
|
||||
className="d-flex flex-column justify-content-center align-items-center p-4 w-100 min-vh-100"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onDragEnter={[Function]}
|
||||
onDragLeave={[Function]}
|
||||
onDragOver={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="presentation"
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-end close-button-container"
|
||||
>
|
||||
<iconbutton
|
||||
iconas="Icon"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-center align-items-center p-4 w-100 min-vh-100"
|
||||
role="presentation"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-center align-items-center gap-2 text-center min-vh-100 w-100
|
||||
className="d-flex flex-column justify-content-center align-items-center gap-2 text-center min-vh-100 w-100
|
||||
dropzone-middle "
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-center align-items-center bg-light rounded-circle file-upload"
|
||||
>
|
||||
<icon
|
||||
class="text-muted"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center gap-1 flex-wrap flex-column pt-5"
|
||||
>
|
||||
<span
|
||||
style="font-size: 20px;"
|
||||
>
|
||||
FormattedMessage
|
||||
</span>
|
||||
<span
|
||||
style="font-size: 12px;"
|
||||
>
|
||||
FormattedMessage
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center mt-3"
|
||||
>
|
||||
<span
|
||||
class="mx-2 text-dark"
|
||||
>
|
||||
OR
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
accept=""
|
||||
data-testid="fileInput"
|
||||
style="display: none;"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
>
|
||||
<div
|
||||
className="d-flex justify-content-center align-items-center bg-light rounded-circle file-upload"
|
||||
>
|
||||
<Icon
|
||||
className="text-muted"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex video-id-container"
|
||||
className="d-flex align-items-center justify-content-center gap-1 flex-wrap flex-column pt-5"
|
||||
>
|
||||
<div
|
||||
class="d-flex video-id-prompt"
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "20px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<input
|
||||
placeholder="Paste your video ID or URL"
|
||||
type="text"
|
||||
value=""
|
||||
<FormattedMessage
|
||||
defaultMessage="Drag and drop video here or click to upload"
|
||||
description="Display message for Drag and Drop zone"
|
||||
id="VideoUploadEditor.dropVideoFileHere"
|
||||
/>
|
||||
<button
|
||||
class="border-start-0"
|
||||
data-testid="inputSaveButton"
|
||||
type="button"
|
||||
>
|
||||
<icon
|
||||
class="rounded-circle text-dark"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</span>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "12px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Upload MP4 or MOV files (5 GB max)"
|
||||
description="Info message for supported formats"
|
||||
id="VideoUploadEditor.uploadInfo"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex align-items-center mt-3"
|
||||
>
|
||||
<span
|
||||
className="mx-2 text-dark"
|
||||
>
|
||||
OR
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
accept=""
|
||||
data-testid="fileInput"
|
||||
multiple={false}
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"display": "none",
|
||||
}
|
||||
}
|
||||
tabIndex={-1}
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex video-id-container"
|
||||
>
|
||||
<div
|
||||
className="d-flex video-id-prompt"
|
||||
>
|
||||
<input
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Paste your video ID or URL"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<button
|
||||
className="border-start-0"
|
||||
data-testid="inputSaveButton"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
className="rounded-circle text-dark"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`VideoUploader renders without errors 1`] = `
|
||||
exports[`VideoUploader snapshots renders as expected with error message 1`] = `
|
||||
<div>
|
||||
<div>
|
||||
<div
|
||||
className="d-flex flex-column justify-content-center align-items-center p-4 w-100 min-vh-100"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onDragEnter={[Function]}
|
||||
onDragLeave={[Function]}
|
||||
onDragOver={[Function]}
|
||||
onDrop={[Function]}
|
||||
onFocus={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
role="presentation"
|
||||
tabIndex={0}
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-center align-items-center p-4 w-100 min-vh-100"
|
||||
role="presentation"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="d-flex flex-column justify-content-center align-items-center gap-2 text-center min-vh-100 w-100
|
||||
className="d-flex flex-column justify-content-center align-items-center gap-2 text-center min-vh-100 w-100
|
||||
dropzone-middle "
|
||||
>
|
||||
<div
|
||||
class="d-flex justify-content-center align-items-center bg-light rounded-circle file-upload"
|
||||
>
|
||||
<icon
|
||||
class="text-muted"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center gap-1 flex-wrap flex-column pt-5"
|
||||
>
|
||||
<span
|
||||
style="font-size: 20px;"
|
||||
>
|
||||
FormattedMessage
|
||||
</span>
|
||||
<span
|
||||
style="font-size: 12px;"
|
||||
>
|
||||
FormattedMessage
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center mt-3"
|
||||
>
|
||||
<span
|
||||
class="mx-2 text-dark"
|
||||
>
|
||||
OR
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
accept=""
|
||||
data-testid="fileInput"
|
||||
style="display: none;"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex video-id-container"
|
||||
>
|
||||
<div
|
||||
class="d-flex video-id-prompt"
|
||||
className="d-flex justify-content-center align-items-center bg-light rounded-circle file-upload"
|
||||
>
|
||||
<input
|
||||
placeholder="Paste your video ID or URL"
|
||||
type="text"
|
||||
value=""
|
||||
<Icon
|
||||
className="text-muted"
|
||||
/>
|
||||
<button
|
||||
class="border-start-0"
|
||||
data-testid="inputSaveButton"
|
||||
type="button"
|
||||
>
|
||||
<icon
|
||||
class="rounded-circle text-dark"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex align-items-center justify-content-center gap-1 flex-wrap flex-column pt-5"
|
||||
>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "20px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Drag and drop video here or click to upload"
|
||||
description="Display message for Drag and Drop zone"
|
||||
id="VideoUploadEditor.dropVideoFileHere"
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
style={
|
||||
Object {
|
||||
"fontSize": "12px",
|
||||
}
|
||||
}
|
||||
>
|
||||
<FormattedMessage
|
||||
defaultMessage="Upload MP4 or MOV files (5 GB max)"
|
||||
description="Info message for supported formats"
|
||||
id="VideoUploadEditor.uploadInfo"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex align-items-center mt-3"
|
||||
>
|
||||
<span
|
||||
className="mx-2 text-dark"
|
||||
>
|
||||
OR
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
accept=""
|
||||
data-testid="fileInput"
|
||||
multiple={false}
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
style={
|
||||
Object {
|
||||
"display": "none",
|
||||
}
|
||||
}
|
||||
tabIndex={-1}
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="d-flex video-id-container"
|
||||
>
|
||||
<div
|
||||
className="d-flex video-id-prompt"
|
||||
>
|
||||
<input
|
||||
onChange={[Function]}
|
||||
onClick={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
placeholder="Paste your video ID or URL"
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
<button
|
||||
className="border-start-0"
|
||||
data-testid="inputSaveButton"
|
||||
onClick={[Function]}
|
||||
type="button"
|
||||
>
|
||||
<Icon
|
||||
className="rounded-circle text-dark"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`VideoUploaderEdirtor snapshots renders as expected with default behavior 1`] = `
|
||||
<ContextConsumer>
|
||||
<Component />
|
||||
</ContextConsumer>
|
||||
`;
|
||||
|
||||
@@ -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.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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(
|
||||
<IntlProvider locale="en">
|
||||
<VideoUploadEditor {...props} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
const renderUploaderComponent = (props = defaultUploaderProps) => render(
|
||||
<IntlProvider locale="en">
|
||||
<VideoUploader {...props} />
|
||||
</IntlProvider>,
|
||||
);
|
||||
|
||||
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(<VideoUploader {...defaultUploaderProps} />)).toMatchSnapshot();
|
||||
});
|
||||
test('renders as expected with error message', () => {
|
||||
const defaultUploaderPropsWithError = { ...defaultUploaderProps, errorMessages: 'Some Error' };
|
||||
expect(shallow(<VideoUploader {...defaultUploaderPropsWithError} />)).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('VideoUploaderEdirtor', () => {
|
||||
describe('snapshots', () => {
|
||||
test('renders as expected with default behavior', () => {
|
||||
expect(shallow(<VideoUploadEditor {...defaultEditorProps} />)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
expect(mockOnUpload).toHaveBeenCalledWith(file);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user