`window` 没有暴露给 Jest [英] `window` is not being exposed to 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 对象没有暴露给测试.
如何正确地将诸如 window
或 document
之类的全局对象暴露给 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屋!