反应测试:“ TypeError:MutationObserver不是构造函数” 强制更新jsdom 使用jest-environment-jsdom-* 使用mutationobserver-shim

问题描述

问题

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

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

TypeError: MutationObserver is not a constructor

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

这可能与或可能与以下事实无关:组件库导出的测试帮助程序依赖于Jest26。(很难确定这些帮助程序是否正在使用-我们有一些非常大的“单元”测试。)

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

  • 反应脚本3.4.4
  • 笑话24.9.0
  • testing-library / dom 7.26.3
  • testing-library / jest-dom 5.10.0
  • testing-library / react ^ 10.0.0

运行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来关注this thread。在test中更改我的package.json脚本并运行yarn test --showConfig会产生一堆信息,包括以下行:

"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

我运行了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' ,并且测试将通过。但是,如果我将导入添加到我的Jest globalSetup文件中,它将无法正常工作。我收到与以前相同的ReferenceError: window is not defined错误

我的问题

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

解决方法

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

如果这是一个未创建的create-react-app项目,则与setupFilesAfterEnv对应的安装文件为src/setupTests.tssrc/setupTests.js)。

较新的jsdom版本导致错误,表示它与旧的Jest(jest@24)不兼容。应该弹出并升级它们,否则必须使用具有Jest 26支持的更新的CRA(react-scripts@4)。