摘要:
我试图在其componentWillMount中测试一个侦听本机DOM事件的React组件.
我发现jsdom(@ 8.4.0)在调度事件和添加事件监听器时不能正常工作.
window.addEventListener('click',() => { throw new Error("success") }) const event = new Event('click') document.dispatchEvent(event) throw new Error('failure')
这引发了“失败”.
语境:
如果上述风险为XY problem,我想提供更多背景信息.
这是我试图测试的组件的提取/简化版本. You can see it working on Webpackbin.
import React from 'react' export default class Example extends React.Component { constructor() { super() this._onDocumentClick = this._onDocumentClick.bind(this) } componentWillMount() { this.setState({ clicked: false }) window.addEventListener('click',this._onDocumentClick) } _onDocumentClick() { const clicked = this.state.clicked || false this.setState({ clicked: !clicked }) } render() { return <p>{JSON.stringify(this.state.clicked)}</p> } }
这是我正在尝试编写的测试.
import React from 'react' import ReactDOM from 'react-dom' import { mount } from 'enzyme' import Example from '../src/example' describe('test',() => { it('test',() => { const wrapper = mount(<Example />) const event = new Event('click') document.dispatchEvent(event) // at this point,I expect the component to re-render,// with updated state. expect(wrapper.text()).to.match(/true/) }) })
为了完整起见,这是我的test_helper.js初始化jsdom:
import { jsdom } from 'jsdom' import chai from 'chai' const doc = jsdom('<!doctype html><html><body></body></html>') const win = doc.defaultView global.document = doc global.window = win Object.keys(window).forEach((key) => { if (!(key in global)) { global[key] = window[key] } })
复制案例:
我这里有一个责备案例:https://github.com/jbinto/repro-jsdom-events-not-firing
git clone https://github.com/jbinto/repro-jsdom-events-not-firing.git
cd repro-jsdom-events-not-firing
npm安装
npm测试
解决方法
您正在将事件分派给文档,因此窗口将无法看到它,因为默认情况下它不会冒泡.您需要创建气泡设置为true的事件.例:
var jsdom = require("jsdom"); var document = jsdom.jsdom(""); var window = document.defaultView; window.addEventListener('click',function (ev) { console.log('window click',ev.target.constructor.name,ev.currentTarget.constructor.name); }); document.addEventListener('click',function (ev) { console.log('document click',ev.currentTarget.constructor.name); }); console.log("not bubbling"); var event = new window.Event("click"); document.dispatchEvent(event); console.log("bubbling"); event = new window.Event("click",{bubbles: true}); document.dispatchEvent(event);