如何正确测试React Dropzone onDrop方法

Alb*_*ivé 10 javascript unit-testing reactjs jestjs react-dropzone

我正在测试React Dropzone,我需要检查onDrop函数.此函数有两个参数(acceptedFiles和rejectedFiles).我在嘲笑这样的文件:

let image = {
  name: 'cat.jpg',
  size: 1000,
  type: 'image/jpeg'
};
Run Code Online (Sandbox Code Playgroud)

然后在我的测试中,我这样做:

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);
});
Run Code Online (Sandbox Code Playgroud)

这是我的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');
};
Run Code Online (Sandbox Code Playgroud)

预期的结果是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);
  }
Run Code Online (Sandbox Code Playgroud)

谢谢.

小智 7

路过时

let image = {
  name: 'cat.jpg',
  size: 1000,
  type: 'image/jpeg'
};
Run Code Online (Sandbox Code Playgroud)

wrapper.find(Dropzone).simulate('drop', { dataTransfer: { files: images } });
Run Code Online (Sandbox Code Playgroud)

它会认为图像未定义或为空.我能解决这个问题的方法是

//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] } });
Run Code Online (Sandbox Code Playgroud)

这当然是你如何为纯文本文件做的.对于不同类型的图像,您需要指定图像类型而不是"text/plain"


Mic*_*ski 6

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

wrapper.find(...).simulate('drop', ...);
Run Code Online (Sandbox Code Playgroud)

对我不起作用。

相反,我changeinput现场进行了模拟。这适合我对组件进行单元测试的用例。我不关心测试组件的特定放置功能,因为这超出了对我的组件进行单元测试的范围。假设react-dropzone功能正常,我只需要测试我的组件是否正确处理了文件放置事件,我仍然可以通过与input字段交互来进行测试。它具有更通用的良好副作用,以防我将来更换 dropzone 库。

wrapper.find('input').simulate('change', {
  target: { files },
  preventDefault: () => {},
  persist: () => {},
});
Run Code Online (Sandbox Code Playgroud)

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'),
];
Run Code Online (Sandbox Code Playgroud)

同样,它适合我的用例,只创建像这样的模拟文件对象,而不是使用 native FilelastModifiedDate如果需要,您可以添加更多属性(例如),但我没有。

如果出于某种原因,您觉得需要创建适当的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;
};
Run Code Online (Sandbox Code Playgroud)

由于path未设置属性,我在测试中遇到了一些问题。检查本机File对象的相等性也很麻烦。序列化的文件对象最终会是{},这显然没有用。我相信你可以让它工作,但 IMO,File如果可以,请避免使用本机对象。在我的测试中使用它们没有任何好处。