Challenge 3: Why a Missing await Produces Flakiness — Possible Solution ==================================================================== screen.findByText(...) returns a PROMISE — it doesn't search for the element once and return immediately; it repeatedly retries the query over a short window of time (a few seconds by default), resolving as soon as a match appears, or rejecting if the timeout is reached first. If await is forgotten — e.g. writing expect(screen.findByText("Ada Lovelace")).toBeInTheDocument(); instead of expect(await screen.findByText("Ada Lovelace")).toBeInTheDocument(); — the expression screen.findByText(...) evaluates to the PROMISE OBJECT ITSELF, not the eventually-found element. toBeInTheDocument() then runs against that Promise object, not against a DOM element at all. Depending on the matcher and testing setup, this might immediately throw a clearly-wrong-looking error (a Promise is obviously not a DOM node) — OR, in some setups/matcher combinations, it might not fail immediately in an obviously diagnostic way, and the test function itself may finish and be reported as "passed" before the underlying Promise has even settled, since nothing in the test is actually waiting for it to resolve or reject. WHY THIS CAUSES INTERMITTENT PASS/FAIL RATHER THAN A CONSISTENT ERROR: because the real async work (React re-rendering once the effect's data arrives) is still happening in the background, independent of whether the test bothered to wait for it. Depending on unpredictable factors — how fast the test machine is, what else is running, minor timing differences between test runs — the real update might happen to complete before the test process moves on and reports a result in one run, and NOT complete in time during another run on the same unchanged code. This is exactly why a missing await on an async Testing Library call produces genuinely flaky (sometimes-passing, sometimes-failing) behavior rather than a clean, consistent, easy-to- spot failure — the bug is about WHEN things happen, not something crash-worthy on its own, so the timing race is what breaks sometimes and not other times, whereas a real code error, by contrast, would produce the same failure and the same clear error message on every single run.