jsdom:dispatchEvent/addEventListener似乎不起作用
jsdom: dispatchEvent/addEventListener doesn't seem to work
摘要:
我正在尝试测试一个在其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问题的风险,我想提供更多上下文。
这是我尝试测试的组件的提取/简化版本。你可以看到它在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/)
})
})
为了完整起见,这是我初始化 jsdom 的test_helper.js
:
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 install
npm test
您正在将事件调度到document
,因此window
不会看到它,因为默认情况下它不会冒泡。您需要创建将bubbles
设置为 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.target.constructor.name,
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);
这里的问题是 jsdom 提供的document
实际上并没有被酶测试使用。
酶使用来自React.TestUtils
的renderIntoDocument
。
https://github.com/facebook/react/blob/510155e027d56ce3cf5c890c9939d894528cf007/src/test/ReactTestUtils.js#L85
{
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);
},
// ...
}
这意味着我们所有的酶测试都不会针对 jsdom 提供的document
执行,而是在与任何文档分离的div 节点中执行。
酶仅将 jsdom 提供的document
用于静态方法,例如 getElementById
等它不用于存储/操作 DOM 元素。
为了做这些类型的测试,我实际上调用了ReactDOM.render
,并使用DOM方法断言输出。
代码:https://github.com/LVCarnevalli/create-react-app/blob/master/src/components/datepicker
链接:ReactTestUtils.Simulate 无法通过 addEventListener 触发事件绑定?
元件:
componentDidMount() {
ReactDOM.findDOMNode(this.datePicker.refs.input).addEventListener("change", (event) => {
const value = event.target.value;
this.handleChange(Moment(value).toISOString(), value);
});
}
测试:
it('change empty value date picker', () => {
const app = ReactTestUtils.renderIntoDocument(<Datepicker />);
const datePicker = ReactDOM.findDOMNode(app.datePicker.refs.input);
const value = "";
const event = new Event("change");
datePicker.value = value;
datePicker.dispatchEvent(event);
expect(app.state.formattedValue).toEqual(value);
});
- electronic BrowserWindow的最小高度和宽度在hide()show()方法之后不起作用
- 监视函数从服务返回不起作用,但作用域函数起作用
- 幻灯片滚动javascript不起作用
- 简单的javascript在Shopify中不起作用
- Recaptcha在IE7和IE8中不起作用
- Ember Data DS.Model's set函数不起作用
- JsFiddle上的鼠标事件不起作用
- 我的AngularJS表达式没有'不起作用
- 点击按钮输入不起作用
- 面向对象的Javascript代码在IE7中不起作用
- 分部隐藏在jquery中不起作用
- 在phonegap应用程序内部重定向不起作用
- Array.length似乎不起作用;console.log则显示其他情况
- $ionicplatform内的$scope不;不起作用
- 我的javascript for循环不起作用
- Meteor-添加用户自定义字段的方法不起作用
- 为什么 .focus() 不起作用,而 .css(“color”,“red”) 在同一个选择器上起作用
- Textarea必需的attribut在javascript中不起作用
- 为什么javascript:void(0)在Firefox中不起作用
- 退出全屏不起作用