React Testing库-使用FileReader模拟上传文件

问题描述

我想测试一个React组件,在该组件上上传了证书文件,并且文件的结果可以显示在文本区域中。 我仍在学习编写单元测试,这里面临着模拟FileReader,readAsText和onloadend的困难。 我读了几个例子,但它们没有按预期工作。任何指导都会有所帮助

谢谢

证书组件

export default function Cert() {

 const fileInputRef = useRef();

  function handleEvent(obj,event) {
    var event = new Event(event,{ target: obj,bubbles: true });
    return obj ? obj.dispatchEvent(event) : false;
  }

 let handleChangeFile = (file) => {
    let fileData = new FileReader();
    fileData.readAsText(file);
    fileData.onloadend = () => {
      let el = document.getElementById('cert');
      el.value = event.target.result;
      handleEvent(el,'input');
      if (fileInputRef.current) {
        fileInputRef.current.value = '';
      }
    };
    fileData.onerror = function () {
      console.log(fileData.error);
    };
  };

  return (
<CheckboxWithOptions name="int" label='app'>
 <Field
          component={ExpandingTextareaField}
          name="certificate"
          label='Upload Certificate *'
          isRequired
          validate={required}
          id="cert"
        />
        <div>
          <Button
            label='Upload file'
            type="button"
            appearance="brand"
            size="large"
            onClick={() => {
              fileInputRef.current.click();
            }}
            data-typeId="test"
          />
          <input
            style={{
              opacity: 0,position: 'fixed',top: 0,left: 0,width: 0,}}
            type="file"
            accept=".cert"
            ref={fileInputRef}
            onChange={(e) => handleChangeFile(e.target.files[0])}
            data-testid="testinput"
          />
        </div>
}


Cert.test.js

it('upload file to show in textarea ',async () => {
        const file = new File(['dummy'],'test.cert',{ type: 'cert' })
        render(
            <div>
                <label htmlFor="file-uploader">Upload file:</label>
                <input id="file-uploader" type="file" onChange={(e) => handleChangeFile('e')} />
            </div>,)
        const { getByLabelText } = render(<TestComponent />);

        await waitForElementToBeRemoved(() => screen.getByText(/loading/i));
        expect(getByLabelText("CheckBox").value).toBe("false");
        fireEvent.click(screen.getByLabelText("CheckBox"))
        const input = screen.getByLabelText(/Upload file/i)
        fireEvent.click(input)
        userEvent.upload(input,file)
        await waitFor(() => expect(handleChangeFile).toBeCalledTimes(1)); // working fine till here
   jest.spyOn(global,"FileReader")
            .mockImplementation(function () {
                readAsText = jest.fn();
            });
        fireEvent.change(input,{
            target: {
                files: [file]
            }
        });
        expect(FileReader).toHaveBeenCalled(); // not working
// test the FileReader and textarea
})

解决方法

在检查一些应该在 FileReader.onload 上调用的副作用时遇到了同样的问题,所以我只是在触发事件后设置了一个短暂的暂停(我正在使用酶):

const pauseFor = milliseconds => new Promise(resolve => setTimeout(resolve,milliseconds));
...
wrapper.find('.upload-box').simulate('drop',someMockedDropEvent);
// set pause was the only way to make reader.onload to fire
await pauseFor(100);
expect(something).toEqual(something)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...