Open
Description
@testing-library/react
version: 16.2.0- Testing Framework and version: vitest
- DOM Environment: chromium, via
@vitest/browser
Relevant code or config:
import { use } from 'react';
import { render, screen } from '@testing-library/react';
function TestComponent({ promise }: { promise: Promise<unknown> }) {
use(promise);
return 'test';
}
test('render', async () => {
const promise = new Promise((resolve) => {
setTimeout(resolve, 10);
});
render(<TestComponent promise={promise} />);
await expect(screen.findByText('test')).resolves.toBeInTheDocument();
});
What you did:
I use use(promise)
in components.
What happened:
I get the following error when rendering via @testing-library/react
's render()
.
A component suspended inside an `act` scope, but the `act` call was not awaited. When testing React components that depend on asynchronous data, you must await the result:
await act(() => ...)
The test also fails:
Caused by: TestingLibraryElementError: Unable to find an element with the text: test. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible.
Reproduction:
See "Relevant code or config" above.
Adding an un-awaited act
manually does not resolve the issue either:
import { use } from 'react';
import { act, render, screen } from '@testing-library/react';
function TestComponent({ promise }: { promise: Promise<unknown> }) {
use(promise);
return 'test';
}
test('render', async () => {
const promise = new Promise((resolve) => {
setTimeout(resolve, 10);
});
act(() => {
render(<TestComponent promise={promise} />);
});
await expect(screen.findByText('test')).resolves.toBeInTheDocument();
});
Problem description:
I should never get any act warnings when using @testing-library/react
functions.
Suggested solution:
As the warning explicitly advises, awaiting the act
call fixes the warning/test:
import { use } from 'react';
import { act, render, screen } from '@testing-library/react';
function TestComponent({ promise }: { promise: Promise<unknown> }) {
use(promise);
return 'test';
}
test('render', async () => {
const promise = new Promise((resolve) => {
setTimeout(resolve, 10);
});
await act(() => {
render(<TestComponent promise={promise} />);
});
await expect(screen.findByText('test')).resolves.toBeInTheDocument();
});
AFAICT, in React 19, act
always returns a promise, so it may be best to always await
it.
Fixing the issue would make render
async, which may be a breaking change.
https://github.com/testing-library/react-testing-library/blob/main/src/pure.js#L149
Metadata
Metadata
Assignees
Labels
No labels