reactjs - React 测试库 - 使用 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>
}
证书测试.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)
推荐阅读
- flutter - 颤振流行到新路线
- php - Drupal 在动态创建的元标记中转义 url
- dialogflow-es - 轮播中的项目不能在智能显示器上点击/选择
- python - 从 n 人的团队中形成 r 组的最佳方法,但尽量减少重叠
- python - 使用 matplotlib 针对正态分布、高斯分布、指数分布和伽马分布创建动画的问题
- ios - 如何在标签中添加按钮?
- http - 如何为 AAD 生成 Http 请求?
- haskell - 将 Int 定义为 Haskell 中类型类的实例时出现问题
- memory - 多级页表中页表条目的大小是多少?
- c# - 在缺少异常处理的同步方法中检测异步构造所需的 NDepend 代码规则