awaitIdle
Suspends until the composition is idle, making the AWT tree reflect the latest state.
It runs the event dispatch thread's queue itself, so recomposition makes progress while it waits, and returns once there is neither pending recomposition nor pending snapshot work AND the EDT queue has drained the runnables the idle composition scheduled - a window show that a Dialog { } defers to its own dispatch, for example, has landed by the time this returns. The tree is validated only once that queue is drained, as a window validates after the events ahead of it.
With mainClock's autoAdvance at its default of true, reaching that state is this call's own job: it sends whatever frames are needed. With autoAdvance set to false, this drains the same pending work but sends no frame itself, so a composition parked waiting for one - mid-animation, or simply holding an unapplied recomposition - is exactly the state this returns on; call MainTestClock.advanceTimeByFrame or MainTestClock.advanceTimeBy to move it forward.
If the composition never becomes idle within a generous frame cap, this fails with an AssertionError whose message names the outstanding work and includes a readable dump of the current AWT tree (including realized windows), rather than hanging until the surrounding test framework times out.
A throw that ends recomposition - one out of a node's update block, for instance - fails the call that ran the failing pass with that throwable. What an effect throws - the body of a androidx.compose.runtime.LaunchedEffect, or a coroutine launched in the scope androidx.compose.runtime.rememberCoroutineScope returns - ends recomposition too, and fails the first call that runs the event dispatch thread's queue after it. A cancelled effect is no failure. Either throw is thrown once: the composition recomposes no more, and later calls return as they do over an idle composition. One that no call is left to throw fails the test as it ends.
A failure the library itself raises on the event dispatch thread - reached from neither a recomposition nor a caller callback - fails this call the same way rather than being lost to the thread's own uncaught-exception handler. A test that expects any of these wraps the call in assertFailsWith.