`window` 没有暴露给 Jest [英] `window` is not being exposed to Jest

查看:27
本文介绍了`window` 没有暴露给 Jest的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

 失败 src/js/components/__tests__/Controls.test.jsx● 测试套件运行失败参考错误:窗口未定义

Controls.jsx:

import { Unwrapped as Controls } from '../Controls'描述('<MyInterestsControls/>', () => {it('应该用夹具数据渲染组件', () => {const 组件 = 浅(<UnwrappedMyInterestControls仪表板数据={仪表板数据}loadingFlags={{ 控件:false }}/>)期望(组件). toMatchSnapshot()})})

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

import * as queryString from 'query-string'const flag = queryString.parse(window.location.search).flag ||'离开'^^^^^^ 这似乎是问题

我尝试导入 jsdom

import { JSDOM } from 'jsdom'

并实施提出的解决方案 这里在我的测试文件的顶部:

const { JSDOM } = require('jsdom');const jsdom = new JSDOM('<!doctype html><html><body></body></html>');const { 窗口 } = jsdom;函数 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 = 窗口;global.document = window.document;global.navigator = {用户代理:'node.js',};copyProps(窗口,全局);

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

如何正确地将诸如 windowdocument 之类的全局对象暴露给 Jest 测试?

相关的 package.json

 "脚本": {"test:watch": "NODE_ENV=test jest --watch"},...开发依赖":{..."jest": "^20.0.4","jest-mock": "^21.2.0","jsdom": "^11.0.0",...},...开玩笑":{详细":真实,"collectCoverageFrom": ["src/js/helpers/preparePayload.js","src/js/components-ni","!**/node_modules/**",!**/dist/**"],覆盖阈值":{全球的": {声明":50,分支":50,功能":50,行":75}},"testEnvironment": "jest-environment-node"}

解决方案

更新:

<块引用>

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

您的问题取决于配置.

在你设定的那一刻:

testEnvironment":jest-environment-node"

您正在将默认配置从类似浏览器的 jest 更改为 jest-environment-node (node-like) 意味着您的测试将在NodeJs 环境

要解决它,您可以将 testEnvironment 设置为 jsdom
或者你从你的配置中删除 testEnvironment 以便它在你的 package.json 中采用默认值:

<代码> ...开玩笑":{详细":真实,collectCoverageFrom":[src/js/helpers/preparePayload.js",src/js/components-ni",!**/node_modules/**",!**/dist/**"],覆盖阈值":{全球":{声明":50,分支机构":50,功能":50,行":75}}}

这是他们在文档中所说的:

<块引用>

testEnvironment [string] # 默认:jsdom"

测试环境将用于测试.Jest 中的默认环境是通过 jsdom 实现类似浏览器的环境.如果你正在构建一个节点服务,可以使用node选项来使用类似node的环境相反.

<小时>

你需要`node`环境吗?

正如我所见,您的测试旨在在类似浏览器的环境下运行.

如果您需要一个明确的节点环境,最好使用 @jest-environment 隔离该情况:

/*** @jest-environment 节点*/test('在这个测试文件中使用节点', () => {期望(真).not.toBeNull();});

或者相反,如果您打算在 node 环境下运行测试

/*** @jest-environment jsdom*/test('在这个测试文件中使用 jsdom', () => {const element = document.createElement('div');期望(元素).not.toBeNull();});

<小时>

结论

这样你就可以避免手动导入 jsdom 和设置全局变量,jsdom 会自动模拟 DOM 实现.

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

I have a test that imports a component that in turn imports a helper file that uses the window object to pull out a query string parameter. I get the following error about 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 imports ./helpers/services.js which contains the following:

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

I have attempted to import jsdom

import { JSDOM } from 'jsdom'

And implement the solution presented here at the top of my test file:

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);

however I still get the error and it seems JSDOM's window object isn't exposed to the test.

How can I properly expose global objects like window or document to a jest test?

relevant 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"
  }

解决方案

UPDATE:

As mentioned by @RiZKiT in the comment bellow, since Jest v.27.0 the default test environment has changed from "jsdom" to "node".

Your problem relies on the configuration.

In the moment you set:

"testEnvironment": "jest-environment-node"

you are changing the default configuration from jest which is browser-like to jest-environment-node (node-like) meaning that your test will be run under a NodeJs environment

To solve it either you set your testEnvironment to jsdom
Or you remove the testEnvironment from your config so it will take the default value in yourpackage.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
      }
    }
  }

This is what they say in the documentation:

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.


Do you need the `node` environment?

As I could see, your tests are meant to be run under a browser-like environment.

If you ever need an explicit node environment, better you isolate that case using @jest-environment:

/**
 * @jest-environment node
 */

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

or the other way around if you are meant to run the tests under node environment

/**
 * @jest-environment jsdom
 */

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


Conclusion

With this you can avoid importing jsdom manually and setting global variables, jsdom will mock the DOM implementation automatically.

If you need to change the environment for your tests use the notation @jest-environment

这篇关于`window` 没有暴露给 Jest的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆