为什么使用ReactTestUtils将iframe呈现为jsdom并不提供contentWindow?

时间:2016-03-16 00:17:48

标签: javascript node.js iframe jsdom

我试图测试呈现iframe并将标记直接注入该iframe的React组件。 (我没有尝试在iframe中加载网址。)

该组件在浏览器中实际上运行良好,但到目前为止编写测试似乎是不可能的。我不确定为什么。

这是一个缩短的测试案例,证明了失败。



    // Set up DOM
    var jsdom = require( 'jsdom' ).jsdom;
    global.document = jsdom( '' );
    global.window = document.defaultView;
    global.navigator = document.defaultView.navigator;

    // Prepare React
    var ReactTestUtils = require( 'react-addons-test-utils' );
    var React = require( 'react' );

    var Frame = React.createClass( {
      componentDidMount() {
        console.log( 'iframe loaded. adding content' );
        const iframe = this.refs.iframe;
        console.log( 'adding content to', iframe.contentWindow ); // Should not be null
        iframe.contentWindow.document.open();
        iframe.contentWindow.document.write( 'Hello World!' );
        iframe.contentWindow.document.close();
      },

      render() {
        console.log( 'rendering iframe' );
        return React.createElement( 'iframe', { ref: 'iframe' } );
      }
    } );

    // Render the component
    ReactTestUtils.renderIntoDocument( React.createElement( Frame ) );

要运行此功能,您需要安装以下npm软件包:jsdom,react,react-addons-test-utils。您应该能够使用node运行上面的代码。

2 个答案:

答案 0 :(得分:4)

我对您的代码进行了彻底的测试,结果发现问题是ReactTestUtils.renderIntoDocument

ReactTestUtils.renderIntoDocument为Component创建一个容器,但不再附加到DOM,因此contentWindowiframe元素的原因为ReactTestUtils。如果您阅读了renderIntoDocument来源中的评论,您会发现他们正在考虑重命名ReactDOM,因为从技术上讲,它不会! 似乎解决方案是直接使用ReactTestUtils

以下是var ReactTestUtils = { renderIntoDocument: function (instance) { var div = document.createElement('div'); // None of our tests actually require attaching the container to the // DOM, and doing so creates a mess that we rely on test isolation to // clean up, so we're going to stop honoring the name of this method // (and probably rename it eventually) if no problems arise. // document.documentElement.appendChild(div); return ReactDOM.render(instance, div); }, } 来源的一些代码:

ReactDOM

在您的测试用例中使用// Set up DOM var jsdom = require( 'jsdom' ).jsdom; global.document = jsdom( '' ); global.window = document.defaultView; global.navigator = document.defaultView.navigator; // Prepare React var ReactTestUtils = require( 'react-addons-test-utils' ); var React = require( 'react' ); var ReactDOM = require('react-dom') var Frame = React.createClass( { componentDidMount() { console.log( 'iframe loaded. adding content' ); const iframe = this.refs.iframe; console.log( 'adding content to', iframe.contentWindow ); // Should not be null iframe.contentWindow.document.open(); iframe.contentWindow.document.write( 'Hello World!' ); iframe.contentWindow.document.close(); // Should log "Hello World!" console.log(iframe.contentWindow.document.body.innerHTML); }, render() { console.log( 'rendering iframe' ); return React.createElement( 'iframe', { ref: 'iframe' } ); } } ); // Render the component // NOPE //ReactTestUtils.renderIntoDocument( React.createElement( Frame ) ); // YUP ReactDOM.render(React.createElement(Frame), document.body)

ReactTestUtils

Test.class的文档中没有提到这一点太糟糕了。

答案 1 :(得分:1)

在contentWindow可用之前,您需要将iframe附加到文档中。

检查此代码:

var iframe = document.createElement('iframe');
console.log(iframe.contentWindow);

document.body.appendChild(iframe);

console.log(iframe.contentWindow);