为什么使用ReactTestUtils将iframe渲染成jsdom不提供contentWindow?

我试图testing一个呈现iframe的React组件,并直接向该iframe注入标记。 (我不想在iframe中加载一个URL。)

该组件实际上在浏览器中运行得非常好,但是迄今为止对其进行testing似乎是不可能的。 我不知道为什么。

这是一个缩短的testing用例,certificate失败。

// 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。 你应该能够使用节点运行上面的代码。

我彻底地testing了你的代码,最终发现问题是ReactTestUtils.renderIntoDocument

ReactTestUtils.renderIntoDocument为Component创build一个容器,但不附加到DOM(因此,为什么contentWindow对于iframe元素为空)。 如果您阅读ReactTestUtils源代码中的注释,您会注意到他们正在考虑重命名renderIntoDocument因为从技术上讲它不会! 看来,解决scheme是直接使用ReactDOM

以下是来自ReactTestUtils源代码的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); }, } 

在testing用例中使用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的文档中没有提到这太糟糕了。

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

检查这个代码:

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