diff --git a/src/uploader/test/__snapshots__/index.legacy.js.snap b/src/uploader/test/__snapshots__/index.legacy.js.snap
deleted file mode 100644
index 6421e923c..000000000
--- a/src/uploader/test/__snapshots__/index.legacy.js.snap
+++ /dev/null
@@ -1,173 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`delete preview image 1`] = `
-
-`;
-
-exports[`disable preview image 1`] = `
-
-`;
-
-exports[`file message should be reactive 1`] = `
-
-
-
-

-
-
-
-
-
-
-
-
-
-`;
-
-exports[`image-fit prop 1`] = `
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`max-count prop 1`] = `
-
-
-
-

-
-
-
-
-
-
-
-
-`;
-
-exports[`preview-cover slot 1`] = `
-
-
-
-

-
-
-
url: https://img.yzcdn.cn/vant/cat.jpeg, index: 0
-
-
-
-
-
-

-
-
-
url: https://img.yzcdn.cn/vant/cat.jpeg, index: 1
-
-
-
-
-
-
-
-
-`;
-
-exports[`preview-size prop 1`] = `
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`render preview image 1`] = `
-
-
-
-

-
-
-
-
-
-
-
-
-
-
https://img.yzcdn.cn/vant/test.pdf
-
-
-
-
-
-
-

-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`render upload-text 1`] = `
-
-`;
-
-exports[`upload-icon prop 1`] = `
-
-`;
diff --git a/src/uploader/test/__snapshots__/index.spec.ts.snap b/src/uploader/test/__snapshots__/index.spec.ts.snap
new file mode 100644
index 000000000..52809c25f
--- /dev/null
+++ b/src/uploader/test/__snapshots__/index.spec.ts.snap
@@ -0,0 +1,282 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`delete preview image 1`] = `
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`disable preview image 1`] = `
+
+`;
+
+exports[`disable preview image 2`] = `
+
+`;
+
+exports[`file message should be reactive 1`] = `
+
+`;
+
+exports[`image-fit prop 1`] = `
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`preview-cover slot 1`] = `
+
+
+
+
+

+
+
+
+
+
+ Custom Preview Cover
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+ Custom Preview Cover
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`preview-size prop 1`] = `
+
+`;
+
+exports[`render preview image 1`] = `
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ https://img01.yzcdn.cn/vant/test.pdf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
+exports[`upload-icon prop 1`] = `
+
+`;
diff --git a/src/uploader/test/index.legacy.js b/src/uploader/test/index.legacy.js
deleted file mode 100644
index 9ed3bfee4..000000000
--- a/src/uploader/test/index.legacy.js
+++ /dev/null
@@ -1,539 +0,0 @@
-import { Uploader } from '..';
-import { mount, later, triggerDrag } from '../../../test';
-
-window.File = function () {
- this.size = 10000;
-};
-
-const mockFileDataUrl = 'data:image/test';
-const mockFile = new File([], 'test.jpg');
-const file = { target: { files: [mockFile] } };
-const multiFile = { target: { files: [mockFile, mockFile] } };
-const IMAGE = 'https://img.yzcdn.cn/vant/cat.jpeg';
-const PDF = 'https://img.yzcdn.cn/vant/test.pdf';
-
-window.FileReader = function () {
- this.readAsText = function () {
- this.onload &&
- this.onload({
- target: {
- result: mockFileDataUrl,
- },
- });
- };
- this.readAsDataURL = this.readAsText;
-};
-
-test('disabled', () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- disabled: true,
- afterRead,
- },
- });
-
- wrapper.vm.onChange(file);
- expect(afterRead).toHaveBeenCalledTimes(0);
-});
-
-test('result-type as text', (done) => {
- const wrapper = mount(Uploader, {
- props: {
- resultType: 'text',
- afterRead: (readFile) => {
- expect(readFile.content).toEqual(mockFileDataUrl);
- done();
- },
- },
- });
-
- wrapper.vm.onChange(file);
-});
-
-test('result-type as file', (done) => {
- const wrapper = mount(Uploader, {
- props: {
- resultType: 'file',
- afterRead: (readFile) => {
- expect(readFile.file).toBeTruthy();
- expect(readFile.content).toBeFalsy();
- done();
- },
- },
- });
-
- wrapper.vm.onChange(file);
-});
-
-test('set input name', (done) => {
- const wrapper = mount(Uploader, {
- props: {
- name: 'uploader',
- beforeRead: (readFile, detail) => {
- expect(detail.name).toEqual('uploader');
- return true;
- },
- afterRead: (readFile, detail) => {
- expect(detail.name).toEqual('uploader');
- done();
- },
- },
- });
-
- wrapper.vm.onChange(file);
-});
-
-test('unknown resultType', () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- resultType: 'xxxx',
- afterRead,
- },
- });
- wrapper.vm.onChange(file);
- expect(afterRead).toHaveBeenCalledTimes(0);
-});
-
-test('before read return false', () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- beforeRead: () => false,
- afterRead,
- },
- });
-
- const input = wrapper.find('input');
-
- wrapper.vm.onChange(file);
- expect(afterRead).toHaveBeenCalledTimes(0);
- expect(input.element.value).toEqual('');
-});
-
-test('before read return promise and resolve', async () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- beforeRead: () =>
- new Promise((resolve) => {
- resolve(file);
- }),
- afterRead,
- },
- });
-
- wrapper.vm.onChange(file);
-
- await later();
- expect(afterRead).toHaveBeenCalledTimes(1);
-});
-
-test('before read return promise and resolve no value', async () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- beforeRead: () =>
- new Promise((resolve) => {
- resolve();
- }),
- afterRead,
- },
- });
-
- const input = wrapper.find('input');
- wrapper.vm.onChange(file);
- await later();
- expect(afterRead).toHaveBeenCalledTimes(1);
- expect(input.element.value).toEqual('');
-});
-
-test('before read return promise and reject', async () => {
- const afterRead = jest.fn();
- const wrapper = mount(Uploader, {
- props: {
- beforeRead: () =>
- new Promise((resolve, reject) => {
- reject();
- }),
- afterRead,
- },
- });
-
- const input = wrapper.find('input');
- wrapper.vm.onChange(file);
-
- await later();
- expect(afterRead).toHaveBeenCalledTimes(0);
- expect(input.element.value).toEqual('');
-});
-
-test('file size overlimit', async () => {
- const wrapper = mount(Uploader, {
- props: {
- maxSize: 1,
- },
- });
- wrapper.vm.onChange(file);
- wrapper.vm.onChange(multiFile);
-
- await later();
- expect(wrapper.emitted('oversize')[0]).toBeTruthy();
- expect(wrapper.emitted('oversize')[1]).toBeTruthy();
-
- wrapper.vm.maxSize = 100000;
- wrapper.vm.onChange(multiFile);
-
- await later();
- expect(wrapper.emitted('oversize')[2]).toBeFalsy();
-});
-
-test('render upload-text', () => {
- const wrapper = mount(Uploader, {
- props: {
- uploadText: 'Text',
- },
- });
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('render preview image', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [
- { url: 'https://img.yzcdn.cn/vant/cat.jpeg' },
- { url: 'https://img.yzcdn.cn/vant/test.pdf' },
- { file: { name: 'test.pdf' } },
- ],
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.vm.onChange(file);
- await later();
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('image-fit prop', () => {
- const wrapper = mount(Uploader, {
- props: {
- imageFit: 'contain',
- fileList: [{ url: 'https://img.yzcdn.cn/vant/cat.jpeg' }],
- },
- });
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('upload-icon prop', () => {
- const wrapper = mount(Uploader, {
- props: {
- uploadIcon: 'add',
- },
- });
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('disable preview image', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [],
- previewImage: false,
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.vm.onChange(file);
- await later();
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('max-count prop', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [],
- maxCount: 1,
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.vm.onChange(multiFile);
- await later();
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('preview-size prop', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [],
- previewSize: 30,
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.vm.onChange(file);
- await later();
-
- expect(wrapper.html()).toMatchSnapshot();
-});
-
-test('deletable prop', () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- },
- });
-
- expect(wrapper.find('.van-uploader__preview-delete').element).toBeTruthy();
-
- wrapper.setProps({ deletable: false });
- expect(wrapper.find('.van-uploader__preview-delete').element).toBeFalsy();
-});
-
-test('delete preview image', () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- previewSize: 30,
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.find('.van-uploader__preview-delete').trigger('click');
- expect(wrapper.vm.fileList.length).toEqual(0);
-
- expect(wrapper.html()).toMatchSnapshot();
- expect(wrapper.emitted('delete')[0]).toBeTruthy();
-});
-
-test('before-delete prop return false', () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- beforeDelete: () => false,
- },
- });
-
- wrapper.find('.van-uploader__preview-delete').trigger('click');
- expect(wrapper.emitted('delete')).toBeFalsy();
-});
-
-test('before-delete prop return true', () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- beforeDelete: () => true,
- },
- });
-
- wrapper.find('.van-uploader__preview-delete').trigger('click');
- expect(wrapper.emitted('delete')).toBeTruthy();
-});
-
-test('before-delete prop resolved', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- beforeDelete: () => new Promise((resolve) => resolve()),
- },
- });
-
- wrapper.find('.van-uploader__preview-delete').trigger('click');
- await later();
- expect(wrapper.emitted('delete')).toBeTruthy();
-});
-
-test('before-delete prop rejected', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- beforeDelete: () => new Promise((resolve, reject) => reject()),
- },
- });
-
- wrapper.find('.van-uploader__preview-delete').trigger('click');
- await later();
- expect(wrapper.emitted('delete')).toBeFalsy();
-});
-
-test('click to preview image', async () => {
- const wrapper = mount(Uploader, {
- props: {
- previewFullImage: false,
- fileList: [{ url: IMAGE }, { url: PDF }],
- },
- });
-
- wrapper.find('.van-image').trigger('click');
- const imagePreviewNode = document.querySelector('.van-image-preview');
- expect(imagePreviewNode).toBeFalsy();
-
- wrapper.setProps({ previewFullImage: true });
- wrapper.find('.van-image').trigger('click');
-
- await later();
-
- const imagePreviewNode2 = document.querySelector('.van-image-preview');
- const images = imagePreviewNode2.querySelectorAll(
- '.van-image-preview__image'
- );
- expect(images.length).toEqual(1);
-});
-
-test('preview-options prop', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- previewOptions: {
- closeable: true,
- },
- },
- });
-
- wrapper.find('.van-image').trigger('click');
- await later();
-
- const closeIcon = document.querySelectorAll('.van-image-preview__close-icon');
- expect(closeIcon.length).toEqual(1);
-});
-
-test('closeImagePreview method', () => {
- const close = jest.fn();
- const wrapper = mount(Uploader, {
- mocks: {
- imagePreview: {
- close,
- },
- },
- });
-
- wrapper.vm.closeImagePreview();
- expect(close).toHaveBeenCalledTimes(1);
-
- // should not throw error
- const wrapper2 = mount(Uploader);
- wrapper2.vm.closeImagePreview();
-});
-
-test('click-preview event', () => {
- const wrapper = mount(Uploader, {
- props: {
- previewFullImage: false,
- fileList: [{ url: IMAGE }, { url: PDF }],
- },
- });
-
- wrapper.find('.van-image').trigger('click');
- expect(wrapper.emitted('click-preview')[0][0]).toEqual({ url: IMAGE });
- expect(wrapper.emitted('click-preview')[0][1]).toEqual({
- name: '',
- index: 0,
- });
-});
-
-test('close-preview event', async () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }],
- },
- });
-
- wrapper.find('.van-image').trigger('click');
-
- const preview = document.querySelector('.van-image-preview');
- const swipe = preview.querySelector('.van-swipe-item');
- triggerDrag(swipe, 0, 0);
-
- await later(300);
- expect(wrapper.emitted('close-preview')).toBeTruthy();
-});
-
-test('show-upload prop', () => {
- const wrapper = mount(Uploader);
- expect(wrapper.contains('.van-uploader__upload')).toBeTruthy();
- wrapper.setProps({ showUpload: false });
- expect(wrapper.contains('.van-uploader__upload')).toBeFalsy();
-});
-
-test('file message should be reactive', (done) => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [],
- afterRead(file) {
- file.status = 'uploading';
- file.message = 1;
- setTimeout(() => {
- file.message = 2;
- expect(wrapper.html()).toMatchSnapshot();
- done();
- });
- },
- },
- listeners: {
- input(fileList) {
- wrapper.setProps({ fileList });
- },
- },
- });
-
- wrapper.vm.onChange(file);
-});
-
-test('multiFile upload filter max-size file', async () => {
- const SmallFile = function () {
- this.size = 100;
- };
- const multiFiles = {
- target: { files: [mockFile, new SmallFile([], 'small-test.jpg')] },
- };
-
- const wrapper = mount(Uploader, {
- props: {
- maxSize: 1000,
- },
- });
- wrapper.vm.onChange(multiFiles);
-
- await later();
-
- expect(wrapper.emitted('oversize')[0]).toBeTruthy();
-});
-
-test('preview-cover slot', () => {
- const wrapper = mount(Uploader, {
- props: {
- fileList: [{ url: IMAGE }, { url: IMAGE }],
- },
- slots: {
- 'preview-cover': (item) => `url: ${item.url}, index: ${item.index}`,
- },
- });
-
- expect(wrapper.html()).toMatchSnapshot();
-});
diff --git a/src/uploader/test/index.spec.ts b/src/uploader/test/index.spec.ts
new file mode 100644
index 000000000..b255ef725
--- /dev/null
+++ b/src/uploader/test/index.spec.ts
@@ -0,0 +1,574 @@
+import Uploader, { UploaderFileListItem } from '..';
+import { mount, later, triggerDrag } from '../../../test';
+import { nextTick } from 'vue';
+
+const mockFileDataUrl = 'data:image/test';
+const mockFile = new File([new ArrayBuffer(10000)], 'test.jpg');
+const IMAGE = 'https://img01.yzcdn.cn/vant/cat.jpeg';
+const PDF = 'https://img01.yzcdn.cn/vant/test.pdf';
+
+(window.FileReader as any) = function (this: any) {
+ (this as any).readAsText = function () {
+ this.onload &&
+ this.onload({
+ target: {
+ result: mockFileDataUrl,
+ },
+ });
+ };
+ this.readAsDataURL = this.readAsText;
+};
+
+test('disabled', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ disabled: true,
+ afterRead,
+ },
+ });
+
+ await later();
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(0);
+});
+
+test('result-type as text', async (done) => {
+ const wrapper = mount(Uploader, {
+ props: {
+ resultType: 'text',
+ afterRead(readFile: UploaderFileListItem | UploaderFileListItem[]) {
+ expect((readFile as UploaderFileListItem).content).toEqual(
+ mockFileDataUrl
+ );
+ done();
+ },
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+});
+
+test('result-type as file', (done) => {
+ const wrapper = mount(Uploader, {
+ props: {
+ resultType: 'file',
+ afterRead: (readFile: UploaderFileListItem | UploaderFileListItem[]) => {
+ expect((readFile as UploaderFileListItem).file).toBeTruthy();
+ expect((readFile as UploaderFileListItem).content).toBeFalsy();
+ done();
+ },
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+});
+
+test('set input name', (done) => {
+ const wrapper = mount(Uploader, {
+ props: {
+ name: 'uploader',
+ beforeRead: (
+ file: File | File[],
+ detail: { name: string | number; index: number }
+ ) => {
+ expect(detail.name).toEqual('uploader');
+ return file;
+ },
+ afterRead: (
+ readFile: UploaderFileListItem | UploaderFileListItem[],
+ detail: { name: string | number; index: number }
+ ) => {
+ expect(detail.name).toEqual('uploader');
+ done();
+ },
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+});
+
+test('unknown resultType', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ afterRead,
+ },
+ });
+ await wrapper.setProps({ resultType: 'xxxx' });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(0);
+});
+
+test('before read return false', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ beforeRead: () => undefined,
+ afterRead,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(0);
+ expect(input.element.value).toEqual('');
+});
+
+test('before read return promise and resolve', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ beforeRead: (file: File | File[]) =>
+ new Promise((resolve) => {
+ resolve(file);
+ }),
+ afterRead,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(1);
+});
+
+test('before read return promise and resolve no value', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ beforeRead: () =>
+ new Promise((resolve) => {
+ resolve(undefined);
+ }),
+ afterRead,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(1);
+ expect(input.element.value).toEqual('');
+});
+
+test('before read return promise and reject', async () => {
+ const afterRead = jest.fn();
+ const wrapper = mount(Uploader, {
+ props: {
+ beforeRead: () =>
+ new Promise((resolve, reject) => {
+ reject();
+ }),
+ afterRead,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(afterRead).toHaveBeenCalledTimes(0);
+ expect(input.element.value).toEqual('');
+});
+
+test('file size overlimit', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ maxSize: 1,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+
+ let fileList = [mockFile];
+ Object.defineProperty(input.element, 'files', {
+ get: () => jest.fn().mockReturnValue(fileList)(),
+ });
+
+ await input.trigger('change');
+
+ fileList = [mockFile, mockFile];
+ await input.trigger('change');
+
+ await later();
+ expect(wrapper.emitted<[File]>('oversize')![0]).toBeTruthy();
+ expect(wrapper.emitted<[File]>('oversize')![1]).toBeTruthy();
+
+ await wrapper.setProps({ maxSize: 100000 });
+
+ fileList = [mockFile];
+ await input.trigger('change');
+
+ await later();
+ expect(wrapper.emitted<[File]>('oversize')![2]).toBeFalsy();
+});
+
+test('render upload-text', () => {
+ const uploadText = 'Text';
+ const wrapper = mount(Uploader, {
+ props: {
+ uploadText,
+ },
+ });
+
+ const text = wrapper.find('.van-uploader__upload-text');
+ expect(text?.text()).toEqual(uploadText);
+});
+
+test('render preview image', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [
+ { url: 'https://img01.yzcdn.cn/vant/cat.jpeg' },
+ { url: 'https://img01.yzcdn.cn/vant/test.pdf' },
+ { file: mockFile },
+ ],
+ },
+ });
+
+ expect(wrapper.html()).toMatchSnapshot();
+});
+
+test('image-fit prop', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ imageFit: 'contain',
+ modelValue: [{ url: 'https://img01.yzcdn.cn/vant/cat.jpeg' }],
+ },
+ });
+
+ expect(wrapper.html()).toMatchSnapshot();
+});
+
+test('upload-icon prop', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ uploadIcon: 'add',
+ },
+ });
+
+ expect(wrapper.html()).toMatchSnapshot();
+});
+
+test('disable preview image', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [],
+ previewImage: false,
+ },
+ });
+
+ await wrapper.setProps({ modelValue: [{ file: mockFile }] });
+ expect(wrapper.html()).toMatchSnapshot();
+
+ await wrapper.setProps({ previewImage: true });
+ expect(wrapper.html()).toMatchSnapshot();
+});
+
+test('max-count prop', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [],
+ maxCount: 1,
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile, mockFile]),
+ });
+ input.trigger('change');
+ await later();
+ expect(
+ wrapper.emitted<[File | File[]]>('update:modelValue')![0][0]
+ ).toHaveLength(1);
+});
+
+test('preview-size prop', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [],
+ previewSize: 30,
+ },
+ });
+
+ await wrapper.setProps({ modelValue: [{ file: mockFile }] });
+ expect(wrapper.html()).toMatchSnapshot();
+});
+
+test('deletable prop', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ },
+ });
+
+ expect(wrapper.find('.van-uploader__preview-delete').exists()).toBeTruthy();
+
+ await wrapper.setProps({ deletable: false });
+ expect(wrapper.find('.van-uploader__preview-delete').exists()).toBeFalsy();
+});
+
+test('delete preview image', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ previewSize: 30,
+ },
+ });
+
+ wrapper.find('.van-uploader__preview-delete').trigger('click');
+
+ expect(wrapper.emitted<[File]>('update:modelValue')![0][0]).toHaveLength(0);
+ expect(wrapper.html()).toMatchSnapshot();
+ expect(wrapper.emitted<[File]>('delete')![0]).toBeTruthy();
+});
+
+test('before-delete prop return false', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ beforeDelete: () => false,
+ },
+ });
+
+ wrapper.find('.van-uploader__preview-delete').trigger('click');
+ expect(wrapper.emitted('delete')).toBeFalsy();
+});
+
+test('before-delete prop return true', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ beforeDelete: () => true,
+ },
+ });
+
+ wrapper.find('.van-uploader__preview-delete').trigger('click');
+ expect(wrapper.emitted('delete')).toBeTruthy();
+});
+
+test('before-delete prop resolved', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ beforeDelete: () => new Promise((resolve) => resolve(true)),
+ },
+ });
+
+ wrapper.find('.van-uploader__preview-delete').trigger('click');
+ await later();
+ expect(wrapper.emitted('delete')).toBeTruthy();
+});
+
+test('before-delete prop rejected', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ beforeDelete: () => new Promise((resolve, reject) => reject()),
+ },
+ });
+
+ wrapper.find('.van-uploader__preview-delete').trigger('click');
+ await later();
+ expect(wrapper.emitted('delete')).toBeFalsy();
+});
+
+test('click to preview image', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ previewFullImage: false,
+ modelValue: [{ url: IMAGE }, { url: PDF }],
+ },
+ });
+
+ wrapper.find('.van-image').trigger('click');
+ await later();
+ expect(document.querySelector('.van-image-preview')).toBeFalsy();
+
+ await wrapper.setProps({ previewFullImage: true });
+ wrapper.find('.van-image').trigger('click');
+ await later();
+ expect(document.querySelector('.van-image-preview')).toBeTruthy();
+
+ const images = document.querySelectorAll(
+ '.van-image-preview .van-image-preview__image'
+ );
+ expect(images).toHaveLength(1);
+});
+
+test('preview-options prop', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ previewOptions: {
+ images: [],
+ closeable: true,
+ },
+ },
+ });
+
+ wrapper.find('.van-image').trigger('click');
+ await later();
+
+ const closeIcon = document.querySelectorAll('.van-image-preview__close-icon');
+ expect(closeIcon).toHaveLength(1);
+});
+
+test('closeImagePreview method', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ },
+ });
+
+ await nextTick();
+ await (wrapper.vm as Record).closeImagePreview();
+ expect(wrapper.emitted('close-preview')).toBeFalsy();
+
+ wrapper.find('.van-image').trigger('click');
+ await (wrapper.vm as Record).closeImagePreview();
+ expect(wrapper.emitted('close-preview')).toBeTruthy();
+});
+
+test('click-preview event', () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ previewFullImage: false,
+ modelValue: [{ url: IMAGE }, { url: PDF }],
+ },
+ });
+
+ wrapper.find('.van-image').trigger('click');
+ expect(wrapper.emitted<[File]>('click-preview')![0][0]).toEqual({
+ url: IMAGE,
+ });
+ expect(
+ wrapper.emitted<[File, { name: string; index: number }]>(
+ 'click-preview'
+ )![0][1]
+ ).toEqual({
+ name: '',
+ index: 0,
+ });
+});
+
+test('close-preview event', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }],
+ },
+ });
+
+ await later();
+ wrapper.find('.van-image').trigger('click');
+
+ const preview = document.querySelector('.van-image-preview');
+ const swipe = preview?.querySelector(
+ '.van-swipe-item'
+ ) as HTMLDivElement;
+ triggerDrag(swipe, 0, 0);
+
+ await later(300);
+ expect(wrapper.emitted('close-preview')).toBeTruthy();
+});
+
+test('show-upload prop', async () => {
+ const wrapper = mount(Uploader);
+
+ expect(wrapper.find('.van-uploader__upload').exists()).toBeTruthy();
+ await wrapper.setProps({ showUpload: false });
+ expect(wrapper.find('.van-uploader__upload').exists()).toBeFalsy();
+});
+
+test('file message should be reactive', async (done) => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [],
+ afterRead(file: UploaderFileListItem | UploaderFileListItem[]) {
+ if (Array.isArray(file)) return;
+ file.status = 'uploading';
+ file.message = '1';
+ setTimeout(() => {
+ file.message = '2';
+ expect(wrapper.html()).toMatchSnapshot();
+ done();
+ });
+ },
+ },
+ });
+
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile]),
+ });
+ input.trigger('change');
+});
+
+test('multiFile upload filter max-size file', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ maxSize: 1000,
+ },
+ });
+
+ const smallFile = new File([new ArrayBuffer(100)], 'small.jpg');
+ const input = wrapper.find('.van-uploader__input');
+ Object.defineProperty(input.element, 'files', {
+ get: jest.fn().mockReturnValue([mockFile, smallFile]),
+ });
+ input.trigger('change');
+ await later();
+
+ expect(wrapper.emitted<[File]>('oversize')![0]).toBeTruthy();
+});
+
+test('preview-cover slot', async () => {
+ const wrapper = mount(Uploader, {
+ props: {
+ modelValue: [{ url: IMAGE }, { url: IMAGE }],
+ },
+ slots: {
+ 'preview-cover': 'Custom Preview Cover',
+ },
+ });
+
+ expect(wrapper.html()).toMatchSnapshot();
+});
diff --git a/src/uploader/test/utils.legacy.js b/src/uploader/test/utils.spec.ts
similarity index 80%
rename from src/uploader/test/utils.legacy.js
rename to src/uploader/test/utils.spec.ts
index 58435c82b..55847e8ef 100644
--- a/src/uploader/test/utils.legacy.js
+++ b/src/uploader/test/utils.spec.ts
@@ -10,8 +10,12 @@ test('isImageFile', () => {
expect(isImageFile({ url: 'https://a.jfif' })).toBeTruthy();
expect(isImageFile({ url: 'https://a.bmp' })).toBeTruthy();
expect(isImageFile({ url: 'https://a.dpg' })).toBeTruthy();
- expect(isImageFile({ file: { type: 'image/jpg' } })).toBeTruthy();
- expect(isImageFile({ file: { type: 'application/pdf' } })).toBeFalsy();
+ expect(
+ isImageFile({ file: new File([], 'foo.jpg', { type: 'image/jpg' }) })
+ ).toBeTruthy();
+ expect(
+ isImageFile({ file: new File([], 'bar.pdf', { type: 'application/pdf' }) })
+ ).toBeFalsy();
expect(isImageFile({ content: 'data:image/xxx' })).toBeTruthy();
expect(isImageFile({ content: 'data:application/xxx' })).toBeFalsy();
expect(isImageFile({ isImage: true })).toBeTruthy();