act
The act
function is a utility provided by the React Testing Library that wraps around your code, ensuring that all updates related to state changes, effects, and other asynchronous actions are flushed before proceeding. This is crucial when testing components with asynchronous behavior, as it helps maintain a consistent and predictable test environment.
A simple example of using act
with Jest is shown below:
import React, { useState } from 'react';
import { render, fireEvent, act } from '@testing-library/react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>{count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
test('increments the counter when the button is clicked', async () => {
const { getByText } = render(<Counter />);
const incrementButton = getByText('Increment');
const counterDisplay = getByText('0');
await act(async () => {
fireEvent.click(incrementButton);
});
expect(counterDisplay.textContent).toBe('1');
});
In this example, we use the act
function to wrap the fireEvent.click
call, ensuring that the state update is completed before we check the updated value of the counter.
waitFor
The waitFor
function is another utility provided by the React Testing Library that helps deal with asynchronous behavior in your components. It is used when you need to wait for an element to appear or change, or when you expect some action to occur after a certain period of time.
waitFor
returns a Promise that resolves when the specified condition is met. It retries the condition every 50ms (by default) until it passes or times out after 1000ms (by default).
Here’s a simple example using waitFor
with Jest:
import React, { useEffect, useState } from 'react';
import { render, waitFor } from '@testing-library/react';
function AsyncMessage() {
const [message, setMessage] = useState('');
useEffect(() => {
const timer = setTimeout(() => {
setMessage('Hello, World!');
}, 500);
return () => clearTimeout(timer);
}, []);
return <p>{message}</p>;
}
test('displays the message after a delay', async () => {
const { getByText } = render(<AsyncMessage />);
await waitFor(() => {
expect(getByText('Hello, World!')).toBeInTheDocument();
});
});
In this example, the AsyncMessage
component sets a message after a 500ms delay. We use waitFor
to wait for the message to appear before checking that it is present in the document.