reactjs - 在测试期间无法访问组件中的 DOM 元素(在浏览器中工作)
问题描述
背景
我有一个组件,我正在访问一个元素的子元素(使用 ref)。目标是将粘贴事件拦截到输入字段中,并将粘贴的内容拆分和分发到几个不受控制的表单输入元素上。在浏览器中渲染组件时(使用 Storybook),这一切都可以正常工作。
问题
然而,在测试中,我无法以任何我尝试的方式访问孩子。
问题
- 我如何使用
fireEvent
或如何设置测试有问题吗? - 我对 React 很陌生,我应该以其他方式访问 DOM 元素吗?
- 或者我应该根本不使用测试库来测试这种行为?
任何帮助将不胜感激,因为我现在不知道还能尝试什么!
例子
我已经制作了一个显示问题的组件的最小示例。
零件
import React, { useRef } from "react";
import { prettyDOM } from "@testing-library/dom";
function Dummy({}) {
const inputContainer = useRef(null);
const handleClick = (e) => {
// The elements exist!
console.log('document', prettyDOM(document))
console.log('div', prettyDOM(inputContainer.current))
console.log('e.target', prettyDOM(e.target))
// All attempts to get the inputs return empty collections.
console.log('div.children', inputContainer.current.children)
console.log('div.childNodes', inputContainer.current.childNodes)
console.log('div.querySelectorAll("*")', inputContainer.current.querySelectorAll("*"))
console.log('e.target.parentNode.querySelectorAll("input")', e.target.parentNode.querySelectorAll("input"))
// Going via the document doesn't work either...
console.log('document.querySelectorAll("#outer input").children', document.querySelectorAll('#outer input'))
// For some reason, firstChild works (but I need all children, not just one).
console.log('div.firstChild', inputContainer.current.firstChild.value)
};
return (
<fieldset id="outer">
<div ref={inputContainer}>
<input type="text" onClick={handleClick} defaultValue="bar"/>
<input type="text" />
</div>
</fieldset>
);
}
export default Dummy;
测试
import React from "react";
import { render, screen } from "@testing-library/react";
import { fireEvent } from '@testing-library/dom'
import Dummy from "./Dummy";
describe("Dummy", () => {
it("should do something", () => {
render(<Dummy />);
fireEvent.click(screen.getByDisplayValue("bar"));
expect(false).toBe(true);
});
});
笑话输出
FAIL src/components/Dummy.test.js
Dummy
✕ should do something (96 ms)
● Dummy › should do something
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
11 | fireEvent.click(screen.getByDisplayValue("bar"));
12 |
> 13 | expect(false).toBe(true);
| ^
14 | });
15 | });
16 |
at Object.<anonymous> (src/components/Dummy.test.js:13:19)
console.log
document <html>
<head />
<body>
<div>
<fieldset
id="outer"
>
<div>
<input
type="text"
value="bar"
/>
<input
type="text"
/>
</div>
</fieldset>
</div>
</body>
</html>
at handleClick (src/components/Dummy.js:11:13)
console.log
div <div>
<input
type="text"
value="bar"
/>
<input
type="text"
/>
</div>
at handleClick (src/components/Dummy.js:12:13)
console.log
e.target <input
type="text"
value="bar"
/>
at handleClick (src/components/Dummy.js:13:13)
console.log
div.children HTMLCollection {}
at handleClick (src/components/Dummy.js:16:13)
console.log
div.childNodes NodeList {}
at handleClick (src/components/Dummy.js:17:13)
console.log
div.querySelectorAll("*") NodeList {}
at handleClick (src/components/Dummy.js:18:13)
console.log
e.target.parentNode.querySelectorAll("input") NodeList {}
at handleClick (src/components/Dummy.js:19:13)
console.log
document.querySelectorAll("#outer input").children NodeList {}
at handleClick (src/components/Dummy.js:22:13)
console.log
div.firstChild bar
at handleClick (src/components/Dummy.js:25:13)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 3.995 s
Ran all test suites matching /dum/i.
Watch Usage: Press w to show more.
解决方案
这些
HTMLCollection {}
NodeList {}
不是空列表!无论内容如何,它们都以这种方式打印!包含 1 或 1,000 个元素的列表将被打印为{}
(由 jsdom,我假设?)。
我真诚地希望这能帮助别人节省一些时间,因为它确实让我付出了太多……
推荐阅读
- flutter - 颤动问题底部溢出 61 像素//这是我的代码,请有人帮忙
- java - 如何从 jar 文件中加载图像?
- javascript - Vue.js:快速键入时不应用使用计算属性的输入格式
- c++ - 如何对向量内的行求和?
- php - curl 未填充的 cookie(IG 交易)
- java - 在java中运行包含“behave”命令的python脚本
- mysql - MYSQL - 行到列转置
- average - Grafana 平均间隔
- webpack - 面向 webworker 的 Webpack 不会导入依赖项的浏览器版本
- crystal-lang - 如何在 Crystal 中进行通用记忆?