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
On Android, tracking runs in the app process and is accessible to instrumented tests. JVM, iOS,
and Wasm tests use the shared tracer through runRecompositionTrackingUiTest.
Compatibility¶
Minimum supported Compose for Dejavu 0.5.x: 1.11 (BOM 2026.05.00). The 0.5.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. Validated with Kotlin 2.4.0 and its Compose compiler plugin.
| Compose BOM | Compose | Kotlin tested | Status |
|---|---|---|---|
| 2026.05.00 | 1.11.x | 2.4.0 | Minimum |
| 2026.06.01 | 1.11.x | 2.4.0 | Latest 1.11 checkpoint |
| 2026.08.00 | 1.12.x | 2.4.0 | Release baseline |
The release baseline is Compose Multiplatform 1.12.0 and Android Compose BOM 2026.08.00; 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.01, and
2026.08.00. 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.
Android 0.5.0 artifacts require compile SDK 37 and min SDK 24. To retain an older Android Compose line,
use enforcedPlatform for the selected BOM in both application and instrumentation dependencies;
a regular platform can allow the newer transitive baseline to win. DejaVu 0.4.0 remains the
Compose Multiplatform 1.11 / compile SDK 36 baseline.
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.
New Compose API 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 BOM checkpoint.
Compose 1.12 Coverage¶
The Compose 1.12 baseline additionally validates keyed SideEffect, shrinking vararg effect and
remember keys, assertions using runWithoutImplicitWait, and nested movable content under
LinkBuffer. Exact counters continue using unkeyed SideEffect, including a deliberately inefficient
fixture whose keyed callback stays quiet during four recompositions. The experimental suite runs
26 tests on 1.12 and retains 20 on the supported Android 1.11 checkpoints.
DejavuComposeTestRule delegates the new hasPendingWork and runWithoutImplicitWait methods on
Compose 1.12. These methods require 1.12; the existing rule API remains covered on Android 1.11.
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. - Non-Android instance diagnostics — unresolved tags can share a function-level count when multiple instances use the same composable. Android has the most complete per-instance diagnostics.
- 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.