在基于jsdom的testing中调用setState导致“无法在工作线程中呈现标记”错误
我正在使用我自己的小型“虚拟浏览器”实用程序在jsdom下testing我的React组件。 工作得很好,直到我想setState
。 例如,当testing儿童年龄input控件时:
describe('rendering according to the draft value', function () { var component; beforeEach(function () { component = TestUtils.renderIntoDocument( React.createElement(ChildrenInput, {value: []}) ); component.setState({draft: [{age: null}, {age: null}]}, done); }); it('overrides the value property for the count', function () { assert.strictEqual(component.refs.count.props.value, 2); }); it('overrides the value property for the ages', function () { assert.strictEqual(component.refs.age1.props.value, null); }); });
…在我得到的setState
行上:
未捕获的错误:不变的违规:dangerouslyRenderMarkup(…):无法在工作线程中呈现标记。 当unit testing需要React或服务器渲染使用React.renderToString时,确保window
和document
全局可用。
我知道window
和document
全局的确是由基于TestBrowser
的TestBrowser设置的,就像那样:
global.document = jsdom.jsdom('<html><body></body></html>', jsdom.level(1, 'core')); global.window = global.document.parentWindow;
我甚至试图将setState
换成setTimeout(..., 0)
。 这没有帮助。 我怎样才能testing状态变化的工作?
在加载时,React确定它是否可以使用DOM,并将其作为布尔值存储。
var canUseDOM = !!( typeof window !== 'undefined' && window.document && window.document.createElement ); ExecutionEnvironment.canUseDOM = canUseDOM;
这意味着如果在这些条件成立之前加载它,则认为它不能使用DOM。
你可以在你之前把猴子打补丁。
require('fbjs/lib/ExecutionEnvironment').canUseDOM = true
或者你可以假装它:
global.window = {}; global.window.document = {createElement: function(){}};
或者确保在设置JSDOM之前不加载React,这是我唯一的方法,但是这也是最困难和最容易出错的。
或者你可以把这个问题作为一个问题来报告,或者检查一下jess的来源,看看它是如何解决的。
如果你使用Mocha和Babel,你需要在编译器评估React代码之前设置jsdom。
// setup-jsdom.js var jsdom = require("jsdom"); // Setup the jsdom environment // @see https://github.com/facebook/react/issues/5046 global.document = jsdom.jsdom('<!doctype html><html><body></body></html>'); global.window = document.defaultView; global.navigator = global.window.navigator;
用--require
arg:
$ mocha --compilers js:babel/register --require ./test/setup-jsdom.js test/*.js
见https://github.com/facebook/react/issues/5046#issuecomment-146222515
资源
我也有使用巴别testingES6代码的这个错误。 重点是import React from 'react'
和const React = require('react')
import React from 'react'
是有区别的。 如果您使用的是import
语法,那么您的所有导入都会在其他任何事情之前发生,所以您不能在之前模拟window
或document
。
所以第一点是要在testing中取代import
(在哪里是重要的)
第二点是通过使用global.navigator = global.window.navigator
来模拟global.navigator = global.window.navigator
。
希望它会帮助别人。
直到我尝试在mocha命令中要求使用jsdom-global时,没有任何工作对我有用:
--require jsdom-global/register
来源: https : //github.com/rstacruz/jsdom-global/blob/master/README.md#mocha