![](/img/trans.png)
[英]Testing error thrown by a React component using testing-library and jest
[英]Trouble testing React component render with Jest and Testing-Library because there's no Document available to Jest
我正在尝试使用 Jest 和 React-Testing-Library 来测试 React 组件 <Main/> 的呈现,但是当我运行测试时,处理fetch
的client
会抛出错误,因为它正在使用document.querySelector()
-但是当 Jest 运行时没有document
,因为没有呈现浏览器。
我的目标是:设置 Jest 和 RTL,以便我们可以开始为所有组件编写测试。 我想首先验证我可以无错误地渲染<Main/>
。
这是Client.js
class Client {
constructor() {
console.log("Client initializing")
console.log(document.querySelector('meta[name="csrf-token"]'))
console.log(document)
this.token = document.querySelector('meta[name="csrf-token"]').content;
}
getData(path) {
return (
fetch(`${window.location.origin}${path}`, {
headers: { "X-CSRF-Token": this.token }
})
)
}
submitData(path, method, body) {
return (
fetch(`${window.location.origin}${path}`, {
method: method,
headers: { "X-CSRF-Token": this.token },
body: body
})
)
}
deleteData(path) {
return (
fetch(`${window.location.origin}${path}`, {
method: "DELETE",
headers: {
"X-CSRF-Token": this.token,
"Content-Type": "application/json"
}
})
)
}
}
export default Client;
这是main.test.js
:
/**
* @jest-environment jsdom
*/
import React from 'react';
import { render, screen } from '@testing-library/react';
// import userEvent from '@testing-library/user-event';
import Main from '../../app/javascript/components/Main';
test("renders without errors", ()=> {
render(<Main/>);
});
我还设置了一个setupTests.js
文件:
require("jest-fetch-mock").enableMocks();
import '@testing-library/jest-dom';
并在package.json
中调用它:
"jest": {
"roots": [
"test/javascript"
],
"moduleNameMapper": {
"\\.(svg|png)": "<rootDir>/__mocks__/svgrMock.js"
},
"automock": false,
"setupFilesAfterEnv": [
"./test/javascript/setupTests.js"
]
},
我还在jest.config.js
文件中设置了 testEnvironment testEnvironment: 'jsdom'
。
当我运行yarn jest
时,出现以下错误: TypeError: Cannot read properties of null (reading 'content')
which points to this.token = document.querySelector('meta[name="csrf-token"]').content;
在Client.js
这对我来说很有意义,因为它正在寻找 DOM 元素,但是 Jest 在 Node 中运行(没有浏览器渲染)所以找不到 DOM。
我想我需要:
document
,以便应用程序可以在不在浏览器中呈现的情况下运行。 不知道该怎么做。setupTests.js
),包括许多类似这样的排列:import { TextDecoder, TextEncoder } from 'util'
global.TextEncoder = TextEncoder
global.TextDecoder = TextDecoder
//variables to mock a csrf token
const csrfToken = 'abcd1234';
const virtualDom = `
<!doctype html>
<head>
<meta name="csrf-token" content="${csrfToken}" />
</head>
<body>
<form>
<input type="hidden" name="csrf-token" value=${csrfToken}>
</form>
</body>
</html>
`;
const { JSDOM } = require("jsdom");
//mock a page passing virtualDom to JSDOM
const page = new JSDOM(virtualDom);
const { window } = page;
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);
但是global.window = window
似乎从来没有工作,因为如果我声明然后立即console.log(global.window, window)
我得到 null 然后是 window。
我也不知道如何正确地做到这一点,但我也知道降级 React 可能是错误的路径。
yarn
Jest 在后台使用jsdom
,所以“没有 DOM”是不正确的,但是所有页面都在测试中实例化了 - 没有来自服务器的东西(并且jsdom
既不支持导航以从服务器请求真实页面然后继续测试).
因此我们需要在测试中渲染元素:
render(<>
<meta name="csrf-token" content="mocked-token" />
<Main/>
</>);
虽然我不确定为什么您在 globalSetup 中尝试的完整页面替换不起作用,但也许 Jest 不允许以这种方式覆盖 JSDOM 实例并且在运行 globalSetup.js 之前绑定。
事实证明,我必须模拟所有进入从 Main 呈现的组件的数据。 (除了 CSRF 令牌模拟)
一旦我这样做了,其他一切就都到位了。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.