12

我正在测试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 返回接受文件但返回拒绝文件,我不知道为什么。

哑剧类型没关系,也有大小。

这就是 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);
  }

谢谢。

4

4 回答 4

9

通过时

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] } });

这当然是你对纯文本文件的处理方式。对于不同类型的图像,您需要指定图像类型而不是“文本/纯文本”

于 2018-01-30T14:21:05.390 回答
8

我在使用useDropzone钩子时遇到了这个问题。使用

wrapper.find(...).simulate('drop', ...);

对我不起作用。

相反,我changeinput球场上进行了模拟。这适合我对组件进行单元测试的用例。我不关心测试组件的特定放置功能,因为这超出了对我的组件进行单元测试的范围。假设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'),
];

同样,它适合我的用例来创建像这样的模拟文件对象,而不是使用 native 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如果可以的话,避免使用原生对象。在我的测试中使用它们没有任何好处。

于 2019-08-08T22:02:56.590 回答
3

我正在使用反应测试库,这对我来说是正确的,我已将测试 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();
  });

我在这里的官方文档中找到了所有这些信息

于 2021-05-14T01:11:47.707 回答
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'] }
});
于 2021-03-16T22:26:33.453 回答