All topics
Testingintermediate

Testing Asynchronous Components with findBy and waitFor

Learn how to correctly test components that update after an asynchronous operation, without relying on arbitrary timeouts.

Components that fetch data or otherwise update asynchronously (after a promise resolves, a timer fires, or a debounce settles) can't be tested with a synchronous assertion immediately after rendering or triggering an interaction, since the expected UI change hasn't happened yet at that exact moment. Testing Library provides two main tools for this: findBy* queries (which return a promise that resolves once a matching element appears, or rejects after a timeout) and waitFor (which repeatedly re-runs a callback until it stops throwing, or times out).

findBy/waitFor is like repeatedly and efficiently checking a mailbox every few minutes until a package actually arrives, versus deciding in advance to wait exactly one full day regardless of whether the package shows up in the first ten minutes or takes two days — the polling approach adapts to how long things actually take instead of guessing a fixed wait.

Key Concepts

1
findByText('Loaded data') is essentially getByText combined with retrying/waiting, making it the natural choice when you're waiting for a specific element to eventually appear. waitFor(() => expect(mockFn).toHaveBeenCalled()) is more general-purpose, useful for asserting arbitrary conditions (not just 'does this element exist') that need to eventually become true.
findByText('Loaded data')getByTextwaitFor(() => expect(mockFn).toHaveBeenCalled())
2
A critical anti-pattern to avoid is using an arbitrary fixed delay (await new Promise(r => setTimeout(r, 1000))) to 'wait long enough' for an async update — this makes tests slower than necessary in the common case and still flaky in the rare case where the operation takes longer than the guessed delay, whereas findBy*/waitFor poll efficiently and resolve as soon as the condition is actually met.
await new Promise(r => setTimeout(r, 1000))findBy*waitFor
3
Interviewers ask candidates to fix a flaky test that uses a hardcoded setTimeout delay to wait for an async update, expecting them to replace it with the appropriate findBy* or waitFor call and to explain why polling-based waiting is both faster on average and more reliable than a fixed guessed delay.
setTimeoutfindBy*waitFor