简体   繁体   中英

In jest/enzyme, how do you simulate a click on an element with eventListener bound by [element].addEventListener (not window.addEventListener)?

In react, when you have an element with an onClick prop, it's easy to use Enzyme's .simulate("click") method to click it. However, there's an example in my codebase where an element is referenced by React's "ref" prop, and then that element's .addEventListener is invoked to bind an event handler to it.

I've provided a code example: https://codesandbox.io/s/1z4xok048j

The key line is this:

if (this.refs.hey) {
  this.refs.hey.addEventListener("click", this.handleClick);
}

In the code example, the eventHandler is not bound until componentDidUpdate is run, so if you click on the "click me to increment counter" div, the child element receives new props and its componentDidUpdate triggers. Then if you click on the Child element, its eventHandler triggers as expected. However, I can't reproduce this behavior in my Enzyme/Jest tests.

I've done the obvious .simulate("click") method from Enzyme and it does not work; when I change from using refs and the event listeners to using an onClick , .simulate("click") works as expected. However, removing the refs causes other bugs to surface and I haven't been able to figure out why, so I'd prefer to find out a way to simulate clicking the button.

The code for .simulate("click") actually looks for the onClick function and passes the params to it, there is no 'actual' click going on. You might have to mock the addEventListener functions with something like

// Set-up event listener mock
const map = {};
window.addEventListener = jest.genMockFn().mockImpl((event, callback) => {
  map[event] = callback;
});

The answer is actually really simple. The general idea is to .find the node and get the underlying HTML DOM Node with .getDOMNode() . Once you have it, replace its .addEventListener like so:

const map ={};
const namedByRefComponent = component.find(".some-class-name");
const namedByRefDomNode = namedByRefComponent.getDOMNode();

namedByRefDomNode.addEventListener = jest.fn().mockImplementation((event, cb) => {
    map[event] = cb;
});

after that, your DOM node's event handlers can be found in map and you can invoke them in the tests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM