Asynchronous Query Not Awaited
ID |
javascript.testing_library_query_not_awaited |
Severity |
high |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Reliability |
Language |
JavaScript |
Tags |
async, reliability, testing |
Description
Reports a Testing Library findBy* or findAllBy* query written as a bare statement.
The find* family is the asynchronous half of the query API: it retries until the element appears and returns a promise, where get* and query* answer at once. A statement that neither awaits nor returns that promise starts the polling and throws the handle away.
Only a discarded result is reported. An await, a return, a .then() continuation and an argument position all hand the promise on. A result assigned to a variable is not reported either, even without an await: the variable may be awaited on a later line, which is a legitimate way to start two queries in parallel.
javascript.promise_result_ignored cannot host this — it resolves the callee to a locally declared async function, and these queries come from the library.
Rationale
// Bad
it('shows the alert', async () => {
submit();
screen.findByRole('alert'); // starts polling, waits for nothing
expect(log.entries).toHaveLength(1);
});
-
Nothing is waited for, so the assertions that follow run against the page as it was before the element arrived.
-
When the element never appears, the query’s rejection has no owner: it becomes an unhandled rejection charged to a later test, or a bare "test timed out" that never names the missing element.
-
The two query families differ by four characters, so the mistake reads as correct code in review.
-
The result depends on how fast the machine is, which is what makes this a leading cause of tests that pass locally and fail in CI.