21

我正在使用我自己的微型“虚拟浏览器”实用程序在jsdom下测试我的 React 组件。工作得很好,直到我尝试。例如,在测试儿童年龄输入控件时:setState

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(...):无法在工作线程中呈现标记。在单元测试时需要 React 或使用 React.renderToString 进行服务器渲染之前,请确保window并在全球范围内可用。document

我知道全局变量确实是由 jsdom-based 设置的window,如下所示:documentTestBrowser

global.document = jsdom.jsdom('<html><body></body></html>', jsdom.level(1, 'core'));
global.window = global.document.parentWindow;

我什至试图包装setStatesetTimeout(..., 0). 它没有帮助。如何使测试状态更改起作用?

4

4 回答 4

21

在加载时,React 确定它是否可以使用 DOM,并将其存储为布尔值。

var canUseDOM = !!(
  typeof window !== 'undefined' &&
  window.document &&
  window.document.createElement
);
ExecutionEnvironment.canUseDOM = canUseDOM;

这意味着如果它在这些条件成立之前被加载,它假定它不能使用 DOM。

您可以在 beforeEach 中对其进行修补。

require('fbjs/lib/ExecutionEnvironment').canUseDOM = true

或者你可以先伪造它:

global.window = {}; global.window.document = {createElement: function(){}};

或者确保在设置 JSDOM 之前不加载 React,这是我认为的唯一方法,但它也是最困难和最容易出错的方法。

或者您可以将此作为问题报告,或检查 jest 的来源并查看它是如何解决的。

于 2014-11-11T18:49:21.853 回答
10

如果你使用 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;

使用--requirearg:

$ mocha --compilers js:babel/register --require ./test/setup-jsdom.js test/*.js

https://github.com/facebook/react/issues/5046#issuecomment-146222515

资源

于 2015-10-07T15:30:17.253 回答
3

我在使用 Babel 测试 ES6 代码时也遇到了这个错误。import React from 'react'关键是和之间有区别const React = require('react')。如果您使用的是import语法,那么您的所有导入都会在其他任何事情之前发生,因此您不能模拟windowdocument之前。

所以首先是在测试中替换importrequire(重要的地方)

第二位是global.navigator使用global.navigator = global.window.navigator.

希望它会帮助某人。

于 2015-07-09T13:40:24.380 回答
1

在我尝试在 mocha 命令中要求 jsdom-global 之前,没有什么对我有用:

--require jsdom-global/register

来源:https ://github.com/rstacruz/jsdom-global/blob/master/README.md#mocha

于 2017-01-16T00:37:21.657 回答