# Making Jetpack Compose UIs testable

`ai-mobile-tester` locates elements through Android's accessibility tree (the same data
`uiautomator dump` exposes). Jetpack Compose renders your whole UI into a single
`AndroidComposeView`, so without one small opt-in, the only things matchable are visible
**text** and **`contentDescription`** — which are fragile across locales and dynamic data.
This guide makes your Compose elements addressable by **stable ids**.

## The opt-in

Requires **Compose UI 1.2.0+**. Apply it once, high in your tree (e.g. your top-level
`Scaffold`/`Box`), in builds you test against:

```kotlin
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.testTagsAsResourceId

Box(Modifier.semantics { testTagsAsResourceId = true }) {
    // your app content
}
```

This makes every `Modifier.testTag(...)` show up as a `resource-id` in the accessibility
tree. Then tag your **clickable containers** (not the inner `Text`):

```kotlin
Button(onClick = { /* ... */ }, modifier = Modifier.testTag("sign_in_button")) {
    Text("Sign in")
}
```

## The bare-id rule

In your YAML tests and tool calls, refer to the tag by its **bare** name — `sign_in_button`,
never the package-qualified `com.example.app:id/sign_in_button`. The package-qualified form
silently matches nothing for Compose tags.

## Where to apply it

`testTagsAsResourceId` exposes your tags to the accessibility tree. Most teams apply it in
debug/test builds (or app-wide if exposing internal tags to accessibility tooling is
acceptable for your app).

## Finding what's missing

Run the `check_testability` tool against any screen. It reports how many actionable elements
have a stable id, lists the ones that don't, and repeats the snippet above — so you can tag
exactly the elements your tests need.
