Jest asynchronous tests
Version baseline: Jest 30.x, with 30.4.2 as the current stable release at this review. Inspect the installed patch, Node.js support, module system, test environment, and transformer compatibility before changing configuration.
Make the test return or await the asynchronous work and assert the failure path explicitly. A test that finishes before its promise or callback runs is a false positive even when Jest reports it as passed.
Promise and async/await forms
test("resolves with a user", async () => {
await expect(loadUser()).resolves.toMatchObject({ id: "u1" });
});
test("rejects for an unknown user", async () => {
await expect(loadUser("missing")).rejects.toThrow("not found");
});
Equivalent direct assertions must return the promise:
test("returns data", () => {
return fetchData().then((data) => expect(data).toEqual(expected));
});
When a test expects a rejection or callback assertion, use
expect.assertions(1) or expect.hasAssertions() so a missing error path
cannot pass without running the assertion.
Callback form
Use the done callback only for APIs that genuinely use callbacks:
test("reads a file", (done) => {
readFile((error, value) => {
try {
expect(error).toBeNull();
expect(value).toBe("ok");
done();
} catch (assertionError) {
done(assertionError);
}
});
});
Do not combine done with async or a returned promise. That creates two
completion signals and often causes a timeout or confusing failure.
Diagnose a hang or false pass
- Find the first async boundary and check that the test awaits, returns, or
calls
doneexactly once. - Check rejected promises and callback errors are asserted.
- Check fake timers, polling, retries, and network mocks; hand timer work to
11ai-operator-jest-v30-timers. - Run the focused test with a useful timeout only while diagnosing. Fix the missing completion or cleanup instead of raising the global timeout.
- Run the test twice and then the relevant suite to catch leaked state.
Guardrails
- Do not add
--forceExitto hide unfinished async work. - Do not increase
testTimeoutglobally for one slow or stuck test. - Do not leave real network requests, servers, files, or timers open after the test; clean them in the appropriate lifecycle hook.