\`window\` 没有暴露给 Jest

新手上路,请多包涵

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

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

   ReferenceError: window is not defined

控件.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'

并在我的测试文件顶部实施了 此处 提供的解决方案:

 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 的 窗口 对象没有暴露给测试。

如何正确地将全局对象(如 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"
  }

原文由 1252748 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
1 个回答

正如@RiZKiT 在下面的评论中提到的,自 Jest v27.0 以来 ,默认测试环境 已从 "jsdom" 更改为 "node"

您的问题取决于配置。

在你设置的那一刻:

 "testEnvironment": "jest-environment-node"

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

To solve it either you set your testEnvironment to jsdom Or you remove the testEnvironment from your configuration, so it will take the default value in your 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 [字符串] # 默认值:“jsdom”

将用于测试的测试环境。 Jest 中的默认环境是通过 jsdom 的类似浏览器的环境。如果您正在构建节点服务,则可以使用节点选项来使用类似节点的环境。


## 你需要 `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

原文由 Jose Paredes 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题