React testing: "TypeError: MutationObserver is not a constructor"

React testing: "TypeError: MutationObserver is not a constructor"

问题

我正在尝试测试内部组件库的新版本,它最近升级了一些依赖项,现在在内部使用 Jest 26。该库还导出了一些测试助手。

在另一个使用上述组件库的代码库中,当 运行 某些单元测试时,我得到以下结果:

TypeError: MutationObserver is not a constructor

    at /<path_to_repo>/node_modules/@testing-library/dom/dist/wait-for.js:78:18

这可能与组件库导出的测试助手依赖于 Jest 26 这一事实有关,也可能无关。(很难判断是否正在使用这些助手——我们有一些非常大的“单元”测试。)

相关包版本(在使用代码库中):

运行 yarn list jsdom 产生以下结果:

├─ jest-environment-jsdom-fourteen@1.0.1
│  └─ jsdom@14.1.0
├─ jest-environment-jsdom@24.9.0
│  └─ jsdom@11.12.0
└─ jsdom@16.4.0

我知道升级 react-scripts 和 Jest 可能会解决这个问题,但我正在尝试找到一种不涉及该问题的方法。 (理想情况下,我们不希望这是升级到我们新的组件库版本的先决条件。)

尝试的解决方案

强制更新 jsdom

首先我尝试添加

"resolutions": {
  "jsdom": "^14.0.0"
},

给我的 package.json。这确实使 yarn list jsdom 仅输出 jsdom@14.1.0,但我仍然得到相同的 TypeError。解析为 ^15.0.0 导致了同样的错误,解析为 ^16.0.0 给了我以下错误:

TypeError: this.dom.runVMScript is not a function

  at JSDOMEnvironment.runScript (node_modules/jest-environment-jsdom/build/index.js:187:23)

使用jest-environment-jsdom-*

我尝试通过安装 jest-environment-jsom-sixteen 来关注 。在 package.json 和 运行 yarn test --showConfig 中更改我的 test 脚本会产生一堆信息,包括以下行:

"testEnvironment": "/<path_to_repo>/node_modules/jest-environment-jsdom-sixteen/lib/index.js",

如果我在测试中添加 console.log(navigator.userAgent),我也会得到

Mozilla/5.0 (darwin) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/16.4.0

但是,我还是一样TypeError: MutationObserver is not a constructor

我也尝试了jest-environment-jsdom-fourteenjest-environment-jsdom-fifteen,并尝试将jsdom强制为^14.0.0。同样的结果。

使用mutationobserver-shim

I 运行 yarn add -D mutationobserver-shim 并将其导入(使用 import 'mutationobserver-shim')到我的 jestSetup.ts 中(这是我的 Jest 配置中 globalSetup 指向的内容) ,但这导致了以下错误:

ReferenceError: window is not defined
  at Object.<anonymous> (/<path_to_repo>/node_modules/mutationobserver-shim/dist/mutationobserver.min.js:12:1)

将导入而不是添加到我的测试文件产生与上面相同的 TypeError,并且将 console.log(global.MutationObserver) 添加到我的测试文件产生 undefined.

一个不太好的解决方案

经过反复试验,我发现如果我 1) 安装了 jest-environment-jsdom-sixteen 并告诉 Jest 使用它 2) 在我的测试中添加 import 'mutationobserver-shim' file,测试将通过。但是,如果我将导入添加到我的 Jest globalSetup 文件中,它就不起作用。我得到了和以前一样的 ReferenceError: window is not defined 错误。

我的问题

如何在不要求我们组件库的用户向他们的所有测试文件添加导入语句的情况下消除这两个错误?

应在 setupFilesAfterEnv 中应用 polyfill,因为这是 JSDOM 环境实例化和 window 可用的地方。 window 不应在 globalSetup 中可用,因为它在 运行 测试范围内不可用。

如果这是未弹出的 create-react-app 项目,对应于 setupFilesAfterEnv 的安装文件是 src/setupTests.ts (src/setupTests.js).

较新的 jsdom 版本会导致错误,这意味着它与旧 Jest (jest@24) 不兼容。它们应该被弹出并升级,或者必须使用支持 Jest 26 的更新的 CRA (react-scripts@4)。