我正在使用user-event尝试进行更多“现实”的用户交互。但是,单击输入后,它将不会触发onChange
函数,因为默认情况下,它将仅弹出文件资源管理器供用户上传文件。如何模拟用户上传文件?
我的代码:
// Component
const FileInputComponent = ({ handleFileUpload }) => (
<div>
<input type="file" id="testing" accept=".png,.jpg" onChange={handleFileUpload} />
<label htmlFor="testing">Input File Here</label>
</div>
);
// Test file
test("Clicking on the label button calls the `handleFileUpload` function", () => {
const handleFileUploadMockFn = jest.fn();
const { getByLabelText } = render(<FileInputComponent handleFileUpload={handleFileUploadMockFn} />
userEvent.click(getByLabelText("Input File Here"));
expect(handleFileUploadMockFn).toHaveBeenCalledTimes(1);
});
答案 0 :(得分:2)
我发现了一个有点笨拙的解决方案,我不确定它是否符合测试中的最佳实践,但我会与您分享它可能会有所帮助
describe('Upload files', () => {
let file;
beforeEach(() => {
file = new File(['(⌐□_□)'], 'chucknorris.png', { type: 'image/png' });
});
test('cover photo upload', async () => {
// render the component
const { getByTestId } = render(<YourComponent />);
// get the upload button
let uploader = getByTestId('photo-uploader');
// simulate ulpoad event and wait until finish
await waitFor(() =>
fireEvent.change(uploader, {
target: { files: [file] },
})
);
// get the same uploader from the dom
let image = document.getElementById('photo-uploader');
// check if the file is there
expect(image.files[0].name).toBe('chucknorris.png');
expect(image.files.length).toBe(1);
});
});
答案 1 :(得分:0)
这是我们使用RTL测试文件输入的方式:
describe('input file', () => {
let rtl: RenderResult;
beforeEach(() => {
rtl = render(<MyComponentWithFileInput />);
});
test('input file', async () => {
const file = new File(['(⌐□_□)'], 'file.xml', { type: 'application/xml' });
// upload the file by updating the value attribute of the input
// I assume : <input type="file" data-testid="fileInput" />
fireEvent.change(rtl.getByTestId('fileInput'), {
target: { files: [file] },
});
// here your onChange function should have been called
expect(handleFileUploadMockFn).toHaveBeenCalledTimes(1);
// if you have a form which is submitted you should be able to check values :
expect(onSubmitForm).toHaveBeenCalledWith({
file: expect.any(Object),
});
});
});
这是一般性的想法,显然应该进行更新以匹配您的设置。
答案 2 :(得分:0)
@darthzeren 的回答几乎是正确的,但链接似乎已经过时。 这是 lib 维护者描述的解决方案: https://testing-library.com/docs/ecosystem-user-event/#uploadelement-file--clickinit-changeinit--options
仅引用文档中的示例,以防将来链接失效:
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)
})
test('upload multiple files', () => {
const files = [
new File(['hello'], 'hello.png', {type: 'image/png'}),
new File(['there'], 'there.png', {type: 'image/png'}),
]
render(
<div>
<label htmlFor="file-uploader">Upload file:</label>
<input id="file-uploader" type="file" multiple />
</div>,
)
const input = screen.getByLabelText(/upload file/i)
userEvent.upload(input, files)
expect(input.files).toHaveLength(2)
expect(input.files[0]).toStrictEqual(files[0])
expect(input.files[1]).toStrictEqual(files[1])
})
答案 3 :(得分:-1)
您要测试上传的内容吗? https://github.com/testing-library/user-event#uploadelement-file--clickinit-changeinit-
我只是说
const FileInput= getByLabelText('file-input-label')
userEvent.upload(FileInput, testFile)
它为我模拟了onChange