我正在测试React Dropzone,我需要检查onDrop功能。此函数有两个参数(acceptedFiles和rejectedFiles)。我嘲笑这样的文件:
let image = {
name: 'cat.jpg',
size: 1000,
type: 'image/jpeg'
};
然后在我的测试中,我这样做:
it('should call handleOnDrop with more than 5 acceptedFiles', () => {
const wrapper = mount(mockComponent());
for (let index = 0; index < 5; index++) {
images.push(image);
}
wrapper.find(Dropzone).simulate('drop', { dataTransfer: { files: images } });
expect(setUserNotificationsSpy).toHaveBeenCalledTimes(1);
});
这是我的onDrop功能:
const handleOnDrop = (acceptedFiles, rejectedFiles) => {
if (rejectedFiles && rejectedFiles.length) {
checkMaxFile(rejectedFiles, maxSize) && setUserNotifications('error_big_image');
}
acceptedFiles && acceptedFiles.length <= maxFiles ? onDrop(acceptedFiles) : setUserNotifications('more_than_5');
};
预期结果是handleOnDrop返回acceptedFiles但返回rejectedFiles并且我不知道原因。
Mime键入它的确定和大小。
这是来自react-dropzone的功能:
fileAccepted(file) {
// Firefox versions prior to 53 return a bogus MIME type for every file drag, so dragovers with
// that MIME type will always be accepted
return file.type === 'application/x-moz-file' || accepts(file, this.props.accept);
}
感谢。
答案 0 :(得分:7)
传递时
let image = {
name: 'cat.jpg',
size: 1000,
type: 'image/jpeg'
};
进入
wrapper.find(Dropzone).simulate('drop', { dataTransfer: { files: images } });
它会认为图像未定义或为空。 我能解决这个问题的方法是
//Create a non-null file
const fileContents = "file contents";
const file = new Blob([fileContents], { type: "text/plain" });
wrapper.find(Dropzone).simulate("drop", { dataTransfer: { files: [file] } });
这当然是你如何为纯文本文件做的。对于不同类型的图像,您需要指定图像类型而不是执行&#34; text / plain&#34;
答案 1 :(得分:2)
在使用useDropzone
钩子时遇到了这个问题。使用
wrapper.find(...).simulate('drop', ...);
对我不起作用。
相反,我在change
字段上模拟了input
。这适合用于单元测试组件的用例。我不在乎测试组件的特定放置功能,因为这超出了对组件进行单元测试的范围。假设react-dropzone
可以正常工作,我只需要测试我的组件是否正确处理了文件放置事件,我仍然可以通过与input
字段进行交互来进行测试。而且它具有更通用的好处,以防将来我换掉dropzone库。
wrapper.find('input').simulate('change', {
target: { files },
preventDefault: () => {},
persist: () => {},
});
我这样定义我的files
:
const createFile = (name, size, type) => ({
name,
path: name,
size,
type,
});
const files = [
createFile('foo.png', 200, 'image/png'),
createFile('bar.jpg', 200, 'image/jpeg'),
];
同样,仅使用像这样创建模拟文件对象,而不是使用本机File
来满足我的用例。您可以根据需要添加更多属性(例如lastModifiedDate
),但我没有。
如果出于某种原因,您认为需要创建适当的File
实例,则也可以这样做:
const createFile = (name, size, type) => {
// the first arg, [], is the file content
// it's irrelevant, so I left it blank
// you can fill it like ['foobar'] or [name] if you want to
const file = new File([], name, { type });
Reflect.defineProperty(file, 'size', {
get() {
return size;
}
});
return file;
};
由于未设置path
属性,我在测试中遇到了一些问题。检查本地File
对象的相等性也是很麻烦的。序列化的文件对象最终将是{}
,这显然没有用。我确定您可以使其正常运行,但是IMO,请尽量避免使用本机File
对象。在我的测试中使用它们没有好处。
答案 2 :(得分:2)
如果有人在创建存根文件后遇到任何进一步的问题,我发现还在 dataTransfer 选项中提供了一个 types 字段来绕过 react-dropzone 使用的一些检查。我正在使用 RTL,所以 ymmv。
const fakeVideo = new File(['muhaahahah'], 'hello.mp4', { type: 'video/mp4' });
fireEvent.drop(getByTestId('test-input'), {
dataTransfer: { files: [fakeVideo], types: ['Files'] }
});
答案 3 :(得分:1)
我正在使用 react 测试库,这对我来说很有效, 我已将测试 ID 附加到从 useDropZone 钩子中获取 getRootProps 的 div,它不一定必须是 div,它可以是任何容器元素
function dispatchEvt(node: any, type: any, data: any) {
const event = new Event(type, { bubbles: true });
Object.assign(event, data);
fireEvent(node, event);
}
async function flushPromises(rerender: any, ui: any) {
await act(() => wait(() => rerender(ui)));
}
const onDropMock = jest.fn();
it("The on Drop is called on dragging a file ", async () => {
const file = new File([JSON.stringify({ ping: true })], "fileName.csv", { type: "text/csv" });
const data = mockData([file]);
const ui = <MyComponent onDrop={onDropMock} />;
const { container, rerender } = render(ui);
const input = screen.getByTestId("testId-for-div");
dispatchEvt(input, "drop", data);
await flushPromises(rerender, ui);
expect(onDropMock).toHaveBeenCalled();
});
我在官方文档中找到了所有这些信息 here