如何使用React Testing Library通过Ant Design的Upload模拟上传文件?

时间:2020-09-23 20:59:48

标签: reactjs antd react-testing-library

我正在使用Ant Design的Upload组件。

 <Upload 
     accept=".xlsx" 
     onChange={onImport}
  >
     <Button>Upload</Button>
 </Upload>

我试图使用fireEvent.change模拟更改,但该操作什么都不做:

const inputEl = screen.getByText('Import');
const file = new File(['(⌐□_□)'], 'chucknorris.xlsx');
fireEvent.change(inputEl, { target: { files: [file] } });

我也尝试使用fireEvent.drop。我尝试同时设置dataTransfer和files属性。

Object.defineProperty(inputEl, 'dataTransfer', {
    value: {
        files: [file]
    }
});
Object.defineProperty(inputEl, 'files', {
    value: [file]
});
fireEvent.drop(inputEl);

这会触发上传,但我不断收到以下错误:

Cannot read property 'files' of undefined
  at AjaxUploader._this.onFileDrop (node_modules/rc-upload/lib/AjaxUploader.js:108:63)

如何测试Ant Design的上传?

2 个答案:

答案 0 :(得分:0)

这是我的处理方式。由于 input 是隐藏的,您无法使用 RTL 查询它,我只是使用 document 查询输入,如下所示:

async simulateFileUpload() {
  const file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
  const hiddenFileInput = document.querySelector('input[type="file"]') as Element;

  await act(async () => {
    fireEvent.change(hiddenFileInput, { target: { files: [file] } });
  });
}

这不是最好的做法,但它是测试上传功能的唯一方法。
我将 fireEvent 包裹在 await act() 中,但这只是因为上传会触发我的应用程序中的某些状态更改,您当然可以直接将其扔掉

答案 1 :(得分:0)

您可以使用用户事件;是测试库的配套库,提供比内置 fireEvent 方法更高级的浏览器交互模拟。

安装:

npm install --save-dev @testing-library/user-event

用法:

import React from 'react'
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

test('upload file', () => {
   const file = new File(['hello'], 'hello.png', { type: 'image/png' })

    render(
        <div>
           <label htmlFor="file-uploader">Upload file:</label>
           <input id="file-uploader" type="file" />
        </div>
    )
    const input = screen.getByLabelText(/upload file/i)
    userEvent.upload(input, file)

    expect(input.files[0]).toStrictEqual(file)
    expect(input.files.item(0)).toStrictEqual(file)
    expect(input.files).toHaveLength(1)
})