我正在使用jest v27和@testing-library/react v12,我升级到React 17,有addEventListener无意中添加到文档中的selectionchange事件。我根本没有使用这个活动。
最小可重现示例:
// App.test.tsx
import { render } from "@testing-library/react";
import App from "./App";
test("App", () => {
it("test", async () => {
const addSpyDoc = jest.spyOn(window.document, "addEventListener");
render(<App />);
// this expect would fail and show that it is called with
// 1: "selectionchange", [Function bound dispatchDiscreteEvent], false
// 2: "selectionchange", [Function bound dispatchDiscreteEvent], true
expect(addSpyDoc).not.toHaveBeenCalled();
});
});
// App.tsx
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
</div>
);
}
// index.tsx
import { render } from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
render(<App />, rootElement);
以下是配置文件和package.json
// tsconfig.json
{
"include": ["*"],
"compilerOptions": {
"baseUrl": ".",
"lib": ["dom", "es2015"],
"jsx": "react-jsx",
"isolatedModules": true,
"moduleResolution": "node",
"module": "ESNext",
"target": "ES6",
"resolveJsonModule": true
}
}
// .babelrc.json
{
"sourceType": "unambiguous",
"presets": [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins": []
}
// jest.config.ts
import type { Config } from "@jest/types";
export const sharedConfig: Config.InitialOptions = {
verbose: true,
preset: "ts-jest",
testEnvironment: "jsdom",
};
// package.json
"dependencies": {
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"ts-node": "^10.9.1",
"ts-jest": "^27.1.3",
"@babel/core": "^7.17.9",
"@babel/preset-env": "^7.23.3",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "12.1.5",
"@types/jest": "^27.4.1",
"@types/node": "^17.0.25",
"@types/react": "17.0.55",
"@types/react-dom": "17.0.23",
"babel-loader": "^8.2.4",
"jest": "27.5.1",
"typescript": "4.5.3"
},
"scripts": {
"test": "jest test --env=jsdom"
},
为了更容易运行,这里有React 17和16的两个沙箱。在v16中,没有额外的事件添加到文档中。
https://codesandbox.io/s/jest-react-testing-library-forked-8cygdn?file=/src/App.test.tsxReact 17
https://codesandbox.io/s/jest-react-testing-library-forked-r4k6zh?file=/src/App.test.tsxReact 16
这种行为是预期的吗?添加这个非故意的选择更改事件的原因是什么?
非常感谢您的帮助!
我遇到了类似的问题,并通过调试器查看 ReactDOM 的 listenToNativeEvent 实现有一个特殊情况,它添加了一个事件气泡侦听器。这种情况是针对“selectionchange”事件且 rootContainerElement 不是文档节点时的情况。
selectionchange 事件是一个浏览器事件,当用户在文档中进行选择时触发,并且我相信它不会在 DOM 树中冒泡(浏览器直接在文档上触发它)。因此,即使根容器不是文档节点,React 组件也必须正确监听选择更改事件。
我还没有使用react18进行测试,看看行为是否不同,但似乎是有意为之,而且我不确定我们是否应该在使用react17并模拟addEventListenerCall时在测试中考虑这种行为。