How to Test Form in React: Simple Guide with Examples
To test a form in React, use
React Testing Library to simulate user input and form submission, then check if the expected behavior or output occurs. Use fireEvent or userEvent to fill inputs and submit the form, and expect assertions to verify results.Syntax
Testing a React form involves rendering the form component, simulating user actions like typing and submitting, and asserting the expected outcomes.
render(): Renders the component for testing.fireEventoruserEvent: Simulates user input and events.screen.getByLabelText(): Selects form inputs by their label.expect(): Checks if the output or behavior matches expectations.
javascript
import { render, screen, fireEvent } from '@testing-library/react'; import FormComponent from './FormComponent'; test('form submission', () => { render(<FormComponent />); const input = screen.getByLabelText('Name'); fireEvent.change(input, { target: { value: 'Alice' } }); const submitButton = screen.getByRole('button', { name: /submit/i }); fireEvent.click(submitButton); expect(screen.getByText('Hello, Alice')).toBeInTheDocument(); });
Example
This example shows a simple React form that takes a name input and displays a greeting after submission. The test simulates typing a name and clicking submit, then checks if the greeting appears.
javascript
import React, { useState } from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; function GreetingForm() { const [name, setName] = useState(''); const [greeting, setGreeting] = useState(''); const handleSubmit = (e) => { e.preventDefault(); setGreeting(`Hello, ${name}`); }; return ( <div> <form onSubmit={handleSubmit} aria-label="greeting-form"> <label htmlFor="name-input">Name</label> <input id="name-input" value={name} onChange={(e) => setName(e.target.value)} aria-label="Name" /> <button type="submit">Submit</button> </form> {greeting && <p>{greeting}</p>} </div> ); } // Test test('shows greeting after form submission', () => { render(<GreetingForm />); const input = screen.getByLabelText('Name'); fireEvent.change(input, { target: { value: 'Alice' } }); const button = screen.getByRole('button', { name: /submit/i }); fireEvent.click(button); expect(screen.getByText('Hello, Alice')).toBeInTheDocument(); });
Output
The test passes, confirming the greeting 'Hello, Alice' appears after submitting the form with the name input.
Common Pitfalls
Common mistakes when testing React forms include:
- Not using
fireEventoruserEventto simulate real user input, leading to tests that don't reflect actual usage. - Forgetting to prevent default form submission behavior in the component, which can cause test failures.
- Selecting inputs incorrectly, such as using
getByTextinstead ofgetByLabelText, which is less reliable and less accessible. - Not waiting for asynchronous updates if the form triggers async actions.
Example of wrong and right ways:
javascript
/* Wrong: Changing input value directly without fireEvent */ input.value = 'Alice'; /* Right: Using fireEvent to simulate user typing */ fireEvent.change(input, { target: { value: 'Alice' } });
Quick Reference
| Step | Description | Example Function |
|---|---|---|
| Render form | Render the form component to test | render() |
| Select input | Find input by label for accessibility | screen.getByLabelText('Name') |
| Simulate input | Change input value like a user | fireEvent.change(input, { target: { value: 'text' } }) |
| Submit form | Click submit button | fireEvent.click(button) |
| Assert result | Check expected output or behavior | expect(...).toBeInTheDocument() |
Key Takeaways
Use React Testing Library's render and fireEvent to simulate user input and form submission.
Always select inputs by their labels for accessibility and reliable tests.
Prevent default form submission in your component to avoid test errors.
Avoid directly changing input values without events; simulate real user actions.
Check the UI updates or side effects after form submission with expect assertions.