How It Works¶
Dejavu hooks into the Compose runtime's CompositionTracer API (available since compose-runtime 1.2.0):
- Intercepts trace calls —
Composer.setTracer()receives callbacks for every composable enter/exit - Maps testTag to composable — walks the
CompositionDatagroup tree to find which composable encloses eachModifier.testTag() - Counts recompositions — maintains a thread-safe counter per composable, incrementing on recomposition (not initial composition)
- Tracks causality —
Snapshot.registerApplyObserverdetects state changes; dirty bits detect parameter-driven recompositions - Reports on failure — assembles source location, timeline, tracked composables, and causality into a structured error
All tracking runs in the app process on the main thread, directly accessible to instrumented tests.
Compatibility¶
Minimum supported Compose for Dejavu 0.4.x: 1.11 (BOM 2026.05.00). The 0.4.x test harness uses the Compose testing v2 APIs introduced with this line. For Compose 1.10, use Dejavu 0.3.1. This keeps that older Compose line available without letting newer transitive artifacts mask an unsupported combination. Requires Kotlin 2.3+ with the Compose compiler plugin.
| Compose BOM | Compose | Kotlin | Status |
|---|---|---|---|
| 2026.05.00 | 1.11.x | 2.3.x+ | Minimum |
| 2026.06.00 | 1.11.x | 2.3.x+ | Previous 1.11 checkpoint |
| 2026.06.01 | 1.11.x | 2.3.x+ | Release baseline |
The release baseline is Compose Multiplatform 1.11.1 and Android Compose BOM 2026.06.01; the floor
is Compose 1.11 (BOM 2026.05.00). CI derives its matrix from the composeBomCompat* checkpoints and
composeBom baseline in gradle/libs.versions.toml, currently 2026.05.00, 2026.06.00, and
2026.06.01. Compatibility runs enforce the selected BOM so newer transitive Compose
Multiplatform artifacts cannot silently replace the runtime under test. CompositionObserver
support is unconditional; there is no degraded or observer-excluded build path.
Compose Testing v2¶
Dejavu's test harness uses the Compose testing v2 APIs (runComposeUiTest /
createAndroidComposeRule from the androidx.compose.ui.test.v2 packages). These default to
StandardTestDispatcher rather than v1's UnconfinedTestDispatcher. Recomposition counts were
verified to be unchanged on JVM under the new dispatcher, so no rebaselining of test expectations
was required.
Compose 1.11 Coverage¶
The compose-experimental module is a staging area for recomposition coverage of experimental /
newest-Compose APIs before they graduate into the core accuracy suite. It exercises Dejavu against
Compose 1.11's new composables and runtime paths: the experimental Grid and FlexBox layouts,
derivedMediaQuery / mediaQuery adaptive breakpoints, the Styles API
(androidx.compose.foundation.style), movableContentOf, and the experimental LinkBuffer composer
runtime path (ComposeRuntimeFlags.isLinkBufferComposerEnabled). These tests run on JVM, iOS,
Wasm, and Android instrumented; Android runs every supported 1.11 BOM checkpoint.
Known Limitations¶
- Off-screen lazy items —
LazyColumn/LazyRowonly compose items that are visible. Items that haven't been composed don't exist in the composition tree, so Dejavu has nothing to track. Scroll them into view before asserting. - Activity-owned Recomposer clock —
createAndroidComposeRuleuses the Activity's realRecomposer, not a test-controlled one. This meansmainClock.advanceTimeBy()can't drive infinite animations forward. UsecreateComposeRule(without an Activity) if you need a controllable clock. - Parameter change tracking precision — parameter diffs use
Group.parametersfrom the Compose tooling data API, which was designed for Layout Inspector rather than programmatic diffing. Parameter names may be unavailable, and values are compared viahashCode/toString, so custom types without meaningfultoStringshow opaque values. - iOS x64 — Compose Multiplatform 1.11 removes Apple x64 target support, so Dejavu supports
iosArm64andiosSimulatorArm64for the 1.11 baseline.