jsdom:dispatchEvent/addEventListener 似乎不起作用 [英] jsdom: dispatchEvent/addEventListener doesn't seem to work

查看:17
本文介绍了jsdom:dispatchEvent/addEventListener 似乎不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

总结:

我正在尝试测试在其 componentWillMount 中侦听本机 DOM 事件的 React 组件.

I am attempting to test a React component that listens to native DOM events in its componentWillMount.

我发现 jsdom (@8.4.0) 在调度事件和添加事件侦听器方面没有按预期工作.

I'm finding that jsdom (@8.4.0) doesn't work as expected when it comes to dispatching events and adding event listeners.

我能提取的最简单的代码:

The simplest bit of code I can extract:

window.addEventListener('click', () => {
  throw new Error("success")
})

const event = new Event('click')
document.dispatchEvent(event)

throw new Error('failure')

这会引发失败".

上下文:

冒着上述成为 XY 问题的风险,我想提供更多背景信息.

At risk of the above being an XY problem, I want to provide more context.

这是我尝试测试的组件的提取/简化版本.你可以看到它在 Webpackbin 上运行.

Here is an extracted/simplified version of the component I'm trying to test. 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>
  }
}

这是我正在尝试编写的测试.

Here is the test I'm trying to write.

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:

Just for completeness, here is my test_helper.js which initializes 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

I have a repro case here: https://github.com/jbinto/repro-jsdom-events-not-firing

<代码>git 克隆 https://github.com/jbinto/repro-jsdom-events-not-firing.gitcd repro-jsdom-events-not-firing安装npm 测试

推荐答案

这里的问题是 jsdom 提供的 document 实际上并没有被 Enzyme 测试使用.

The problem here was that the jsdom-provided document isn't actually getting used by Enzyme tests.

Enzyme 使用 React.TestUtils 中的 renderIntoDocument.

Enzyme uses renderIntoDocument from React.TestUtils.

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);
  },
// ...
}

这意味着我们所有的 Enzyme 测试都不是针对 jsdom 提供的 document 执行的,而是针对与任何文档分离的 div 节点执行的.

This means all of our Enzyme tests are not executed against the jsdom-provided document, but instead into a div node detached from any document.

Enzyme 仅将 jsdom 提供的 document 用于静态方法,例如getElementById 等,不用于存储/操作 DOM 元素.

Enzyme only uses the jsdom-provided document for static methods, e.g. getElementById etc. It is not used to store/operate on DOM elements.

为了进行这些类型的测试,我实际上调用了 ReactDOM.render,并使用 DOM 方法对输出进行断言.

In order to do these kinds of tests I resorted to actually calling ReactDOM.render, and asserting on the output using DOM methods.

这篇关于jsdom:dispatchEvent/addEventListener 似乎不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆