Simulate a button click in Jest
#1 Using Jest
This is how I use the Jest mock callback function to test the click event:
import React from 'react';
import { shallow } from 'enzyme';
import Button from './Button';
describe('Test Button component', () => {
it('Test click event', () => {
const mockCallBack = jest.fn();
const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));
button.find('button').simulate('click');
expect(mockCallBack.mock.calls.length).toEqual(1);
});
});
I am also using a module called enzyme. Enzyme is a testing utility that makes it easier to assert and select your React Components
#2 Using Sinon
Also, you can use another module called Sinon which is a standalone test spy, stubs and mocks for JavaScript. This is how it looks:
import React from 'react';
import { shallow } from 'enzyme';
import sinon from 'sinon';
import Button from './Button';
describe('Test Button component', () => {
it('simulates click events', () => {
const mockCallBack = sinon.spy();
const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));
button.find('button').simulate('click');
expect(mockCallBack).toHaveProperty('callCount', 1);
});
});
#3 Using Your own Spy
Finally, you can make your own naive spy (I don't recommend this approach unless you have a valid reason for that).
function MySpy() {
this.calls = 0;
}
MySpy.prototype.fn = function () {
return () => this.calls++;
}
it('Test Button component', () => {
const mySpy = new MySpy();
const mockCallBack = mySpy.fn();
const button = shallow((<Button onClick={mockCallBack}>Ok!</Button>));
button.find('button').simulate('click');
expect(mySpy.calls).toEqual(1);
});
Using Jest, you can do it like this:
test('it calls start logout on button click', () => {
const mockLogout = jest.fn();
const wrapper = shallow(<Component startLogout={mockLogout}/>);
wrapper.find('button').at(0).simulate('click');
expect(mockLogout).toHaveBeenCalled();
});
Solutions in accepted answer are being deprecated
#4 Calling prop directly
Enzyme simulate is supposed to be removed in version 4. The main maintainer is suggesting directly invoking prop functions, which is what simulate does internally. One solution is to directly test that invoking those props does the right thing; or you can mock out instance methods, test that the prop functions call them, and unit test the instance methods.
You could call click, for example:
wrapper.find('Button').prop('onClick')()
Or
wrapper.find('Button').props().onClick()
Information about deprecation: Deprecation of .simulate() #2173
Testing-library makes this easy for you with the click function.
It's part of the user-event
library that can be used with every dom environment (react, jsdom, browser, ...)
The example from the doc:
import React from 'react'
import {render, screen} from '@testing-library/react'
import userEvent from '@testing-library/user-event'
test('click', () => {
render(
<div>
<label htmlFor="checkbox">Check</label>
<input id="checkbox" type="checkbox" />
</div>,
)
userEvent.click(screen.getByText('Check'))
expect(screen.getByLabelText('Check')).toBeChecked()
})