javascript - `window` 没有暴露给 Jest

标签 javascript reactjs unit-testing jestjs

我有一个导入组件的测试,该组件又导入一个帮助程序文件,该文件使用 window 对象提取查询字符串参数。我收到有关 window 的以下错误:

FAIL  src/js/components/__tests__/Controls.test.jsx
 ● Test suite failed to run

   ReferenceError: window is not defined

Controls.jsx:

import { Unwrapped as Controls } from '../Controls'

describe('<MyInterestsControls />', () => {
  it('should render the component with the fixture data', () => {
    const component = shallow(
      <UnwrappedMyInterestControls
        dashboardData={dashboardData}
        loadingFlags={{ controls: false }}
      />
    )
    expect(component).toMatchSnapshot()
  })
})

Controls.jsx 导入 ./helpers/services.js 其中包含以下内容:

import * as queryString from 'query-string'
const flag = queryString.parse(window.location.search).flag || 'off'
                               ^^^^^^ this seems to be the problem

我试图导入 jsdom:

import { JSDOM } from 'jsdom'

并实现提出的解决方案 here在我的测试文件的顶部:

const { JSDOM } = require('jsdom');

const jsdom = new JSDOM('<!doctype html><html><body></body></html>');
const { window } = jsdom;

function copyProps(src, target) {
  const props = Object.getOwnPropertyNames(src)
    .filter(prop => typeof target[prop] === 'undefined')
    .map(prop => Object.getOwnPropertyDescriptor(src, prop));
  Object.defineProperties(target, props);
}

global.window = window;
global.document = window.document;
global.navigator = {
  userAgent: 'node.js',
};
copyProps(window, global);

但是,我仍然收到错误消息,似乎 JSDOM 的 window 对象未暴露给测试。

如何正确地将全局对象(如 windowdocument)暴露给 Jest 测试?

相关package.json
  "scripts": {
    "test:watch": "NODE_ENV=test jest --watch"
  },
  ...
  "devDependencies": {
    ...
    "jest": "^20.0.4",
    "jest-mock": "^21.2.0",
    "jsdom": "^11.0.0",
    ...
  },
  ...
  "jest": {
    "verbose": true,
    "collectCoverageFrom": [
      "src/js/helpers/preparePayload.js",
      "src/js/components-ni",
      "!**/node_modules/**",
      "!**/dist/**"
    ],
    "coverageThreshold": {
      "global": {
        "statements": 50,
        "branches": 50,
        "functions": 50,
        "lines": 75
      }
    },
    "testEnvironment": "jest-environment-node"
  }

最佳答案

正如@RiZKiT 在下面的评论中提到的,自 Jest v27.0 the default test environment has changed 以来从 "jsdom""node"

您的问题取决于配置。

在你设置的那一刻:

"testEnvironment": "jest-environment-node"

您正在将默认配置从类似于浏览器的 Jest 更改为 jest-environment-node (Node.js-like) 这意味着您的测试将运行在Node.js下环境

要解决这个问题,您可以将 testEnvironment 设置为 jsdom 或者您从配置中删除 testEnvironment,因此它将采用您的 package.json 中的默认值:

 ...
  "jest": {
    "verbose": true,
    "collectCoverageFrom": [
      "src/js/helpers/preparePayload.js",
      "src/js/components-ni",
      "!**/node_modules/**",
      "!**/dist/**"
    ],
    "coverageThreshold": {
      "global": {
        "statements": 50,
        "branches": 50,
        "functions": 50,
        "lines": 75
      }
    }
  }

这是他们在文档中所说的

testEnvironment [string] # Default: "jsdom"

The test environment that will be used for testing. The default environment in Jest is a browser-like environment through jsdom. If you are building a node service, you can use the node option to use a node-like environment instead.


## 你需要 `node` 环境吗?

如我所见,您的测试应该在类似浏览器的环境下运行。

如果您需要一个显式的 Node.js 环境,最好使用 @jest-environment 隔离该情况:

/**
 * @jest-environment node
 */

test('use node in this test file', () => {
  expect(true).not.toBeNull();
});

或者反过来,如果您打算在 Node.js 环境下运行测试:

/**
 * @jest-environment jsdom
 */

test('use jsdom in this test file', () => {
  const element = document.createElement('div');
  expect(element).not.toBeNull();
});

## 结论

这样你就可以避免手动导入 jsdom 和设置全局变量。 jsdom 将模拟 DOM自动执行。

如果您需要更改测试环境,请使用符号 @jest-environment

关于javascript - `window` 没有暴露给 Jest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46105596/

相关文章:

javascript - Mongo 聚合计数值实例

javascript - 从 URL 加载 JSON 数据以导入 HTML 表

javascript - 自定义光标随着窗口滚动而移动

reactjs - React 组件中的排序

java - 模拟引用 SQLiteOpenHelper 的类时出错

android - 如何模拟/ stub Flutter 平台 channel /插件?

javascript - YouTube iframe 返回 "Failed to load resource: Frame load interrupted"

reactjs - 错误 "TypeError: element.type is undefined"isMuiElement

javascript - 如何在reactjs中使单选按钮工作并输出值

python - 如何测试 Python 函数是否引发异常?