runComposeSwingTest

fun runComposeSwingTest(rootSize: Dimension = Dimension(800, 600), timeout: Duration = 60.seconds, effectContext: CoroutineContext = EmptyCoroutineContext, block: suspend ComposeSwingTest.() -> Unit): TestResult

Sets up an isolated Swing-Compose composition, runs the suspending block against it on the EDT, and tears everything down.

The whole block executes as a coroutine on Dispatchers.Swing (the EDT); the calling (JUnit) thread is blocked until it completes or timeout elapses, whichever comes first. Frames are produced under test control rather than automatically, so the composition advances only across idle/await calls. Because the body runs on the EDT, queries and actions read and write the AWT tree directly, and ComposeSwingTest.awaitIdle suspends rather than blocking.

Runs with or without a display, and shows nothing. Swing's own invalidation and layout run as they do in a window, at a fixed root size, so tree/text/constraint AND bounds-based assertions (see SwingNodeInteraction.assertIsDisplayed) all work off-screen. A heavyweight AWT component that needs a native peer (for example java.awt.Canvas, java.awt.Button) is tested in a window the test owns instead.

Content may also compose real top-level peers (Window { }, Dialog { }); those are found with ComposeSwingTest.onWindow and are torn down with the composition when the block completes. Realizing them requires a display - declare that requirement with a JUnit assumption (org.junit.jupiter.api.Assumptions.assumeFalse(GraphicsEnvironment.isHeadless(), ...)) at the top of the block, so the test reports SKIPPED rather than failing on headless environments.

Parameters

rootSize

the off-screen ComposeSwingTest.root's fixed size. The default is large enough that realistic test layouts get sensible, non-zero child bounds.

timeout

the wall-clock deadline after which an unfinished block fails the test instead of hanging it. The frame caps inside ComposeSwingTest.awaitIdle and ComposeSwingTest.waitUntil only bound the work those gates drive themselves; this bounds the test as a whole.

effectContext

extra context elements the composition's effects run under - what a androidx.compose.runtime.LaunchedEffect body and a androidx.compose.runtime.rememberCoroutineScope scope see. The harness's own dispatcher, job, frame clock and policies are added after it and win over anything named here. A kotlinx.coroutines.CoroutineExceptionHandler named here is handed what an effect throws: the throw then fails no gate, and what the handler itself throws fails the next one. Either way recomposition has ended, and a gate that gives up afterwards names the throw. A throw that arrives after the test has ended - from an effect that fails on another thread later, or one that needs more than one turn of the event queue to unwind - is not reported.

block

the test body, run on the Event Dispatch Thread against a fresh ComposeSwingTest.