Skip to content

Spectre

Spectre

Spectre is a Kotlin library for driving live Compose Desktop UIs from automated tests. It reads the Compose semantics tree, drives mouse and keyboard input either through real OS-level events or through synthetic AWT events dispatched straight into the window hierarchy, and records what happens on screen — against IDE-hosted Compose surfaces (IntelliJ, Jewel) and standalone desktop apps alike.

If you've used UI Automator on Android or Espresso for that matter, the shape will feel familiar — Spectre brings the same "find a node, do a thing, assert" loop to Compose Desktop.

Pre-release

Spectre is in bootstrap. There are no published Maven artifacts yet, the public API is still settling, and parts of the codebase are explicitly flagged as not yet hand-audited in the README. Treat anything here as a moving target until a tagged release lands.

Why Spectre

  • Real Compose Desktop, not a simulator. Spectre runs against your actual application windows. Semantics, layout, focus, popups, and HiDPI all come from the running UI rather than a parallel test harness.
  • In-process or cross-JVM. Use ComposeAutomator.inProcess() for the simple case, or use the server module to drive a UI hosted in a different JVM (e.g., an IDE under test).
  • Real or synthetic input. ComposeAutomator.inProcess() defaults to OS-level java.awt.Robot events. Swap in RobotDriver.synthetic(...) and AWT events go directly into the window hierarchy — useful when tests run in parallel and can't fight over OS focus.
  • Recording built in. Region capture via ffmpeg, plus window-targeted capture (ScreenCaptureKit on macOS, gdigrab on Windows, x11grab/portal on Linux). The AutoRecorder picks the right backend per call.
  • JUnit-friendly. Drop-in extension and rule for JUnit 5 and JUnit 4 manage a per-test automator instance for you.

Where to start

  • Getting started — Install Spectre and write your first test.
  • The automator — Concepts: semantics surfaces, queries vs. interactions, why there is no auto-wait.
  • Finding nodesfindByTestTag, findByText, findByContentDescription, findByRole, and the printTree() debugger.
  • SynchronizationwaitForIdle, waitForVisualIdle, waitForNode, and the EDT rule.
  • Recording — Region and window-targeted capture across macOS, Windows, and Linux.
  • Cross-JVM — Drive a UI hosted in another JVM process via the embedded HTTP transport.