inb*_*33n 13 react-testing-library
我正在使用用户事件来尝试进行更“真实”的用户交互。但是,在我单击输入后,它不会触发该onChange
功能,因为默认情况下它只会为用户打开文件浏览器以上传文件。如何模拟用户上传文件?
我的代码:
// Component
const FileInputComponent = ({ handleFileUpload }) => (
<div>
<input type="file" id="testing" accept=".png,.jpg" onChange={handleFileUpload} />
<label htmlFor="testing">Input File Here</label>
</div>
);
Run Code Online (Sandbox Code Playgroud)
// 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);
});
Run Code Online (Sandbox Code Playgroud)
Ili*_*Ili 32
我发现了一个有点 hacky 的解决方案,我不确定它是否符合测试中的最佳实践,但我会与您分享它可能会有所帮助
\ndescribe("Upload files", () => {\n let file;\n\n beforeEach(() => {\n file = new File(["(\xe2\x8c\x90\xe2\x96\xa1_\xe2\x96\xa1)"], "chucknorris.png", { type: "image/png" });\n });\n\n test("cover photo upload", async () => {\n // render the component\n const { getByTestId } = render(<YourComponent />);\n\n // get the upload button\n let uploader = getByTestId("photo-uploader");\n\n // simulate ulpoad event and wait until finish\n await waitFor(() =>\n fireEvent.change(uploader, {\n target: { files: [file] },\n })\n );\n // get the same uploader from the dom\n let image = document.getElementById("photo-uploader");\n // check if the file is there\n expect(image.files[0].name).toBe("chucknorris.png");\n expect(image.files.length).toBe(1);\n });\n});\n
Run Code Online (Sandbox Code Playgroud)\n
小智 29
是您要测试的上传吗? https://github.com/testing-library/user-event
我只是写
const fileInput = getByLabelText('file-input-label')
userEvent.upload(fileInput, testFile)
Run Code Online (Sandbox Code Playgroud)
它onChange
为我模拟了。
小智 11
@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])
})
Run Code Online (Sandbox Code Playgroud)
这是我们使用 RTL 测试文件输入的方法:
\n describe(\'input file\', () => {\n let rtl: RenderResult;\n\n beforeEach(() => {\n rtl = render(<MyComponentWithFileInput />);\n });\n\n test(\'input file\', async () => {\n const file = new File([\'(\xe2\x8c\x90\xe2\x96\xa1_\xe2\x96\xa1)\'], \'file.xml\', { type: \'application/xml\' });\n\n // upload the file by updating the value attribute of the input\n // I assume : <input type="file" data-testid="fileInput" />\n fireEvent.change(rtl.getByTestId(\'fileInput\'), {\n target: { files: [file] },\n });\n\n // here your onChange function should have been called\n expect(handleFileUploadMockFn).toHaveBeenCalledTimes(1);\n\n // if you have a form which is submitted you should be able to check values :\n expect(onSubmitForm).toHaveBeenCalledWith({\n file: expect.any(Object),\n });\n });\n });\n
Run Code Online (Sandbox Code Playgroud)\n这是总体思路,显然应该更新以匹配您的设置。
\n输入元素:
<input type="file" data-testid="fileDropzone"/>
Run Code Online (Sandbox Code Playgroud)
首先渲染元素,然后通过 获取输入文件上传元素getByTestId
。
其次,定义一个假文件:
const fakeFile = new File(['hello'], 'hello.png', { type: 'image/png' });
Run Code Online (Sandbox Code Playgroud)
然后,导入 userEvent。并上传文件,确保在里面说唱act()
:
import userEvent from '@testing-library/user-event';
Run Code Online (Sandbox Code Playgroud)
测试期望,这是最终的代码:
it('Upload Files', async () => {
const { getByTestId } = render(<FileUplaodComponent/>);
const fakeFile = new File(['hello'], 'hello.png', { type: 'image/png' });
const inputFile = getByTestId(/fileDropzone/i);
await act(async () => {
await waitFor(() => {
userEvent.upload(inputFile, fakeFile);
});
});
expect(inputFile.files[0]).toStrictEqual(inputFile);
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7081 次 |
最近记录: |