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.
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.
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.