Jest 测试中的 `requestAnimationFrame` polyfill 错误

`requestAnimationFrame` polyfill error in Jest tests

当我 运行 我的 Jest 单元测试时升级到 React 后出现此错误:

React depends on requestAnimationFrame. Make sure that you load a polyfill in older browsers.

我该如何解决?

我正在使用 Jest 18.1.0。

原来是因为我升级了enzyme而没有升级reactreact-dom.

React 15.5 带来了一些弃用,导致许多依赖库也必须更新。确保您正在更新 reactreact-dom 并检查这些依赖包的自述文件以了解您必须安装的新库。例如,Enzyme 2.8.2 现在需要 react-addons-test-utils 作为依赖项。

找到解决方法!

步骤:

  1. 创建文件__mocks__/react.js
  2. 将以下内容添加到__mocks__/react.js

const react = require('react');
// Resolution for requestAnimationFrame not supported in jest error :
// https://github.com/facebook/react/issues/9102#issuecomment-283873039
global.window = global;
window.addEventListener = () => {};
window.requestAnimationFrame = () => {
  throw new Error('requestAnimationFrame is not supported in Node');
};

module.exports = react;

  1. 运行开玩笑!

如代码注释中所标记

这是来自 https://github.com/facebook/react/issues/9102#issuecomment-283873039

如果你只需要为测试填充它,那么你实际上不需要节流。

使用此代码创建一个新文件:

global.requestAnimationFrame = function (cb) {
    return setTimeout(cb, 0);
};

将该文件添加到 package.json 中的 jest/setupFiles 数组。

这对我有用:

  1. 安装raf

npm install --saveDev rafyarn add -D raf

  1. 将 polyfill 添加到 package.jsonjest 配置中的 setupFiles,如下所示:

'setupFiles': ['raf/polyfill']

注意:如果您在此数组中还有其他安装文件,您可能希望将 raf/polyfill 放在第一位。

如果您使用的是 create-react-app,其中一些解决方案将无法正常工作(或者根本无法正常工作,在 setupFiles 的情况下)。行之有效的方法是在 src/setupTests.js 处创建一个文件并在其中添加您的模拟:

global.requestAnimationFrame = (cb) => { cb(); };

您还可以在其中添加其他全局模拟(例如 localStoragenavigator.serviceWorker)。

另一个可行的解决方案!

想法是在每个规范之前加载一个简单的垫片,通过使用 jest 配置中的 setupFiles 属性。

创建文件 shim.js 文件(最好在您的根目录中)并在其中包含以下代码:

global.requestAnimationFrame = (callback) => {
    setTimeout(callback, 0);
};

接下来,您的文件 all/most 中可能会出现重复出现的冗余代码 - 您希望将它们放在一个文件中并在每个规范之前也有它们 运行,以这样做:

也在根目录中创建一个 setup.js 文件。 D.R.Y 的一段很好的冗余代码是反应酶适配器配置代码。粘贴到这里

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

现在创建jest.config.js文件,指定两个文件的路径

{
    module.exports = {
        "setupFiles": ["<rootDir>shim.js", "<rootDir>setup.js"]
    }
}

N.B: jest 配置文件占用 json,所以确保 json在里面。此外,如果您的 shim.jssetup.js 文件与您的 jest.config.js 不在同一目录中,请相应地调整路径。

希望对您有所帮助!

来源:https://github.com/facebook/jest/issues/4545

只需将您的 react-scripts 升级到 1.0.15 或更高版本。在该版本之后已正式修复。在 https://github.com/facebook/create-react-app/issues/3199

中查看更多详细信息

搜索gaearon commented on 31 Oct 2017

的评论

这是模拟 requestAnimationFrame 的现实方法:

let time;
const maxTimeElapsed = 2000;

beforeEach(() => {
  time = 0;
  jest.spyOn(window, 'requestAnimationFrame').mockImplementation(cb => {
    time += 100;
    if (time < maxTimeElapsed) {
      return cb(time) as any;
    }
  });
});

在您的测试中,它会重复调用 RAF 回调,直到达到您设置的最大运行时间。它立即发生,所以你不需要拖延它。

如果你使用 TypeScript,最好的解决方案是;

window.requestAnimationFrame = (): number => {
   window.clearTimeout();
   return 0;
};

在你所有的描述和测试之前。