Example unit tests - React Testing Library
Last updated: November 26, 2024
We recommend using React Testing Library for all your unit/integration testing needs.
// SimpleLoginForm.js
import React from 'react';
const SimpleLoginForm = ({ onSubmit }) => {
const [error, setError] = React.useState('');
function handleSubmit(event) {
event.preventDefault();
const {
usernameInput: { value: username },
passwordInput: { value: password },
} = event.target.elements;
if (!username) {
setError('username is required');
} else if (!password) {
setError('password is required');
} else {
setError('');
onSubmit({ username, password });
}
}
return (
<div>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="usernameInput">Username</label>
<input id="usernameInput" />
</div>
<div>
<label htmlFor="passwordInput">Password</label>
<input id="passwordInput" type="password" />
</div>
<button type="submit">Submit</button>
</form>
{error ? <div role="alert">{error}</div> : null}
</div>
);
};
export default SimpleLoginForm;
// SimpleLoginForm.unit.spec.jsx
import React from 'react';
import { expect } from 'chai';
import sinon from 'sinon';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import SimpleLoginForm from '../../components/SimpleLoginForm';
describe('my-application', () => {
describe('SimpleLoginForm', () => {
it('calls onSubmit with the username and password when submit is clicked', () => {
const handleSubmit = sinon.spy();
const screen = render(<SimpleLoginForm onSubmit={handleSubmit} />); // alternatively `const { getByLabelText, getByText } = render(<SimpleLoginForm onSubmit={handleSubmit} />);`
const user = { username: 'user123', password: 'password123' };
userEvent.type(screen.getByLabelText(/username/i), user.username);
userEvent.type(screen.getByLabelText(/password/i), user.password);
userEvent.click(getByText(/submit/i));
expect(handleSubmit.callCount).to.equal(1); // alternatively `expect(handleSubmit.calledOnce).to.be.true()` works as well
expect(handleSubmit.calledWith(user)).to.be.true(); // for more explicit testing we can use `calledWithExactly` in place of `calledWith`
});
});
});
We have written a "happy path" test for a SimpleLoginForm
component. Let's break down this test.
Setup
...
const handleSubmit = sinon.spy();
const screen = render(<SimpleLoginForm onSubmit={handleSubmit} />);
const user = { username: 'user123', password: 'password123' };
...
We mock the
handleSubmit
function.We instantiate the
SimpleLoginForm
component, passing in the mockedhandleSubmit
as a prop.We use the
render
function from RTL to produce actual DOM nodes.We get our
screen
utility from the return value ofrender
.We define the user data for reuse later in the test.
Note: In this example we gained access to our query functions through the return value from render
. The global named screen
import currently does not work in our test environment. Alternatively, you can destructure the return value to gain direct access to the RTL query functions.
DOM interactions and queries
...
userEvent.type(screen.getByLabelText(/username/i), user.username);
userEvent.type(screen.getByLabelText(/password/i), user.password);
userEvent.click(getByText(/submit/i));
...
Unit tests should be isolated
Components should use a unique label and text for each test.
Note: We can use the query functions that we destructured from render
to find the input elements in our component by their label text. Testing Library
provides a utility called userEvent that allows us to interact with the DOM nodes. We leverage the type
interaction to enter our username and password into each respective field, then the click
function to submit after querying with the submit button text.
Assertions
...
expect(handleSubmit.callCount).to.equal(1); // alternatively `expect(handleSubmit.calledOnce).to.be.true()` works as well
expect(handleSubmit.calledWith(user)).to.be.true(); // for more explicit testing we can use `calledWithExactly` in place of `calledWith`
...
To conclude this test we need to check that our onSubmit
function fired and received the correct data.
Help and feedback
Get help from the Platform Support Team in Slack.
Submit a feature idea to the Platform.