๐ฑ๏ธ User Interaction Testing in React
Testing how users interact with your components โ like clicking buttons, typing in forms, or submitting data โ is essential to ensure your app behaves correctly in real-world usage.
๐ฏ 1. Why Test User Interactions?
- Verify UI updates correctly on user actions
- Ensure form validation and submission logic works
- Prevent regressions in core UI functionality
โ๏ธ 2. fireEvent vs userEvent
fireEvent
: Simulates DOM events (basic, low-level)userEvent
: Simulates real user behavior (recommended)
๐งช 3. Example: Button Click
// Counter.js
export default function Counter() {
const [count, setCount] = React.useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
// Counter.test.js
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Counter from './Counter';
test('increments count on click', async () => {
render(<Counter />);
const button = screen.getByText('Increment');
await userEvent.click(button);
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});
โจ๏ธ 4. Example: Typing in Input
// Greeting.js
export default function Greeting() {
const [name, setName] = React.useState('');
return (
<div>
<input
placeholder="Enter name"
onChange={(e) => setName(e.target.value)}
/>
<p>Hello {name}</p>
</div>
);
}
// Greeting.test.js
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Greeting from './Greeting';
test('updates name on typing', async () => {
render(<Greeting />);
const input = screen.getByPlaceholderText('Enter name');
await userEvent.type(input, 'React');
expect(screen.getByText('Hello React')).toBeInTheDocument();
});
โ 5. Best Practices
- Use
userEvent
for more realistic simulations - Query elements the way users would (e.g., by role, label)
- Wrap async interactions in
await
- Check visible text and screen updates, not internal state
๐ Summary
- User interaction tests help you verify dynamic behaviors
userEvent
is better thanfireEvent
for simulating real usage- Test inputs, clicks, form submission, and validation thoroughly