mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-28 13:09:40 +08:00
test: Update upload test case (#38282)
This commit is contained in:
parent
46c846a34c
commit
00e5ca5ee9
@ -2,12 +2,12 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import type { UploadRequestOption } from 'rc-upload/lib/interface';
|
import type { UploadRequestOption } from 'rc-upload/lib/interface';
|
||||||
import React from 'react';
|
import React, { createRef } from 'react';
|
||||||
import type { RcFile, UploadFile, UploadProps } from '..';
|
import type { RcFile, UploadFile, UploadProps } from '..';
|
||||||
import Upload from '..';
|
import Upload from '..';
|
||||||
import mountTest from '../../../tests/shared/mountTest';
|
import mountTest from '../../../tests/shared/mountTest';
|
||||||
import rtlTest from '../../../tests/shared/rtlTest';
|
import rtlTest from '../../../tests/shared/rtlTest';
|
||||||
import { fireEvent, render, sleep, act } from '../../../tests/utils';
|
import { fireEvent, render, waitFakeTimer, act } from '../../../tests/utils';
|
||||||
import Form from '../../form';
|
import Form from '../../form';
|
||||||
import { resetWarned } from '../../_util/warning';
|
import { resetWarned } from '../../_util/warning';
|
||||||
import { getFileItem, isImageUrl, removeFileItem } from '../utils';
|
import { getFileItem, isImageUrl, removeFileItem } from '../utils';
|
||||||
@ -19,8 +19,17 @@ describe('Upload', () => {
|
|||||||
mountTest(Upload);
|
mountTest(Upload);
|
||||||
rtlTest(Upload);
|
rtlTest(Upload);
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
});
|
||||||
beforeEach(() => setup());
|
beforeEach(() => setup());
|
||||||
afterEach(() => teardown());
|
afterAll(() => {
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
afterEach(() => {
|
||||||
|
jest.clearAllTimers();
|
||||||
|
return teardown();
|
||||||
|
});
|
||||||
|
|
||||||
// Mock for rc-util raf
|
// Mock for rc-util raf
|
||||||
window.requestAnimationFrame = callback => window.setTimeout(callback, 16);
|
window.requestAnimationFrame = callback => window.setTimeout(callback, 16);
|
||||||
@ -29,16 +38,18 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
// https://github.com/react-component/upload/issues/36
|
// https://github.com/react-component/upload/issues/36
|
||||||
it('should get refs inside Upload in componentDidMount', () => {
|
it('should get refs inside Upload in componentDidMount', () => {
|
||||||
let ref: React.ReactInstance;
|
let ref: React.RefObject<HTMLInputElement>;
|
||||||
class App extends React.Component {
|
class App extends React.Component {
|
||||||
|
inputRef = createRef<HTMLInputElement>();
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
ref = this.refs.input;
|
ref = this.inputRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Upload supportServerRender={false}>
|
<Upload supportServerRender={false}>
|
||||||
<input ref="input" />
|
<input ref={this.inputRef} />
|
||||||
</Upload>
|
</Upload>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -48,7 +59,6 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('return promise in beforeUpload', async () => {
|
it('return promise in beforeUpload', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const data = jest.fn();
|
const data = jest.fn();
|
||||||
const done = jest.fn();
|
const done = jest.fn();
|
||||||
const props: UploadProps = {
|
const props: UploadProps = {
|
||||||
@ -74,22 +84,11 @@ describe('Upload', () => {
|
|||||||
fireEvent.change(wrapper.querySelector('input')!, {
|
fireEvent.change(wrapper.querySelector('input')!, {
|
||||||
target: { files: [{ file: 'foo.png' }] },
|
target: { files: [{ file: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
await act(async () => {
|
|
||||||
for (let i = 0; i < 4; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(done).toHaveBeenCalled();
|
expect(done).toHaveBeenCalled();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('beforeUpload can be falsy', async () => {
|
it('beforeUpload can be falsy', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const done = jest.fn();
|
const done = jest.fn();
|
||||||
const props: UploadProps = {
|
const props: UploadProps = {
|
||||||
action: 'http://upload.com',
|
action: 'http://upload.com',
|
||||||
@ -110,18 +109,11 @@ describe('Upload', () => {
|
|||||||
fireEvent.change(wrapper.querySelector('input')!, {
|
fireEvent.change(wrapper.querySelector('input')!, {
|
||||||
target: { files: [{ file: 'foo.png' }] },
|
target: { files: [{ file: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
for (let i = 0; i < 4; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
expect(done).toHaveBeenCalled();
|
expect(done).toHaveBeenCalled();
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('upload promise return file in beforeUpload', async () => {
|
it('upload promise return file in beforeUpload', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const done = jest.fn();
|
const done = jest.fn();
|
||||||
const data = jest.fn();
|
const data = jest.fn();
|
||||||
const props: UploadProps = {
|
const props: UploadProps = {
|
||||||
@ -153,18 +145,9 @@ describe('Upload', () => {
|
|||||||
fireEvent.change(wrapper.querySelector('input')!, {
|
fireEvent.change(wrapper.querySelector('input')!, {
|
||||||
target: { files: [{ file: 'foo.png' }] },
|
target: { files: [{ file: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
await act(async () => {
|
|
||||||
for (let i = 0; i < 4; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(done).toHaveBeenCalled();
|
expect(done).toHaveBeenCalled();
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not stop upload when return value of beforeUpload is false', done => {
|
it('should not stop upload when return value of beforeUpload is false', done => {
|
||||||
@ -298,8 +281,7 @@ describe('Upload', () => {
|
|||||||
expect(wrapper.querySelectorAll('input#upload').length).toBe(0);
|
expect(wrapper.querySelectorAll('input#upload').length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be controlled by fileList', () => {
|
it('should be controlled by fileList', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const fileList = [
|
const fileList = [
|
||||||
{
|
{
|
||||||
uid: '-1',
|
uid: '-1',
|
||||||
@ -312,11 +294,8 @@ describe('Upload', () => {
|
|||||||
const { rerender } = render(<Upload ref={ref} />);
|
const { rerender } = render(<Upload ref={ref} />);
|
||||||
expect(ref.current.fileList).toEqual([]);
|
expect(ref.current.fileList).toEqual([]);
|
||||||
rerender(<Upload ref={ref} fileList={fileList as UploadProps['fileList']} />);
|
rerender(<Upload ref={ref} fileList={fileList as UploadProps['fileList']} />);
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
expect(ref.current.fileList).toEqual(fileList);
|
expect(ref.current.fileList).toEqual(fileList);
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be able to get uid at first', () => {
|
it('should be able to get uid at first', () => {
|
||||||
@ -451,7 +430,7 @@ describe('Upload', () => {
|
|||||||
expect(linkNode?.getAttribute('rel')).toBe('noopener');
|
expect(linkNode?.getAttribute('rel')).toBe('noopener');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not stop remove when return value of onRemove is false', done => {
|
it('should stop remove when return value of onRemove is false', async () => {
|
||||||
const mockRemove = jest.fn(() => false);
|
const mockRemove = jest.fn(() => false);
|
||||||
const props: UploadProps = {
|
const props: UploadProps = {
|
||||||
onRemove: mockRemove,
|
onRemove: mockRemove,
|
||||||
@ -469,12 +448,11 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-delete')!);
|
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-delete')!);
|
||||||
|
|
||||||
setTimeout(() => {
|
await waitFakeTimer();
|
||||||
expect(mockRemove).toHaveBeenCalled();
|
|
||||||
expect(props.fileList).toHaveLength(1);
|
expect(mockRemove).toHaveBeenCalled();
|
||||||
expect(props.fileList?.[0]?.status).toBe('done');
|
expect(props.fileList).toHaveLength(1);
|
||||||
done();
|
expect(props.fileList?.[0]?.status).toBe('done');
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/18902
|
// https://github.com/ant-design/ant-design/issues/18902
|
||||||
@ -504,13 +482,8 @@ describe('Upload', () => {
|
|||||||
);
|
);
|
||||||
fireEvent.click(container.querySelector('div.ant-upload-list-item .anticon-delete')!);
|
fireEvent.click(container.querySelector('div.ant-upload-list-item .anticon-delete')!);
|
||||||
|
|
||||||
// uploadStart is a batch work which we need wait for react act
|
|
||||||
await act(async () => {
|
|
||||||
await Promise.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delay return true for remove
|
// Delay return true for remove
|
||||||
await sleep(100);
|
await waitFakeTimer();
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
await removePromise(true);
|
await removePromise(true);
|
||||||
});
|
});
|
||||||
@ -519,7 +492,7 @@ describe('Upload', () => {
|
|||||||
expect(file.status).toBe('removed');
|
expect(file.status).toBe('removed');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not stop download when return use onDownload', done => {
|
it('should not stop download when return use onDownload', async () => {
|
||||||
const mockRemove = jest.fn(() => false);
|
const mockRemove = jest.fn(() => false);
|
||||||
const props: UploadProps = {
|
const props: UploadProps = {
|
||||||
onRemove: mockRemove,
|
onRemove: mockRemove,
|
||||||
@ -540,11 +513,9 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-download')!);
|
fireEvent.click(wrapper.querySelector('div.ant-upload-list-item .anticon-download')!);
|
||||||
|
|
||||||
setTimeout(() => {
|
await waitFakeTimer();
|
||||||
expect(props.fileList).toHaveLength(1);
|
expect(props.fileList).toHaveLength(1);
|
||||||
expect(props.fileList?.[0]?.status).toBe('done');
|
expect(props.fileList?.[0]?.status).toBe('done');
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/14439
|
// https://github.com/ant-design/ant-design/issues/14439
|
||||||
@ -658,7 +629,6 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/26427
|
// https://github.com/ant-design/ant-design/issues/26427
|
||||||
it('should sync file list with control mode', async () => {
|
it('should sync file list with control mode', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const done = jest.fn();
|
const done = jest.fn();
|
||||||
let callTimes = 0;
|
let callTimes = 0;
|
||||||
|
|
||||||
@ -718,21 +688,9 @@ describe('Upload', () => {
|
|||||||
target: { files: [{ file: 'foo.png' }] },
|
target: { files: [{ file: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
for (let i = 0; i < 3; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
await act(async () => {
|
|
||||||
await Promise.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(done).toHaveBeenCalled();
|
expect(done).toHaveBeenCalled();
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('maxCount', () => {
|
describe('maxCount', () => {
|
||||||
@ -764,7 +722,7 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(20);
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(onChange.mock.calls[0][0].fileList).toHaveLength(1);
|
expect(onChange.mock.calls[0][0].fileList).toHaveLength(1);
|
||||||
expect(onChange.mock.calls[0][0].fileList[0]).toEqual(
|
expect(onChange.mock.calls[0][0].fileList[0]).toEqual(
|
||||||
@ -807,7 +765,7 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep(20);
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(onChange.mock.calls[0][0].fileList).toHaveLength(2);
|
expect(onChange.mock.calls[0][0].fileList).toHaveLength(2);
|
||||||
expect(onChange.mock.calls[0][0].fileList).toEqual([
|
expect(onChange.mock.calls[0][0].fileList).toEqual([
|
||||||
@ -850,7 +808,7 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
const { file } = onChange.mock.calls[0][0];
|
const { file } = onChange.mock.calls[0][0];
|
||||||
const clone = cloneDeep(file);
|
const clone = cloneDeep(file);
|
||||||
@ -875,6 +833,8 @@ describe('Upload', () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const image = cloneDeep(fileList[0]);
|
||||||
|
|
||||||
const frozenFileList = fileList.map(Object.freeze);
|
const frozenFileList = fileList.map(Object.freeze);
|
||||||
|
|
||||||
const { container: wrapper } = render(
|
const { container: wrapper } = render(
|
||||||
@ -884,11 +844,10 @@ describe('Upload', () => {
|
|||||||
fireEvent.click(rmBtn[rmBtn.length - 1]);
|
fireEvent.click(rmBtn[rmBtn.length - 1]);
|
||||||
|
|
||||||
// Wait for Upload async remove
|
// Wait for Upload async remove
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
await sleep();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
expect(image).toEqual(frozenFileList[0]);
|
||||||
|
});
|
||||||
// https://github.com/ant-design/ant-design/issues/30390
|
// https://github.com/ant-design/ant-design/issues/30390
|
||||||
// IE11 Does not support the File constructor
|
// IE11 Does not support the File constructor
|
||||||
it('should not break in IE if beforeUpload returns false', async () => {
|
it('should not break in IE if beforeUpload returns false', async () => {
|
||||||
@ -906,7 +865,7 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// React 18 is async now
|
// React 18 is async now
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(onChange.mock.calls[0][0].fileList).toHaveLength(1);
|
expect(onChange.mock.calls[0][0].fileList).toHaveLength(1);
|
||||||
spyIE.mockRestore();
|
spyIE.mockRestore();
|
||||||
@ -914,8 +873,6 @@ describe('Upload', () => {
|
|||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/33819
|
// https://github.com/ant-design/ant-design/issues/33819
|
||||||
it('should show the animation of the upload children leaving when the upload children becomes null', async () => {
|
it('should show the animation of the upload children leaving when the upload children becomes null', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const { container, rerender } = render(
|
const { container, rerender } = render(
|
||||||
<Upload listType="picture-card">
|
<Upload listType="picture-card">
|
||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
@ -931,16 +888,12 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Motion leave status change: start > active
|
// Motion leave status change: start > active
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
fireEvent.animationEnd(container.querySelector('.ant-upload-select-picture-card')!);
|
fireEvent.animationEnd(container.querySelector('.ant-upload-select-picture-card')!);
|
||||||
expect(container.querySelector('.ant-upload-select-picture-card')).not.toHaveClass(
|
expect(container.querySelector('.ant-upload-select-picture-card')).not.toHaveClass(
|
||||||
'ant-upload-animate-inline-leave-start',
|
'ant-upload-animate-inline-leave-start',
|
||||||
);
|
);
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('<Upload /> should pass <UploadList /> prefixCls', async () => {
|
it('<Upload /> should pass <UploadList /> prefixCls', async () => {
|
||||||
@ -978,9 +931,8 @@ describe('Upload', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// React 18 is async now
|
// React 18 is async now
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
await sleep();
|
|
||||||
});
|
|
||||||
onChange.mockReset();
|
onChange.mockReset();
|
||||||
|
|
||||||
// Processing
|
// Processing
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Upload from '..';
|
import Upload from '..';
|
||||||
import { fireEvent, render, sleep, waitFor, act } from '../../../tests/utils';
|
import { act, fireEvent, render, waitFakeTimer, waitFor } from '../../../tests/utils';
|
||||||
import Form from '../../form';
|
import Form from '../../form';
|
||||||
import UploadList from '../UploadList';
|
import UploadList from '../UploadList';
|
||||||
import { previewImage } from '../utils';
|
import { previewImage } from '../utils';
|
||||||
@ -54,10 +54,15 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
// HTMLCanvasElement.prototype
|
// HTMLCanvasElement.prototype
|
||||||
|
|
||||||
beforeEach(() => setup());
|
beforeEach(() => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
return setup();
|
||||||
|
});
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
teardown();
|
teardown();
|
||||||
drawImageCallback = null;
|
drawImageCallback = null;
|
||||||
|
jest.clearAllTimers();
|
||||||
|
jest.useRealTimers();
|
||||||
});
|
});
|
||||||
|
|
||||||
let open: jest.MockInstance<any, any[]>;
|
let open: jest.MockInstance<any, any[]>;
|
||||||
@ -109,8 +114,6 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/7269
|
// https://github.com/ant-design/ant-design/issues/7269
|
||||||
it('should remove correct item when uid is 0', async () => {
|
it('should remove correct item when uid is 0', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
{
|
{
|
||||||
uid: '0',
|
uid: '0',
|
||||||
@ -138,36 +141,22 @@ describe('Upload List', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Upload use Promise to wait remove action. Let's wait this also.
|
// Upload use Promise to wait remove action. Let's wait this also.
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
for (let i = 0; i < 10; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Progress motion to active
|
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Progress motion to done
|
// Progress motion to done
|
||||||
// React 17 will reach deadline, so we need check if already done
|
// React 17 will reach deadline, so we need check if already done
|
||||||
if (container.querySelector('.ant-upload-animate-leave-active')) {
|
if (container.querySelector('.ant-upload-animate-leave-active')) {
|
||||||
fireEvent.animationEnd(container.querySelector('.ant-upload-animate-leave-active')!);
|
fireEvent.animationEnd(container.querySelector('.ant-upload-animate-leave-active')!);
|
||||||
}
|
}
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
await waitFakeTimer();
|
||||||
});
|
|
||||||
|
|
||||||
expect(container.querySelectorAll('.ant-upload-list-text-container')).toHaveLength(1);
|
expect(container.querySelectorAll('.ant-upload-list-text-container')).toHaveLength(1);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be uploading when upload a file', async () => {
|
it('should be uploading when upload a file', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const done = jest.fn();
|
const done = jest.fn();
|
||||||
let wrapper: ReturnType<typeof render>;
|
let wrapper: ReturnType<typeof render>;
|
||||||
let latestFileList: UploadFile<any>[] | null = null;
|
let latestFileList: UploadFile<any>[] | null = null;
|
||||||
@ -195,23 +184,14 @@ describe('Upload List', () => {
|
|||||||
fireEvent.change(wrapper.container.querySelector('input')!, {
|
fireEvent.change(wrapper.container.querySelector('input')!, {
|
||||||
target: { files: [{ name: 'foo.png' }] },
|
target: { files: [{ name: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
await Promise.resolve();
|
|
||||||
await Promise.resolve();
|
|
||||||
});
|
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(done).toHaveBeenCalled();
|
expect(done).toHaveBeenCalled();
|
||||||
|
|
||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handle error', async () => {
|
it('handle error', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -231,14 +211,9 @@ describe('Upload List', () => {
|
|||||||
target: { files: [{ name: 'foo.png' }] },
|
target: { files: [{ name: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
|
|
||||||
await act(async () => {
|
await waitFakeTimer();
|
||||||
await Promise.resolve();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Wait twice since `errorRequest` also use timeout for mock
|
// Wait twice since `errorRequest` also use timeout for mock
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(onChange).toHaveBeenLastCalledWith(
|
expect(onChange).toHaveBeenLastCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -249,21 +224,15 @@ describe('Upload List', () => {
|
|||||||
fireEvent.animationEnd(wrapper.querySelector('.ant-upload-animate-appear-active')!);
|
fireEvent.animationEnd(wrapper.querySelector('.ant-upload-animate-appear-active')!);
|
||||||
}
|
}
|
||||||
|
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
expect(wrapper.firstChild).toMatchSnapshot();
|
expect(wrapper.firstChild).toMatchSnapshot();
|
||||||
|
|
||||||
// Error message
|
// Error message
|
||||||
fireEvent.mouseEnter(wrapper.querySelector('.ant-upload-list-item')!);
|
fireEvent.mouseEnter(wrapper.querySelector('.ant-upload-list-item')!);
|
||||||
|
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(baseElement.querySelector('.ant-tooltip')).not.toHaveClass('.ant-tooltip-hidden');
|
expect(baseElement.querySelector('.ant-tooltip')).not.toHaveClass('.ant-tooltip-hidden');
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -285,7 +254,7 @@ describe('Upload List', () => {
|
|||||||
target: { files: [{ name: 'foo.png' }] },
|
target: { files: [{ name: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(ref.current.fileList.length).toBe(fileList.length + 1);
|
expect(ref.current.fileList.length).toBe(fileList.length + 1);
|
||||||
expect(handleChange.mock.calls[0][0].fileList).toHaveLength(3);
|
expect(handleChange.mock.calls[0][0].fileList).toHaveLength(3);
|
||||||
@ -381,8 +350,8 @@ describe('Upload List', () => {
|
|||||||
expect(handleRemove).toHaveBeenCalledWith(fileList[0]);
|
expect(handleRemove).toHaveBeenCalledWith(fileList[0]);
|
||||||
fireEvent.click(wrapper.querySelectorAll('.anticon-delete')[1]);
|
fireEvent.click(wrapper.querySelectorAll('.anticon-delete')[1]);
|
||||||
expect(handleRemove).toHaveBeenCalledWith(fileList[1]);
|
expect(handleRemove).toHaveBeenCalledWith(fileList[1]);
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
expect(handleChange.mock.calls.length).toBe(2);
|
expect(handleChange).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
@ -409,6 +378,7 @@ describe('Upload List', () => {
|
|||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
fireEvent.click(wrapper.querySelectorAll('.anticon-download')[0]);
|
fireEvent.click(wrapper.querySelectorAll('.anticon-download')[0]);
|
||||||
|
expect(handleDownload).toHaveBeenCalled();
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
@ -467,7 +437,7 @@ describe('Upload List', () => {
|
|||||||
<button type="button">upload</button>
|
<button type="button">upload</button>
|
||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(ref.current.fileList[2].thumbUrl).not.toBe(undefined);
|
expect(ref.current.fileList[2].thumbUrl).not.toBe(undefined);
|
||||||
expect(onDrawImage).toHaveBeenCalled();
|
expect(onDrawImage).toHaveBeenCalled();
|
||||||
@ -559,8 +529,6 @@ describe('Upload List', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('not crash when uploading not provides percent', async () => {
|
it('not crash when uploading not provides percent', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const { unmount } = render(
|
const { unmount } = render(
|
||||||
<Upload
|
<Upload
|
||||||
listType="picture"
|
listType="picture"
|
||||||
@ -570,13 +538,9 @@ describe('Upload List', () => {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
|
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should support showRemoveIcon and showPreviewIcon', () => {
|
it('should support showRemoveIcon and showPreviewIcon', () => {
|
||||||
@ -640,8 +604,8 @@ describe('Upload List', () => {
|
|||||||
fireEvent.click(wrapper.querySelectorAll('.custom-delete')[1]);
|
fireEvent.click(wrapper.querySelectorAll('.custom-delete')[1]);
|
||||||
expect(handleRemove).toHaveBeenCalledWith(fileList[1]);
|
expect(handleRemove).toHaveBeenCalledWith(fileList[1]);
|
||||||
expect(myClick).toHaveBeenCalled();
|
expect(myClick).toHaveBeenCalled();
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
expect(handleChange.mock.calls.length).toBe(2);
|
expect(handleChange).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
@ -718,11 +682,9 @@ describe('Upload List', () => {
|
|||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
validator(_, value, callback) {
|
async validator(_, value) {
|
||||||
if (!value || value.length === 0) {
|
if (!value || value.length === 0) {
|
||||||
callback('file required');
|
throw new Error('file required');
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -739,7 +701,7 @@ describe('Upload List', () => {
|
|||||||
const { container, unmount } = render(<TestForm />);
|
const { container, unmount } = render(<TestForm />);
|
||||||
|
|
||||||
fireEvent.submit(container.querySelector('form')!);
|
fireEvent.submit(container.querySelector('form')!);
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
expect(formRef!.getFieldError(['file'])).toEqual(['file required']);
|
expect(formRef!.getFieldError(['file'])).toEqual(['file required']);
|
||||||
|
|
||||||
fireEvent.change(container.querySelector('input')!, {
|
fireEvent.change(container.querySelector('input')!, {
|
||||||
@ -747,7 +709,7 @@ describe('Upload List', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
fireEvent.submit(container.querySelector('form')!);
|
fireEvent.submit(container.querySelector('form')!);
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
expect(formRef!.getFieldError(['file'])).toEqual([]);
|
expect(formRef!.getFieldError(['file'])).toEqual([]);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
@ -795,7 +757,8 @@ describe('Upload List', () => {
|
|||||||
target: { files: [{ name: 'foo.png' }] },
|
target: { files: [{ name: 'foo.png' }] },
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(wrapper.querySelector('.ant-upload-list-item-thumbnail')?.getAttribute('href')).toBe(
|
expect(wrapper.querySelector('.ant-upload-list-item-thumbnail')?.getAttribute('href')).toBe(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
@ -1005,7 +968,7 @@ describe('Upload List', () => {
|
|||||||
</Upload>,
|
</Upload>,
|
||||||
);
|
);
|
||||||
expect(previewFile).toHaveBeenCalledWith(file.originFileObj);
|
expect(previewFile).toHaveBeenCalledWith(file.originFileObj);
|
||||||
await sleep(100);
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
wrapper.querySelector('.ant-upload-list-item-thumbnail img')?.getAttribute('src'),
|
wrapper.querySelector('.ant-upload-list-item-thumbnail img')?.getAttribute('src'),
|
||||||
@ -1039,7 +1002,6 @@ describe('Upload List', () => {
|
|||||||
);
|
);
|
||||||
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
||||||
expect(imgNode.length).toBe(2);
|
expect(imgNode.length).toBe(2);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
it('should render <img /> when custom imageUrl return true', () => {
|
it('should render <img /> when custom imageUrl return true', () => {
|
||||||
@ -1056,7 +1018,6 @@ describe('Upload List', () => {
|
|||||||
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
||||||
expect(isImageUrl).toHaveBeenCalled();
|
expect(isImageUrl).toHaveBeenCalled();
|
||||||
expect(imgNode.length).toBe(3);
|
expect(imgNode.length).toBe(3);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
it('should not render <img /> when custom imageUrl return false', () => {
|
it('should not render <img /> when custom imageUrl return false', () => {
|
||||||
@ -1073,31 +1034,11 @@ describe('Upload List', () => {
|
|||||||
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
const imgNode = wrapper.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
||||||
expect(isImageUrl).toHaveBeenCalled();
|
expect(isImageUrl).toHaveBeenCalled();
|
||||||
expect(imgNode.length).toBe(0);
|
expect(imgNode.length).toBe(0);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('thumbUrl support for non-image', () => {
|
describe('thumbUrl support for non-image', () => {
|
||||||
beforeEach(() => {
|
|
||||||
jest.useFakeTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
const nonImageFile = new File([''], 'foo.7z', { type: 'application/x-7z-compressed' });
|
const nonImageFile = new File([''], 'foo.7z', { type: 'application/x-7z-compressed' });
|
||||||
|
|
||||||
/** Wait for a long promise since `rc-util` internal has at least 3 promise wait */
|
|
||||||
async function waitPromise() {
|
|
||||||
/* eslint-disable no-await-in-loop */
|
|
||||||
for (let i = 0; i < 10; i += 1) {
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
/* eslint-enable */
|
|
||||||
}
|
|
||||||
|
|
||||||
it('should render <img /> when upload non-image file and configure thumbUrl in onChange', async () => {
|
it('should render <img /> when upload non-image file and configure thumbUrl in onChange', async () => {
|
||||||
const thumbUrl =
|
const thumbUrl =
|
||||||
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png';
|
'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png';
|
||||||
@ -1140,20 +1081,12 @@ describe('Upload List', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Wait for `rc-upload` process file
|
// Wait for `rc-upload` process file
|
||||||
await waitPromise();
|
await waitFakeTimer();
|
||||||
|
|
||||||
// Wait for mock request finish request
|
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Basic called times
|
// Basic called times
|
||||||
expect(onChange).toHaveBeenCalled();
|
expect(onChange).toHaveBeenCalled();
|
||||||
|
|
||||||
// Check for images
|
// Check for images
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
const afterImgNode = wrapper.container.querySelectorAll(
|
const afterImgNode = wrapper.container.querySelectorAll(
|
||||||
'.ant-upload-list-item-thumbnail img',
|
'.ant-upload-list-item-thumbnail img',
|
||||||
);
|
);
|
||||||
@ -1162,29 +1095,25 @@ describe('Upload List', () => {
|
|||||||
wrapper.unmount();
|
wrapper.unmount();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not render <img /> when upload non-image file without thumbUrl in onChange', done => {
|
it('should not render <img /> when upload non-image file without thumbUrl in onChange', async () => {
|
||||||
(global as any).testName =
|
(global as any).testName =
|
||||||
'should not render <img /> when upload non-image file without thumbUrl in onChange';
|
'should not render <img /> when upload non-image file without thumbUrl in onChange';
|
||||||
let wrapper: ReturnType<typeof render>;
|
let wrapper: ReturnType<typeof render>;
|
||||||
const onChange: UploadProps['onChange'] = async ({ fileList: files }) => {
|
const onChange = jest.fn<void, Record<'fileList', UploadProps['fileList']>[]>(
|
||||||
wrapper.rerender(
|
({ fileList: files }) => {
|
||||||
<Upload
|
wrapper.rerender(
|
||||||
action="http://jsonplaceholder.typicode.com/posts/"
|
<Upload
|
||||||
listType="picture-card"
|
action="http://jsonplaceholder.typicode.com/posts/"
|
||||||
fileList={files}
|
listType="picture-card"
|
||||||
onChange={onChange}
|
fileList={files}
|
||||||
customRequest={successRequest}
|
onChange={onChange}
|
||||||
>
|
customRequest={successRequest}
|
||||||
<button type="button">upload</button>
|
>
|
||||||
</Upload>,
|
<button type="button">upload</button>
|
||||||
);
|
</Upload>,
|
||||||
|
);
|
||||||
await sleep();
|
},
|
||||||
const imgNode = wrapper.container.querySelectorAll('.ant-upload-list-item-thumbnail img');
|
);
|
||||||
expect(imgNode.length).toBe(0);
|
|
||||||
|
|
||||||
done();
|
|
||||||
};
|
|
||||||
wrapper = render(
|
wrapper = render(
|
||||||
<Upload
|
<Upload
|
||||||
action="http://jsonplaceholder.typicode.com/posts/"
|
action="http://jsonplaceholder.typicode.com/posts/"
|
||||||
@ -1201,10 +1130,17 @@ describe('Upload List', () => {
|
|||||||
fireEvent.change(wrapper.container.querySelector('input')!, {
|
fireEvent.change(wrapper.container.querySelector('input')!, {
|
||||||
target: { files: [nonImageFile] },
|
target: { files: [nonImageFile] },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
await waitFakeTimer();
|
||||||
|
expect(onChange).toHaveBeenCalled();
|
||||||
|
expect(wrapper.container.querySelectorAll('.ant-upload-list-item-thumbnail img').length).toBe(
|
||||||
|
0,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('[deprecated] should support transformFile', done => {
|
it('[deprecated] should support transformFile', done => {
|
||||||
|
jest.useRealTimers();
|
||||||
let wrapper: ReturnType<typeof render>;
|
let wrapper: ReturnType<typeof render>;
|
||||||
let lastFile: UploadFile;
|
let lastFile: UploadFile;
|
||||||
|
|
||||||
@ -1281,8 +1217,6 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/26536
|
// https://github.com/ant-design/ant-design/issues/26536
|
||||||
it('multiple file upload should keep the internal fileList async', async () => {
|
it('multiple file upload should keep the internal fileList async', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const uploadRef = React.createRef<any>();
|
const uploadRef = React.createRef<any>();
|
||||||
|
|
||||||
const MyUpload: React.FC = () => {
|
const MyUpload: React.FC = () => {
|
||||||
@ -1320,14 +1254,10 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
expect(uploadRef.current.fileList).toHaveLength(fileNames.length);
|
expect(uploadRef.current.fileList).toHaveLength(fileNames.length);
|
||||||
|
|
||||||
act(() => {
|
await waitFakeTimer();
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
expect(uploadRef.current.fileList).toHaveLength(fileNames.length);
|
expect(uploadRef.current.fileList).toHaveLength(fileNames.length);
|
||||||
|
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('itemRender', () => {
|
it('itemRender', () => {
|
||||||
@ -1384,13 +1314,11 @@ describe('Upload List', () => {
|
|||||||
const beforeUpload = jest.fn(() => Upload.LIST_IGNORE);
|
const beforeUpload = jest.fn(() => Upload.LIST_IGNORE);
|
||||||
const { container: wrapper, unmount } = render(<Upload beforeUpload={beforeUpload} />);
|
const { container: wrapper, unmount } = render(<Upload beforeUpload={beforeUpload} />);
|
||||||
|
|
||||||
await act(() => {
|
fireEvent.change(wrapper.querySelector('input')!, {
|
||||||
fireEvent.change(wrapper.querySelector('input')!, {
|
target: { files: [{ file: 'foo.png' }] },
|
||||||
target: { files: [{ file: 'foo.png' }] },
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await sleep();
|
await waitFakeTimer();
|
||||||
|
|
||||||
expect(beforeUpload).toHaveBeenCalled();
|
expect(beforeUpload).toHaveBeenCalled();
|
||||||
expect(wrapper.querySelectorAll('.ant-upload-list-text-container')).toHaveLength(0);
|
expect(wrapper.querySelectorAll('.ant-upload-list-text-container')).toHaveLength(0);
|
||||||
@ -1585,8 +1513,6 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
// https://github.com/ant-design/ant-design/issues/36286
|
// https://github.com/ant-design/ant-design/issues/36286
|
||||||
it('remove should keep origin className', async () => {
|
it('remove should keep origin className', async () => {
|
||||||
jest.useFakeTimers();
|
|
||||||
|
|
||||||
const onChange = jest.fn();
|
const onChange = jest.fn();
|
||||||
const list = [
|
const list = [
|
||||||
{
|
{
|
||||||
@ -1605,15 +1531,7 @@ describe('Upload List', () => {
|
|||||||
|
|
||||||
fireEvent.click(container.querySelector('.anticon-delete')!);
|
fireEvent.click(container.querySelector('.anticon-delete')!);
|
||||||
|
|
||||||
// Wait for Upload sync
|
await waitFakeTimer();
|
||||||
for (let i = 0; i < 10; i += 1) {
|
|
||||||
// eslint-disable-next-line no-await-in-loop
|
|
||||||
await Promise.resolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
act(() => {
|
|
||||||
jest.runAllTimers();
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(onChange).toHaveBeenCalledWith(
|
expect(onChange).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -1622,7 +1540,5 @@ describe('Upload List', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
expect(container.querySelector('.ant-upload-list-item-error')).toBeTruthy();
|
expect(container.querySelector('.ant-upload-list-item-error')).toBeTruthy();
|
||||||
|
|
||||||
jest.useRealTimers();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user