This rule raises an issue when a toMatchSnapshot() or toMatchInlineSnapshot() assertion is placed inside a Testing
Library async utility.
Testing Library async utilities wait for a condition to be met. In particular, waitFor and waitForElementToBeRemoved run
their callbacks immediately and retry them until the callback stops throwing or the timeout is reached.
When a snapshot assertion is used as that callback, it can run an unknown number of times while the UI is changing. Updating snapshots can then record transient output or create more snapshot entries than intended. The generated artifacts depend on retry timing, which makes the test unreliable and harder to review.
Wait for the relevant UI state with a regular assertion, then generate the snapshot once the async utility has resolved. The rule does not raise an issue for snapshot assertions placed after the wait.
import { render, waitFor } from '@testing-library/react';
test('shows the loaded panel', async () => {
const { container } = render(<Panel />);
await waitFor(() => {
expect(container).toMatchSnapshot(); // Noncompliant: the snapshot assertion can run again on every retry
});
});
import { render, screen, waitFor } from '@testing-library/react';
test('shows the loaded panel', async () => {
const { container } = render(<Panel />);
await waitFor(() => {
expect(screen.getByText('Ready')).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
import { render, waitFor } from '@testing-library/react';
test('renders the summary', async () => {
const { container } = render(<Summary />);
await waitFor(() => {
expect(container).toMatchInlineSnapshot(); // Noncompliant: retries can write unstable inline snapshots
});
});
import { render, screen, waitFor } from '@testing-library/react';
test('renders the summary', async () => {
const { container } = render(<Summary />);
await waitFor(() => {
expect(screen.getByText('Summary')).toBeInTheDocument();
});
expect(container).toMatchInlineSnapshot();
});