Simulating click on document ReactJS/JSDom

So I am writing some tests for code that adds a click event on the document. I am using JSDom, ReactJS, and Mocha/Chai setup. I have tried the following code in a test:

document.addEventListener('click', function() {
  console.log('test');
});
React.addons.TestUtils.Simulate.click(document);
//also tried React.addons.TestUtils.Simulate.click(document.body);

however this code does not produce the echo that I am expecting.

Is there a way to simulate click, keyup, etc... on the document with JSDom and ReactJS?

UPDATE

To Nick answers, I have tried adding this code to the test:

document.body.addEventListener('click', function() {
  console.log('test');
});

document.body.click();

and I till don't get the console log output. I am not sure if there is some issue with JSDom and doing this type of thing.

If I can't unit test this code, that's fine, there is already some code that I can't unit test right now (code that requires a real DOM to be able to get widths, heights, etc...) but I would like to be able to unit test most of the code (and I am not interested in using PhantomJS for unit testing). My integration tests will cover that type of code.

UPDATE2

Another thing to note is that is that when I console.log(document); I see object attached to the _listeners property for click so I know the event is being attached, it just does not seem to be executing.

728x90

4 Answers Simulating click on document ReactJS/JSDom

Update: document.body.click will work in a browser, but for jsdom you need to manually create the event:

document.body.addEventListener('click', function() {
  console.log('test');
});

var evt = document.createEvent("HTMLEvents");
evt.initEvent("click", false, true);
document.body.dispatchEvent(evt)

The above code is working for me in Jest and should work with "solo" jsdom as well.

Autumn 2018 holiday update 🦃

The tools around simulating events have gotten a great deal better. I've currently shifted my approach to use the excellent react-testing-library to render my components and dispatch events:

import {render, fireEvent} from 'react-testing-library'

test('example', () => {
  const handleClick = jest.fn()

  const {getByText} = render(<div><button onClick={handleClick}>Click Me</button></div>)
  fireEvent.click(getByText('Click Me'))

  expect(handleClick).toHaveBeenCalled()
})

While I still believe in end to end tests with something like puppeteer or selenium (or cypress!) provide the highest level of confidence that something actually works, this provides a huge amount of value without polluting tests with manual event creation.

4 months ago

React.addons.TestUtils.Simulate only works with virtual events. If you want to dispatch native events, you can do that with the DOM api directly.

When simulating a click, if you have a component which renders this:

<div>
   <button onClick={alert}>click me</button>
</div>

And you have a reference to the <button/> in a variable called 'buttonEl', and run this:

React.addons.TestUtils.Simulate.click(buttonEl, 'hello world');

You'd get an alert with 'hello world' in it. All test utils does is create the virtual event, and let it bubble up the virtual dom tree, calling the event handlers along the way.

2 year ago

Simply create an Event and dispatch it:

// Add an event listeners to the document
document.addEventListener('click', function() {
    console.log('test');
});

// Create a new `click` event and `dispatch` it
var event = new MouseEvent('click')
document.dispatchEvent(event)

3 year ago

Event.initEvent() is deprecated and the Event() constructor should now be used instead.

// Add a click event listener to the document
document.addEventListener('click', function() {
    console.log('test');
});

// Create a click event with optional event initialisers: bubbles, cancelable and composed
var evt = new Event('click', { bubbles: false, cancelable: false, composed: false });

// Event can then be dispatched against any element, not only the document
document.dispatchEvent(evt);
myDiv.dispatchEvent(evt);

Browser support is good with the exception of Internet Explorer.

References:

3 months ago