# ComposeTestRule

Artifact: [androidx.compose.ui:ui-test-junit4](https://developer.android.com/jetpack/androidx/releases/compose-ui) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/test/junit4/ComposeTestRule.jvmAndAndroid.kt+class:androidx.compose.ui.test.junit4.ComposeTestRule) Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0) Android/JVM
- android

  ```
  interface ComposeTestRule : TestRule, SemanticsNodeInteractionsProvider
  ```
Known direct subclasses [ComposeContentTestRule](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeContentTestRule)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeContentTestRule` | A `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule` that allows you to set content without the necessity to provide a host for the content. |

Known indirect subclasses [AndroidComposeTestRule](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/AndroidComposeTestRule` |   |

*** ** * ** ***

A `https://junit.org/junit4/javadoc/latest/org/junit/rules/TestRule.html` that allows you to test and control composables, either in isolation or in applications. Most of the functionality in this interface provides some form of test synchronization: the test will block until the app or composable is idle, to ensure the tests are deterministic.

For example, if you would perform a click on the center of the screen while a button is animating from left to right over the screen, without synchronization the test would sometimes click when the button is in the middle of the screen (button is clicked), and sometimes when the button is past the middle of the screen (button is not clicked). With synchronization, the app would not be idle until the animation is over, so the test will always click when the button is past the middle of the screen (and not click it). If you actually do want to click the button when it's in the middle of the animation, you can do so by controlling the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`. You'll have to disable `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#autoAdvance()`, and manually advance the clock by the time necessary to position the button in the middle of the screen.

An instance of `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule` can be created with `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/package-summary#createComposeRule(kotlin.coroutines.CoroutineContext)`, which will also create a host for the compose content for you (see `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeContentTestRule`). If you need to specify which particular Activity is started on Android, you can use `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/package-summary#createAndroidComposeRule(kotlin.coroutines.CoroutineContext)`.

If you don't want any Activity to be started automatically by the test rule on Android, you can use `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/package-summary#createEmptyComposeRule(kotlin.coroutines.CoroutineContext)`. In such a case, you will have to set content using one of Compose UI's setters (like androidx.compose.ui.platform .setContent).

## Summary

| ### Public functions |
|---|---|---|
| `suspend https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#awaitIdle()()` Suspends until the UI is idle. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#hasPendingWork()()` Returns whether the Compose UI has any pending work. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#registerIdlingResource(androidx.compose.ui.test.IdlingResource)(idlingResource: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource)` Registers an `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource` in this test. | android |
| `T` | `<T : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?> https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnIdle(kotlin.Function0)(action: () -> T)` Executes the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnIdle(kotlin.Function0)` in the same way as `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)` but `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitForIdle()` until the app is idle before executing the action. | android |
| `T` | `<T : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?> https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)(action: () -> T)` Runs the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)` on the UI thread. | android |
| `open T` | `<T : https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-any/index.html?> https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runWithoutImplicitWait(kotlin.Function0)(block: () -> T)` Executes the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runWithoutImplicitWait(kotlin.Function0)` with implicit synchronization suppressed. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#unregisterIdlingResource(androidx.compose.ui.test.IdlingResource)(idlingResource: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource)` Unregisters an `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource` from this test. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitForIdle()()` Waits for the UI to become idle. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)(timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, condition: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html)` Blocks until the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` is satisfied. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)( conditionDescription: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html, timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, condition: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Blocks until the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` is satisfied. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)( matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Blocks until at least one node matches the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)( matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Blocks until no nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)( matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Blocks until exactly one node matches the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. | android |
| `open https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)( matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, count: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Blocks until the number of nodes matching the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` is equal to the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)`. | android |

| ### Public properties |
|---|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/unit/Density` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#density()` Current device screen's density. | android |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()` Clock that drives frames and recompositions in compose tests. | android |

| ### Extension functions |
|---|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/annotation/RequiresApi(value = 34) https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#(androidx.compose.ui.test.junit4.ComposeTestRule).disableAccessibilityChecks()()` Disables accessibility checks. | android |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/annotation/RequiresApi(value = 34) https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#(androidx.compose.ui.test.junit4.ComposeTestRule).enableAccessibilityChecks(com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator)( accessibilityValidator: com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator )` Enables accessibility checks that will be run before every action that is expected to change the UI. | android |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider` | `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule.https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#(androidx.compose.ui.test.junit4.ComposeTestRule).onRootWithViewInteraction(androidx.test.espresso.ViewInteraction)( interaction: https://developer.android.com/reference/kotlin/androidx/test/espresso/ViewInteraction )` Scopes the Compose interaction to the View hierarchy matched by the provided Espresso `https://developer.android.com/reference/kotlin/androidx/test/espresso/ViewInteraction`. | android |

### Inherited functions

From [androidx.compose.ui.test.SemanticsNodeInteractionsProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider) `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionCollection` `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider#onAllNodes(androidx.compose.ui.test.SemanticsMatcher,kotlin.Boolean)(matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html)`

Finds all semantics nodes that match the given condition.
android `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction` `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsNodeInteractionsProvider#onNode(androidx.compose.ui.test.SemanticsMatcher,kotlin.Boolean)(matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher, useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html)`

Finds a semantics node that matches the given condition.
android From [org.junit.rules.TestRule](https://junit.org/junit4/javadoc/latest/org/junit/rules/TestRule.html) `https://junit.org/junit4/javadoc/latest/org/junit/runners/model/Statement.html` `https://junit.org/junit4/javadoc/latest/org/junit/rules/TestRule.html#apply-org.junit.runners.model.Statement-org.junit.runner.Description-(p0: https://junit.org/junit4/javadoc/latest/org/junit/runners/model/Statement.html, p1: https://junit.org/junit4/javadoc/latest/org/junit/runner/Description.html)` android

## Public functions

### awaitIdle

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
suspend fun awaitIdle(): Unit
```

Suspends until the UI is idle. Quiescence is reached when there are no more pending changes (e.g. pending recompositions or a pending draw call) and all `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource`s are idle.

If `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#autoAdvance()` is enabled on the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`, this method will advance the clock to process any pending composition, invalidation and animation. If auto advancement is not enabled, the clock will not be advanced which means that the Compose UI appears to be frozen. This is ideal for testing animations in a deterministic way. This method will always wait for all `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource`s to become idle.

Note that some processes are driven by the host operating system and will therefore still execute when auto advancement is disabled. For example, Android's measure, layout and draw passes can still happen if required by the View system.

### hasPendingWork

android Added in [1.12.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.12.0)

```
open fun hasPendingWork(): Boolean
```

Returns whether the Compose UI has any pending work.

This performs a passive check of the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`, snapshot state, and recomposer to determine if there is any pending work. Unlike `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitForIdle()`, calling this method does not advance the clock or drain the main message queue.

This is particularly useful when `autoAdvance` is disabled, allowing you to inspect the state of the UI while an animation or other work is still active. If `autoAdvance` is `true`, the testing framework continuously processes pending work. In that scenario, calling this method acts as a momentary snapshot and will generally return `false`. It may briefly return `true` if work is queued but the framework hasn't auto-advanced yet, making the result fleeting and unreliable for driving test logic.

```kotlin
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick

composeTestRule.mainClock.autoAdvance = false

// Trigger the animation
composeTestRule.onNodeWithTag("ExpandButton").performClick()

while (composeTestRule.hasPendingWork()) {
    // Advance the clock by exactly one frame
    composeTestRule.mainClock.advanceTimeByFrame()
    composeTestRule.waitForIdle()
    composeTestRule.runOnUiThread {
        composeTestRule.runWithoutImplicitWait {
            // Make intermediate assertions (e.g., check bounds or visibility)
            composeTestRule.onNodeWithTag("CardContent").assertExists()
        }
    }
}
```

### registerIdlingResource

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun registerIdlingResource(idlingResource: IdlingResource): Unit
```

Registers an `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource` in this test.

### runOnIdle

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun <T : Any?> runOnIdle(action: () -> T): T
```

Executes the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnIdle(kotlin.Function0)` in the same way as `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)` but `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitForIdle()` until the app is idle before executing the action. This is the recommended way of doing your assertions on shared variables.

This method blocks until the action is complete.

### runOnUiThread

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun <T : Any?> runOnUiThread(action: () -> T): T
```

Runs the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)` on the UI thread.

This method is blocking until the action is complete.

### runWithoutImplicitWait

android Added in [1.12.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.12.0)

```
open fun <T : Any?> runWithoutImplicitWait(block: () -> T): T
```

Executes the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runWithoutImplicitWait(kotlin.Function0)` with implicit synchronization suppressed. `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runWithoutImplicitWait(kotlin.Function0)` should contain read-only assertions, and any actions that mutate state should be performed outside of this block.

To ensure stability of the UI tree while running assertions in this block, make sure to call this on the UI thread, such as with `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)`. If you run this block off the UI thread, state might change in the background and be reflected in the UI while the block is executing. This exposes your test to race conditions, flakiness, and may cause you to read stale or inconsistent state.

Standard node queries (like `onNodeWithTag` or `fetchSemanticsNode`) normally trigger a `waitForIdle()` under the hood. In animation tests that manually step through frames in a loop, these implicit waits impose a severe performance penalty.

This API acts as a performance optimization for motion tests that assert UI state across multiple frames. It is primarily designed for use when mainClock.autoAdvance is set to false and the UI is known to be in a stable state at the specific frame being tested (for example, by calling waitForIdle() before this block).

```kotlin
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performClick

composeTestRule.mainClock.autoAdvance = false

// Trigger an animation
composeTestRule.onNodeWithText("Start Animation").performClick()

// Step through the animation frame-by-frame
while (composeTestRule.hasPendingWork()) {
    composeTestRule.mainClock.advanceTimeByFrame()
    composeTestRule.waitForIdle()
    composeTestRule.runOnUiThread {
        // Suppress implicit synchronization inside this block to avoid redundant
        // waits on each node query, making the frame assertions execute much faster.
        composeTestRule.runWithoutImplicitWait {
            val box1 = composeTestRule.onNodeWithTag("Box1").fetchSemanticsNode()
            val box2 = composeTestRule.onNodeWithTag("Box2").fetchSemanticsNode()

            assert(box1.boundsInRoot.right <= box2.boundsInRoot.left)
        }
    }
}
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#runOnUiThread(kotlin.Function0)` |   |
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#hasPendingWork()` |   |

### unregisterIdlingResource

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun unregisterIdlingResource(idlingResource: IdlingResource): Unit
```

Unregisters an `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource` from this test.

### waitForIdle

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun waitForIdle(): Unit
```

Waits for the UI to become idle. Quiescence is reached when there are no more pending changes (e.g. pending recompositions or a pending draw call) and all `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource`s are idle.

If `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#autoAdvance()` is enabled on the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`, this method will advance the clock to process any pending composition, invalidation and animation. If auto advancement is not enabled, the clock will not be advanced which means that the Compose UI appears to be frozen. This is ideal for testing animations in a deterministic way. This method will always wait for all `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/IdlingResource`s to become idle.

Note that some processes are driven by the host operating system and will therefore still execute when auto advancement is disabled. For example, Android's measure, layout and draw passes can still happen if required by the View system.

### waitUntil

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
fun waitUntil(timeoutMillis: Long, condition: () -> Boolean): Unit
```

Blocks until the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` is satisfied.

If `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#autoAdvance()` is enabled on the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`, this method will actively advance the clock to process any pending composition, invalidation and animation. If auto advancement is not enabled, the clock will not be advanced actively which means that the Compose UI appears to be frozen. It is still valid to use this method in this way, if the condition will be satisfied by something not driven by our clock.

Compared to `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#advanceTimeUntil(kotlin.Long,kotlin.Function0)`, `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` sleeps after every iteration to yield to other processes. This gives `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` a better integration with the host, but it is less preferred from a performance viewpoint. Therefore, we recommend that you try using `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#advanceTimeUntil(kotlin.Long,kotlin.Function0)` before resorting to `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)`.

| Parameters |
|---|---|
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if the given condition is not satisfied. This observes wall clock time, not `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`. |
| `condition: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | Condition that must be satisfied in order for this method to successfully finish. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If the condition is not satisfied after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` (in wall clock time). |

### waitUntil

android Added in [1.7.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.7.0)

```
open fun waitUntil(
    conditionDescription: String,
    timeoutMillis: Long,
    condition: () -> Boolean
): Unit
```

Blocks until the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` is satisfied.

If `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#autoAdvance()` is enabled on the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`, this method will actively advance the clock to process any pending composition, invalidation and animation. If auto advancement is not enabled, the clock will not be advanced actively which means that the Compose UI appears to be frozen. It is still valid to use this method in this way, if the condition will be satisfied by something not driven by our clock.

Compared to `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#advanceTimeUntil(kotlin.Long,kotlin.Function0)`, `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` sleeps after every iteration to yield to other processes. This gives `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` a better integration with the host, but it is less preferred from a performance viewpoint. Therefore, we recommend that you try using `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/MainTestClock#advanceTimeUntil(kotlin.Long,kotlin.Function0)` before resorting to `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)`.

| Parameters |
|---|---|
| `conditionDescription: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html` | An optional human-readable description of `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` that will be included in the timeout exception if thrown. |
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if the given condition is not satisfied. This observes wall clock time, not `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#mainClock()`. |
| `condition: () -> https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | Condition that must be satisfied in order for this method to successfully finish. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If the condition is not satisfied after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.String,kotlin.Long,kotlin.Function0)` (in wall clock time). |

### waitUntilAtLeastOneExists

android Added in [1.13.0-rc01](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.13.0-rc01)

```
open fun waitUntilAtLeastOneExists(
    matcher: SemanticsMatcher,
    timeoutMillis: Long,
    useUnmergedTree: Boolean = false
): Unit
```

Blocks until at least one node matches the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`.

| Parameters |
|---|---|
| `matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher` | The matcher that will be used to filter nodes. |
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if no nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. This observes wall clock time, not frame time. |
| `useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = false` | If true, searches the unmerged semantics tree instead of the merged semantics tree. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If no nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilAtLeastOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` (in wall clock time). |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` |   |

### waitUntilDoesNotExist

android Added in [1.13.0-rc01](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.13.0-rc01)

```
open fun waitUntilDoesNotExist(
    matcher: SemanticsMatcher,
    timeoutMillis: Long,
    useUnmergedTree: Boolean = false
): Unit
```

Blocks until no nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`.

| Parameters |
|---|---|
| `matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher` | The matcher that will be used to filter nodes. |
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if any nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. This observes wall clock time, not frame time. |
| `useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = false` | If true, searches the unmerged semantics tree instead of the merged semantics tree. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If any nodes match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilDoesNotExist(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` (in wall clock time). |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` |   |

### waitUntilExactlyOneExists

android Added in [1.13.0-rc01](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.13.0-rc01)

```
open fun waitUntilExactlyOneExists(
    matcher: SemanticsMatcher,
    timeoutMillis: Long,
    useUnmergedTree: Boolean = false
): Unit
```

Blocks until exactly one node matches the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`.

| Parameters |
|---|---|
| `matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher` | The matcher that will be used to filter nodes. |
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if exactly one node does not match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)`. This observes wall clock time, not frame time. |
| `useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = false` | If true, searches the unmerged semantics tree instead of the merged semantics tree. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If exactly one node does not match the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilExactlyOneExists(androidx.compose.ui.test.SemanticsMatcher,kotlin.Long,kotlin.Boolean)` (in wall clock time). |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` |   |

### waitUntilNodeCount

android Added in [1.13.0-rc01](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.13.0-rc01)

```
open fun waitUntilNodeCount(
    matcher: SemanticsMatcher,
    count: Int,
    timeoutMillis: Long,
    useUnmergedTree: Boolean = false
): Unit
```

Blocks until the number of nodes matching the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` is equal to the given `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)`.

| Parameters |
|---|---|
| `matcher: https://developer.android.com/reference/kotlin/androidx/compose/ui/test/SemanticsMatcher` | The matcher that will be used to filter nodes. |
| `count: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | The number of nodes that are expected to be matched. |
| `timeoutMillis: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The time after which this method throws an exception if the number of nodes that match the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` is not `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)`. This observes wall clock time, not frame time. |
| `useUnmergedTree: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html = false` | If true, searches the unmerged semantics tree instead of the merged semantics tree. |

| Throws |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/ComposeTimeoutException` | If the number of nodes that match the `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` is not `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` after `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntilNodeCount(androidx.compose.ui.test.SemanticsMatcher,kotlin.Int,kotlin.Long,kotlin.Boolean)` (in wall clock time). |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/ComposeTestRule#waitUntil(kotlin.Long,kotlin.Function0)` |   |

## Public properties

### density

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
val density: Density
```

Current device screen's density. Note that it is technically possible for a Compose hierarchy to define a different density for a certain subtree.

### mainClock

android Added in [1.0.0](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.0.0)

```
val mainClock: MainTestClock
```

Clock that drives frames and recompositions in compose tests.

## Extension functions

### ComposeTestRule.disableAccessibilityChecks

android Artifact: [androidx.compose.ui:ui-test-junit4-accessibility](https://developer.android.com/jetpack/androidx/releases/compose-ui) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/test/junit4/accessibility/ComposeTestRuleExt.android.kt+function:disableAccessibilityChecks)

```
@RequiresApi(value = 34)
fun ComposeTestRule.disableAccessibilityChecks(): Unit
```

Disables accessibility checks.

```kotlin
import androidx.compose.ui.test.junit4.accessibility.disableAccessibilityChecks
import androidx.compose.ui.test.junit4.accessibility.enableAccessibilityChecks
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToIndex
import androidx.compose.ui.test.tryPerformAccessibilityChecks
import androidx.test.espresso.accessibility.AccessibilityChecks

// Enable accessibility checks with default configuration:
composeTestRule.enableAccessibilityChecks()

// Accessibility checks are run automatically when performing an action:
composeTestRule.onNodeWithText("Submit").performClick()

// You can also manually run accessibility checks:
composeTestRule.onRoot().tryPerformAccessibilityChecks()

// When disabling accessibility checks..
composeTestRule.disableAccessibilityChecks()

// .. they no longer run when performing an action:
composeTestRule.onNodeWithTag("list").performScrollToIndex(15)
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/accessibility/package-summary#(androidx.compose.ui.test.junit4.AndroidComposeTestRule).enableAccessibilityChecks(com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator)` |   |

### ComposeTestRule.enableAccessibilityChecks

android Artifact: [androidx.compose.ui:ui-test-junit4-accessibility](https://developer.android.com/jetpack/androidx/releases/compose-ui) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/test/junit4/accessibility/ComposeTestRuleExt.android.kt+function:enableAccessibilityChecks)

```
@RequiresApi(value = 34)
fun ComposeTestRule.enableAccessibilityChecks(
    accessibilityValidator: com.google.android.apps.common.testing.accessibility.framework.integrations.espresso.AccessibilityValidator = AccessibilityValidator().setRunChecksFromRootView(true)
): Unit
```

Enables accessibility checks that will be run before every action that is expected to change the UI.

This requires API 34+ (Android U), and currently does not work on Robolectric.

Enabling accessibility checks is currently only supported for AndroidComposeTestRule. If you have a custom ComposeTestRule implementation that delegates to AndroidComposeTestRule, make sure to call this function on the AndroidComposeTestRule instead.

```kotlin
import androidx.compose.ui.test.junit4.accessibility.disableAccessibilityChecks
import androidx.compose.ui.test.junit4.accessibility.enableAccessibilityChecks
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.test.performClick
import androidx.compose.ui.test.performScrollToIndex
import androidx.compose.ui.test.tryPerformAccessibilityChecks
import androidx.test.espresso.accessibility.AccessibilityChecks

// Enable accessibility checks with default configuration:
composeTestRule.enableAccessibilityChecks()

// Accessibility checks are run automatically when performing an action:
composeTestRule.onNodeWithText("Submit").performClick()

// You can also manually run accessibility checks:
composeTestRule.onRoot().tryPerformAccessibilityChecks()

// When disabling accessibility checks..
composeTestRule.disableAccessibilityChecks()

// .. they no longer run when performing an action:
composeTestRule.onNodeWithTag("list").performScrollToIndex(15)
```

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/accessibility/package-summary#(androidx.compose.ui.test.junit4.AndroidComposeTestRule).disableAccessibilityChecks()` |   |

### ComposeTestRule.onRootWithViewInteraction

android Artifact: [androidx.compose.ui:ui-test-junit4](https://developer.android.com/jetpack/androidx/releases/compose-ui) [View Source](https://cs.android.com/search?q=file:androidx/compose/ui/test/junit4/ComposeTestRuleExt.android.kt+function:onRootWithViewInteraction)

```
fun ComposeTestRule.onRootWithViewInteraction(
    interaction: ViewInteraction
): SemanticsNodeInteractionsProvider
```

Scopes the Compose interaction to the View hierarchy matched by the provided Espresso `https://developer.android.com/reference/kotlin/androidx/test/espresso/ViewInteraction`.

It resolves the View from the Espresso `https://developer.android.com/reference/kotlin/androidx/compose/ui/test/junit4/package-summary#(androidx.compose.ui.test.junit4.ComposeTestRule).onRootWithViewInteraction(androidx.test.espresso.ViewInteraction)`, locates all Compose roots within that view hierarchy, and creates a new, scoped SemanticsNodeInteractionsProvider.

```kotlin
import androidx.compose.ui.test.junit4.onRootWithViewInteraction
import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.performClick
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withId

// Select the "Header" View container
val headerInteraction = onView(withId(header_id))

// Scope the Compose interaction to only the Header
composeTestRule
    .onRootWithViewInteraction(headerInteraction)
    .onNodeWithContentDescription("Settings")
    .performClick()
```

```kotlin
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.onRootWithViewInteraction
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.hasDescendant
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText

// Select the specific View row containing "Item #5"
val specificRowInteraction =
    onView(allOf(withId(recycler_item_root_id), hasDescendant(withText("Item #5"))))

// Scope interaction to that specific row View
composeTestRule
    .onRootWithViewInteraction(specificRowInteraction)
    .onNodeWithTag("fav_icon")
    .assertIsDisplayed()
    .performClick()
```

```kotlin
import androidx.compose.ui.test.assertIsEnabled
import androidx.compose.ui.test.junit4.onRootWithViewInteraction
import androidx.compose.ui.test.onNodeWithText
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.matcher.ViewMatchers.withId

// Select the container for the Detail Fragment
val detailContainerInteraction = onView(withId(detail_fragment_container_id))

// Assert that the submit button exists/is enabled only in the detail fragment
composeTestRule
    .onRootWithViewInteraction(detailContainerInteraction)
    .onNodeWithText("Submit")
    .assertIsEnabled()
```