androidx.compose.ui.test

In this page, you'll find documentation for types, properties, and functions available in the androidx.compose.ui.test package.

If you're looking for guidance instead, check out the Testing in Compose guide.

Testing cheat sheet

The Compose testing cheat sheet is a quick reference of some of the most useful Compose test APIs. The cheat sheet is also downloadable in PDF format.

Useful Compose testing APIs

Interfaces

AndroidComposeUiTest

Variant of ComposeUiTest for when you want to have access the current activity of type A.

android
ComposeUiTest

A test environment that allows you to test and control composables, either in isolation or in applications.

Cmn
android
DeviceConfigurationOverride

The specification for an override applied to some piece of content.

Cmn
IdlingResource

Represents a resource of an application under test which can cause asynchronous background work to happen during test execution (e.g. an http request in response to a button click).

Cmn
InjectionScope

The receiver scope of all input injection lambdas offered in ui-test, such as performTouchInput and performMouseInput.

Cmn
KeyInjectionScope

The receiver scope of the key input injection lambda from performKeyInput.

Cmn
MainTestClock

The clock that drives frames, recompositions and launched effects in compose tests.

Cmn
MouseInjectionScope

The receiver scope of the mouse input injection lambda from performMouseInput.

Cmn
MultiModalInjectionScope

The receiver scope of the multi-modal input injection lambda from performMultiModalInput.

Cmn
RotaryInjectionScope

The receiver scope of rotary input injection lambda from performRotaryScrollInput.

Cmn
SemanticsNodeInteractionsProvider

Provides the main entry point into testing.

Cmn
TouchInjectionScope

The receiver scope of the touch input injection lambda from performTouchInput.

Cmn

Classes

AndroidComposeUiTestEnvironment

A test environment that can run tests using the test receiver scope.

android
ComposeTimeoutException

Thrown in cases where Compose test can't satisfy a condition in a defined time limit.

Cmn
GestureScope

This class is deprecated. Replaced by TouchInjectionScope

Cmn
MouseButton

Representation of a mouse button with its associated ID for the current platform.

Cmn
android
ScrollWheel

Representation of a mouse scroll wheel axis.

Cmn
SelectionResult

Result of SemanticsSelector projection.

Cmn
SemanticsMatcher

Wrapper for semantics matcher lambdas that allows to build string explaining to the developer what conditions were being tested.

Cmn
SemanticsNodeInteraction

Represents a semantics node and the path to fetch it from the semantics tree.

Cmn
SemanticsNodeInteractionCollection

Represents a collection of semantics nodes and the path to fetch them from the semantics tree.

Cmn
SemanticsSelector

Projects the given set of nodes to a new set of nodes.

Cmn
StateRestorationTester

Helps to test the state restoration for your Composable component.

Cmn
TestContext

Provides storage of test related entities that must be accessible by anything other than ComposeUiTest and friends, for example the InputDispatcher or the implementation of some assertions and actions.

Cmn
TestMonotonicFrameClock

A MonotonicFrameClock with a time source controlled by a kotlinx-coroutines-test TestCoroutineScheduler.

android

Objects

Annotations

Top-level functions summary

inline AndroidComposeUiTestEnvironment<A>
@ExperimentalTestApi
<A : ComponentActivity> AndroidComposeUiTestEnvironment(
    effectContext: CoroutineContext,
    crossinline activityProvider: () -> A?
)

Creates an AndroidComposeUiTestEnvironment that retrieves the host Activity by delegating to the given activityProvider.

android
Unit

Applies DeviceConfigurationOverride to the content under test to apply some configuration override.

Cmn
Unit

This function is deprecated. Use InterceptPlatformTextInput instead

Cmn
Unit

Adds a named assertion to the collection of assertions to be executed before test actions.

Cmn
SemanticsMatcher

Returns whether the node has at least one ancestor that satisfies the given matcher.

Cmn
SemanticsMatcher

Returns whether the node has at least one child that satisfies the given matcher.

Cmn
SemanticsMatcher

Returns whether the node has at least one descendant that satisfies the given matcher.

Cmn
SemanticsMatcher

Returns whether the node has at least one sibling that satisfies the given matcher.

Cmn
SemanticsMatcher

Return whether the node has a semantics click action defined.

Cmn
SemanticsMatcher
hasContentDescription(
    value: String,
    substring: Boolean,
    ignoreCase: Boolean
)

Returns whether the node's content description contains the given value.

Cmn
SemanticsMatcher

Returns whether the node's content description contains exactly the given values and nothing else.

Cmn
SemanticsMatcher
hasImeAction(actionType: ImeAction)

Returns whether the node defines the given IME action.

Cmn
SemanticsMatcher

Returns whether the node defines a semantics action to insert text on it.

Cmn
SemanticsMatcher

Return whether the node has no semantics click action defined.

Cmn
SemanticsMatcher

Return whether the node has no semantics scrollable action defined.

Cmn
SemanticsMatcher

Returns whether the node's parent satisfies the given matcher.

Cmn
SemanticsMatcher

Returns whether the node defines a semantics action to perform the IME action on it.

Cmn
SemanticsMatcher

Returns whether the node's range info matches exactly to the given accessibility range info.

Cmn
SemanticsMatcher

Returns whether the node defines a semantics action to request focus.

Cmn
SemanticsMatcher

Return whether the node has a semantics scrollable action defined.

Cmn
SemanticsMatcher

Returns whether the node defines the ability to scroll to an item index.

Cmn
SemanticsMatcher

Returns whether the node defines the ability to scroll to an item identified by a key, such as LazyColumn or LazyRow.

Cmn
SemanticsMatcher

Returns whether the node defines the ability to scroll to content identified by a matcher.

Cmn
SemanticsMatcher

Returns whether the node defines a semantics action to set text on it.

Cmn
SemanticsMatcher

Returns whether the node's value matches exactly to the given accessibility value.

Cmn
SemanticsMatcher
hasTestTag(testTag: String)

Returns whether the node is annotated by the given test tag.

Cmn
SemanticsMatcher
hasText(text: String, substring: Boolean, ignoreCase: Boolean)

Returns whether the node's text contains the given text.

Cmn
SemanticsMatcher
hasTextExactly(vararg textValues: String, includeEditableText: Boolean)

Returns whether the node's text contains exactly the given textValues and nothing else.

Cmn
SemanticsMatcher

Returns whether the node is a dialog.

Cmn
SemanticsMatcher

Returns whether the node is editable.

Cmn
SemanticsMatcher

Returns whether the node is enabled.

Cmn
SemanticsMatcher

Return whether the node is able to receive focus

Cmn
SemanticsMatcher

Returns whether the node is focused.

Cmn
SemanticsMatcher

Returns whether the node is marked as an accessibility header.

Cmn
SemanticsMatcher

Returns whether the node is not enabled.

Cmn
SemanticsMatcher

Return whether the node is not able to receive focus.

Cmn
SemanticsMatcher

Returns whether the node is not focused.

Cmn
SemanticsMatcher

Returns whether the node is not selected.

Cmn
SemanticsMatcher

Returns whether the node is not toggled.

Cmn
SemanticsMatcher

Returns whether the node is toggled.

Cmn
SemanticsMatcher

Returns whether the node is a popup.

Cmn
SemanticsMatcher

Return whether the node is the root semantics node.

Cmn
SemanticsMatcher

Return whether the node is selectable.

Cmn
SemanticsMatcher

Returns whether the node is selected.

Cmn
SemanticsMatcher

Return whether the node is checkable.

Cmn
Unit

Removes a named assertion from the collection of assertions to be executed before test actions.

Cmn
inline Unit
@ExperimentalTestApi
<A : ComponentActivity> runAndroidComposeUiTest(
    effectContext: CoroutineContext,
    noinline block: AndroidComposeUiTest<A>.() -> Unit
)

Variant of runComposeUiTest that allows you to specify which Activity should be launched.

android
Unit
@ExperimentalTestApi
<A : ComponentActivity> runAndroidComposeUiTest(
    activityClass: Class<A>,
    effectContext: CoroutineContext,
    block: AndroidComposeUiTest<A>.() -> Unit
)

Variant of runComposeUiTest that allows you to specify which Activity should be launched.

android
Unit

Sets up the test environment, runs the given test and then tears down the test environment.

Cmn
android
Unit

Variant of runComposeUiTest that does not launch an Activity to host Compose content in and thus acts as an "empty shell".

android

Extension functions summary

DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the dark mode or light mode theme for the contained content.

android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the font scale for the contained content.

Cmn
android
DeviceConfigurationOverride
@RequiresApi(value = 31)
DeviceConfigurationOverride.Companion.FontWeightAdjustment(
    fontWeightAdjustment: Int
)

A DeviceConfigurationOverride that overrides the font weight adjustment for the contained content.

android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the available size for the contained content.

Cmn
android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the layout direction for the contained content.

Cmn
android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the locales for the contained content.

android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides whether the screen is round for the contained content.

android
DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the window insets for the contained content.

android
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
MouseInjectionScope.animateMoveAlong(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long
)

Move the mouse along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
Unit
MouseInjectionScope.animateMoveBy(delta: Offset, durationMillis: Long)

Move the mouse from the current position by the given delta, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
Unit
MouseInjectionScope.animateMoveTo(
    position: Offset,
    durationMillis: Long
)

Move the mouse from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteraction.assert(
    matcher: SemanticsMatcher,
    messagePrefixOnError: (() -> String)?
)

Asserts that the provided matcher is satisfied for this node.

Cmn
SemanticsNodeInteractionCollection

Asserts that all the nodes in this collection satisfy the given matcher.

Cmn
SemanticsNodeInteractionCollection

Asserts that this collection contains at least one element that satisfies the given matcher.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteraction.assertContentDescriptionContains(
    value: String,
    substring: Boolean,
    ignoreCase: Boolean
)

Asserts that the node's content description contains the given value.

Cmn
SemanticsNodeInteraction

Asserts that the node's content description contains exactly the given values and nothing else.

Cmn
SemanticsNodeInteractionCollection

Asserts that this collection of nodes is equal to the given expectedSize.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node has a click action.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node has doesn't have a click action.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has height that is greater than or equal to expectedMinHeight.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has height equal to expectedHeight.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is displayed on screen.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is enabled.

Cmn
Unit
Dp.assertIsEqualTo(expected: Dp, subject: String, tolerance: Dp)

Asserts that this value is equal to the given expected value.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node has a focus.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is not displayed on screen.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is not enabled.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node does not have a focus.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is not selected.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is unchecked.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is checked.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is selectable.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is selected.

Cmn
SemanticsNodeInteraction

Asserts that the current semantics node is toggleable.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has the left position in the root composable that is equal to the given position.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
    expectedLeft: Dp,
    expectedTop: Dp
)

Asserts that the layout of this node has position in the root composable that is equal to the given position.

Cmn
SemanticsNodeInteraction

Asserts the node's range info equals the given value.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteraction.assertTextContains(
    value: String,
    substring: Boolean,
    ignoreCase: Boolean
)

Asserts that the node's text contains the given value.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteraction.assertTextEquals(
    vararg values: String,
    includeEditableText: Boolean
)

Asserts that the node's text contains exactly the given values and nothing else.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has the top position in the root composable that is equal to the given position.

Cmn
SemanticsNodeInteraction

Asserts that the touch bounds of this node has height equal to expectedHeight.

Cmn
SemanticsNodeInteraction

Asserts that the touch bounds of this node has width equal to expectedWidth.

Cmn
SemanticsNodeInteraction

Asserts the node's value equals the given value.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has width that is greater than or equal to expectedMinWidth.

Cmn
SemanticsNodeInteraction

Asserts that the layout of this node has width equal to expectedWidth.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
ImageBitmap

Captures the underlying semantics node's surface into bitmap.

android
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

Performs a click gesture (aka a tap) on the associated node.

Cmn
Unit

Use button to click on position, or on the current mouse position if position is unspecified.

Cmn
Unit

Use button to double-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit
GestureScope.doubleClick(position: Offset, delayMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.doubleClick(position: Offset, delayMillis: Long)

Performs a double click gesture (aka a double tap) on the associated node.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.down(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
MouseInjectionScope.dragAndDrop(
    start: Offset,
    end: Offset,
    button: MouseButton,
    durationMillis: Long
)

Use button to drag and drop something from start to end in durationMillis milliseconds.

Cmn
SemanticsNodeInteractionCollection

Returns all the nodes matching the given matcher.

Cmn
SemanticsNodeInteraction

Expects to return exactly one node matching the given matcher.

Cmn
Dp

Returns the position of an alignment line, or Dp.Unspecified if the line is not provided.

Cmn
DpRect

Returns the bounds of the layout of this node as clipped to the root.

Cmn
Rect?

Returns the bounds of the first link matching the predicate, or if that link spans multiple lines, returns the bounds of the first line of the link.

Cmn
DpRect

Returns the bounds of the layout of this node.

Cmn
SemanticsNodeInteraction

Executes all of the assertions registered by addGlobalAssertion.

Cmn
SemanticsNodeInteractionCollection

Executes all of the assertions registered by addGlobalAssertion, each of which will receive the first node of this collection.

Cmn
Boolean

Returns true if the matched node is displayed on screen.

Cmn
Boolean

Asserts that the current semantics node is not displayed on screen.

Cmn
Unit

Use button to long-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit
GestureScope.longClick(position: Offset, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.longClick(position: Offset, durationMillis: Long)

Performs a long click gesture (aka a long press) on the associated node.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.moveBy(pointerId: Int, delta: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.movePointerBy(pointerId: Int, delta: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.movePointerTo(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
GestureScope.moveTo(pointerId: Int, position: Offset)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.multiTouchSwipe(
    curves: List<(timeMillis: Long) -> Offset>,
    durationMillis: Long,
    keyTimes: List<Long>
)

Performs a multi touch swipe gesture on the associated node.

Cmn
SemanticsNodeInteractionCollection
SemanticsNodeInteractionsProvider.onAllNodesWithContentDescription(
    label: String,
    substring: Boolean,
    ignoreCase: Boolean,
    useUnmergedTree: Boolean
)

Finds all semantics nodes with the given label as content description.

Cmn
SemanticsNodeInteractionCollection
SemanticsNodeInteractionsProvider.onAllNodesWithTag(
    testTag: String,
    useUnmergedTree: Boolean
)

Finds all semantics nodes identified by the given tag.

Cmn
SemanticsNodeInteractionCollection
SemanticsNodeInteractionsProvider.onAllNodesWithText(
    text: String,
    substring: Boolean,
    ignoreCase: Boolean,
    useUnmergedTree: Boolean
)

Finds all semantics nodes with the given text.

Cmn
SemanticsNodeInteractionCollection

Returns all the ancestors of this node.

Cmn
SemanticsNodeInteraction

Returns exactly one child of this node.

Cmn
SemanticsNodeInteraction

Returns child of this node at the given index.

Cmn
SemanticsNodeInteractionCollection

Returns children of this node.

Cmn
SemanticsNodeInteraction

Returns the first node in this collection.

Cmn
SemanticsNodeInteraction

Returns the last node in this collection.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteractionsProvider.onNodeWithContentDescription(
    label: String,
    substring: Boolean,
    ignoreCase: Boolean,
    useUnmergedTree: Boolean
)

Finds a semantics node with the given content description.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteractionsProvider.onNodeWithTag(
    testTag: String,
    useUnmergedTree: Boolean
)

Finds a semantics node identified by the given tag.

Cmn
SemanticsNodeInteraction
SemanticsNodeInteractionsProvider.onNodeWithText(
    text: String,
    substring: Boolean,
    ignoreCase: Boolean,
    useUnmergedTree: Boolean
)

Finds a semantics node with the given text.

Cmn
SemanticsNodeInteraction

Returns a parent of this node.

Cmn
SemanticsNodeInteraction

Finds the root semantics node of the Compose tree.

Cmn
SemanticsNodeInteraction

Returns exactly one sibling of this node.

Cmn
SemanticsNodeInteractionCollection

Returns all siblings of this node.

Cmn
Offset

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
SemanticsNodeInteraction

Performs a click action on the element represented by the given semantics node.

Cmn
SemanticsNodeInteraction

Finds the CustomAccessibilityAction in the node's CustomActions list whose label is equal to label and then invokes it.

Cmn
SemanticsNodeInteraction
@ExperimentalTestApi
SemanticsNodeInteraction.performCustomAccessibilityActionWithLabelMatching(
    predicateDescription: String?,
    labelPredicate: (label: String) -> Boolean
)

Finds the CustomAccessibilityAction in the node's CustomActions list whose label satisfies a predicate function and then invokes it.

Cmn
SemanticsNodeInteraction

For a first link matching the predicate performs a click on it.

Cmn
SemanticsNodeInteraction

This function is deprecated. Replaced by performTouchInput

Cmn
Unit

Sends to this node the IME action associated with it in a similar way to the IME.

Cmn
SemanticsNodeInteraction

Executes the key input gesture specified in the given block.

Cmn
Boolean

Send the specified KeyEvent to the focused component.

Cmn
SemanticsNodeInteraction

Executes the mouse gesture specified in the given block.

Cmn
SemanticsNodeInteraction

Executes the multi-modal gesture specified in the given block.

Cmn
SemanticsNodeInteraction

Send the specified RotaryScrollEvent to the focused component.

Cmn
SemanticsNodeInteraction

Scrolls the closest enclosing scroll parent by the smallest amount such that this node is fully visible in its viewport.

Cmn
SemanticsNodeInteraction

Scrolls a scrollable container with items to the item with the given index.

Cmn
SemanticsNodeInteraction

Scrolls a scrollable container with keyed items to the item with the given key, such as LazyColumn or LazyRow.

Cmn
SemanticsNodeInteraction

Scrolls a scrollable container to the content that matches the given matcher.

Cmn
SemanticsNodeInteraction

Provides support to call custom semantics actions on this node.

Cmn
SemanticsNodeInteraction
<T : () -> Boolean> SemanticsNodeInteraction.performSemanticsAction(
    key: SemanticsPropertyKey<AccessibilityAction<T>>,
    invocation: (T) -> Unit
)

Provides support to call custom semantics actions on this node.

Cmn
Unit

Clears the text in this node in similar way to IME.

Cmn
Unit

Sends the given text to this node in similar way to IME.

Cmn
Unit

Sends the given selection to this node in similar way to IME.

Cmn
Unit

Replaces existing text with the given text in this node in similar way to IME.

Cmn
SemanticsNodeInteraction

Executes the touch gesture specified in the given block.

Cmn
Unit
GestureScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long
)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long
)

Performs a pinch gesture on the associated node.

Cmn
Unit
KeyInjectionScope.pressKey(key: Key, pressDurationMillis: Long)

Holds down the given key for the given pressDurationMillis by sending a key down event, advancing the event time and sending a key up event.

Cmn
Unit

Prints all the semantics nodes information into logs (as debug level).

Cmn
Unit
SemanticsNodeInteractionCollection.printToLog(
    tag: String,
    maxDepth: Int
)

Prints all the semantics nodes information into logs (as debug level).

Cmn
String

Prints all the semantics nodes information it holds into string.

Cmn
String

Prints all the semantics nodes information it holds into string.

Cmn
SemanticsNodeInteraction

Requests the focus system to give focus to this node by invoking the RequestFocus semantics action.

Cmn
Unit

Secondary-click on position, or on the current mouse position if position is unspecified.

Cmn
Unit
MouseInjectionScope.smoothScroll(
    scrollAmount: Float,
    durationMillis: Long,
    scrollWheel: ScrollWheel
)

Rotate the mouse's scrollWheel by the given scrollAmount.

Cmn
Unit
TouchInjectionScope.swipe(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long,
    keyTimes: List<Long>
)

Performs a swipe gesture on the associated node.

Cmn
Unit
GestureScope.swipe(start: Offset, end: Offset, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipe(
    start: Offset,
    end: Offset,
    durationMillis: Long
)

Performs a swipe gesture on the associated node.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeDown(startY: Float, endY: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipeDown(
    startY: Float,
    endY: Float,
    durationMillis: Long
)

Performs a swipe down gesture along x = [centerX] of the associated node, from startY till endY, taking durationMillis milliseconds.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeLeft(startX: Float, endX: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipeLeft(
    startX: Float,
    endX: Float,
    durationMillis: Long
)

Performs a swipe left gesture along y = [centerY] of the associated node, from startX till endX, taking durationMillis milliseconds.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeRight(startX: Float, endX: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipeRight(
    startX: Float,
    endX: Float,
    durationMillis: Long
)

Performs a swipe right gesture along y = [centerY] of the associated node, from startX till endX, taking durationMillis milliseconds.

Cmn
Unit

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
@ExperimentalTestApi
GestureScope.swipeUp(startY: Float, endY: Float, durationMillis: Long)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipeUp(
    startY: Float,
    endY: Float,
    durationMillis: Long
)

Performs a swipe up gesture along x = [centerX] of the associated node, from startY till endY, taking durationMillis milliseconds.

Cmn
Unit
GestureScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long
)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit
TouchInjectionScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long
)

Performs a swipe gesture on the associated node such that it ends with the given endVelocity.

Cmn
infix DeviceConfigurationOverride

Combines this override with the other override into a single override, by applying this override as the outer override first, then the other override as an inner override, and then the content.

Cmn
Unit

Use button to triple-click on position, or on the current mouse position if position is unspecified.

Cmn
SemanticsNodeInteractionCollection

Tries to perform accessibility checks on the current screen.

Cmn
SemanticsNodeInteraction

Tries to perform accessibility checks on the current screen.

Cmn
android
Unit
GestureScope.up(pointerId: Int)

This function is deprecated. Replaced by TouchInjectionScope.

Cmn
Unit

Blocks until at least one node matches the given matcher.

Cmn
Unit

Blocks until no nodes match the given matcher.

Cmn
Unit

Blocks until exactly one node matches the given matcher.

Cmn
Unit
@ExperimentalTestApi
ComposeUiTest.waitUntilNodeCount(
    matcher: SemanticsMatcher,
    count: Int,
    timeoutMillis: Long
)

Blocks until the number of nodes matching the given matcher is equal to the given count.

Cmn
Unit

Executes the keyboard sequence specified in the given block, whilst holding down the given key.

Cmn
Unit

Executes the keyboard sequence specified in the given block, in between presses to the given key.

Cmn
Unit

Executes the keyboard sequence specified in the given block, whilst holding down the each of the given keys.

Cmn
Unit

Executes the keyboard sequence specified in the given block, in between presses to the given keys.

Cmn

Extension properties summary

Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Long

The frame delay time for the TestMonotonicFrameClock in milliseconds.

android
Int

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Boolean

Verifies whether either of the alt keys are down.

Cmn
Boolean

Verifies whether either of the control keys are down.

Cmn
Boolean

Verifies whether the function key is down.

Cmn
Boolean

Verifies whether either of the meta keys are down.

Cmn
Boolean

Verifies whether either of the shift keys are down.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Float

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Offset

This property is deprecated. Replaced by TouchInjectionScope.

Cmn
Int

This property is deprecated. Replaced by TouchInjectionScope.

Cmn

Top-level functions

AndroidComposeUiTestEnvironment

@ExperimentalTestApi
inline fun <A : ComponentActivity> AndroidComposeUiTestEnvironment(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    crossinline activityProvider: () -> A?
): AndroidComposeUiTestEnvironment<A>

Creates an AndroidComposeUiTestEnvironment that retrieves the host Activity by delegating to the given activityProvider. Use this if you need to launch an Activity in a way that is not compatible with any of the existing runComposeUiTest, runAndroidComposeUiTest, or runEmptyComposeUiTest methods.

Valid use cases include, but are not limited to, creating your own JUnit test rule that implements AndroidComposeUiTest by delegating to AndroidComposeUiTestEnvironment.test. See AndroidComposeTestRule for a reference implementation.

The activityProvider is called every time activity is called, which in turn is called when setContent is called.

The most common implementation of an activityProvider retrieves the activity from a backing ActivityScenario (that the caller launches within the lambda passed to runTest), but one is not limited to this pattern.

Parameters
<A : ComponentActivity>

The Activity type to be interacted with, which typically (but not necessarily) is the activity that was launched and hosts the Compose content.

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.

crossinline activityProvider: () -> A?

A lambda that should return the current Activity instance of type A, if it is available. If it is not available, it should return null.

DeviceConfigurationOverride

@Composable
fun DeviceConfigurationOverride(
    override: DeviceConfigurationOverride,
    content: @Composable () -> Unit
): Unit

Applies DeviceConfigurationOverride to the content under test to apply some configuration override.

This can be useful to locally test behavior in isolation that depends on properties that are normally device-wide, such as font scale, screen size and layout direction.

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.FontScale

DeviceConfigurationOverride(DeviceConfigurationOverride.FontScale(1.5f)) {
    MyScreen() // will be rendered with a larger than default font scale
}
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.ForcedSize
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

DeviceConfigurationOverride(DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))) {
    MyScreen() // will be rendered in the space for 1280dp by 800dp without clipping
}
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.LayoutDirection
import androidx.compose.ui.unit.LayoutDirection

DeviceConfigurationOverride(DeviceConfigurationOverride.LayoutDirection(LayoutDirection.Rtl)) {
    MyComponent() // will be rendered with a right-to-left layout direction
}

PlatformTextInputMethodTestOverride

@ExperimentalTestApi
@Composable
fun PlatformTextInputMethodTestOverride(
    sessionHandler: PlatformTextInputSession,
    content: @Composable () -> Unit
): Unit

Installs a custom PlatformTextInputSession implementation to run when PlatformTextInputSession.startInputMethod is called by text editors inside content.

Parameters
sessionHandler: PlatformTextInputSession

The PlatformTextInputSession to use to handle input method requests. This object does not need to worry about synchronizing calls to PlatformTextInputSession.startInputMethod – this composable will handle the session management the same way as in production.

content: @Composable () -> Unit

The composable content for which to override the input method handler.

addGlobalAssertion

@ExperimentalTestApi
fun addGlobalAssertion(
    name: String,
    assertion: (SemanticsNodeInteraction) -> Unit
): Unit

Adds a named assertion to the collection of assertions to be executed before test actions.

This API is intended to be invoked by assertion frameworks to register assertions that must hold on the entire application whenever it's fully loaded and ready to interact with. They will be invoked upon common actions such as performClick, and they always verify every element on the screen, not just the element the action is performed on.

This is particularly useful to automatically catch accessibility problems such as contrast ratio, minimum touch-target size, etc.

Parameters
name: String

An identifier for the assertion. It can subsequently be used to deactivate the assertion with removeGlobalAssertion.

assertion: (SemanticsNodeInteraction) -> Unit

A function to be executed.

hasAnyAncestor

fun hasAnyAncestor(matcher: SemanticsMatcher): SemanticsMatcher

Returns whether the node has at least one ancestor that satisfies the given matcher.

Example: For the following tree

|-X
|-A
|-B
|-C1
|-C2

In case of C1, we would check the matcher against A and B

hasAnyChild

fun hasAnyChild(matcher: SemanticsMatcher): SemanticsMatcher

Returns whether the node has at least one child that satisfies the given matcher.

hasAnyDescendant

fun hasAnyDescendant(matcher: SemanticsMatcher): SemanticsMatcher

Returns whether the node has at least one descendant that satisfies the given matcher.

Example: For the following tree

|-X
|-A
|-B
|-C1
|-C2

In case of A, we would check the matcher against B,C1 and C2

hasAnySibling

fun hasAnySibling(matcher: SemanticsMatcher): SemanticsMatcher

Returns whether the node has at least one sibling that satisfies the given matcher.

Sibling is defined as a any other node that shares the same parent.

hasClickAction

fun hasClickAction(): SemanticsMatcher

Return whether the node has a semantics click action defined.

See also
OnClick

hasContentDescription

fun hasContentDescription(
    value: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false
): SemanticsMatcher

Returns whether the node's content description contains the given value.

Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.

Parameters
value: String

Value to match as one of the items in the list of content descriptions.

substring: Boolean = false

Whether to use substring matching.

ignoreCase: Boolean = false

Whether case should be ignored.

hasContentDescriptionExactly

fun hasContentDescriptionExactly(vararg values: String): SemanticsMatcher

Returns whether the node's content description contains exactly the given values and nothing else.

Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.

Parameters
vararg values: String

List of values to match (the order does not matter)

hasImeAction

fun hasImeAction(actionType: ImeAction): SemanticsMatcher

Returns whether the node defines the given IME action.

Parameters
actionType: ImeAction

the action to match.

hasInsertTextAtCursorAction

fun hasInsertTextAtCursorAction(): SemanticsMatcher

Returns whether the node defines a semantics action to insert text on it.

This can be used to, for instance, filter out text fields.

hasNoClickAction

fun hasNoClickAction(): SemanticsMatcher

Return whether the node has no semantics click action defined.

See also
OnClick

hasNoScrollAction

fun hasNoScrollAction(): SemanticsMatcher

Return whether the node has no semantics scrollable action defined.

See also
ScrollBy

hasParent

fun hasParent(matcher: SemanticsMatcher): SemanticsMatcher

Returns whether the node's parent satisfies the given matcher.

Returns false if no parent exists.

hasPerformImeAction

fun hasPerformImeAction(): SemanticsMatcher

Returns whether the node defines a semantics action to perform the IME action on it.

See also
OnImeAction

hasProgressBarRangeInfo

fun hasProgressBarRangeInfo(rangeInfo: ProgressBarRangeInfo): SemanticsMatcher

Returns whether the node's range info matches exactly to the given accessibility range info.

Parameters
rangeInfo: ProgressBarRangeInfo

range info to match.

hasRequestFocusAction

fun hasRequestFocusAction(): SemanticsMatcher

Returns whether the node defines a semantics action to request focus.

See also
RequestFocus

hasScrollAction

fun hasScrollAction(): SemanticsMatcher

Return whether the node has a semantics scrollable action defined.

See also
ScrollBy

hasScrollToIndexAction

fun hasScrollToIndexAction(): SemanticsMatcher

Returns whether the node defines the ability to scroll to an item index.

Note that not all scrollable containers have item indices. For example, a scrollable doesn't have items with an index, while LazyColumn does.

hasScrollToKeyAction

fun hasScrollToKeyAction(): SemanticsMatcher

Returns whether the node defines the ability to scroll to an item identified by a key, such as LazyColumn or LazyRow.

hasScrollToNodeAction

fun hasScrollToNodeAction(): SemanticsMatcher

Returns whether the node defines the ability to scroll to content identified by a matcher.

hasSetTextAction

fun hasSetTextAction(): SemanticsMatcher

Returns whether the node defines a semantics action to set text on it.

This can be used to, for instance, filter out text fields.

See also
SetText

hasStateDescription

fun hasStateDescription(value: String): SemanticsMatcher

Returns whether the node's value matches exactly to the given accessibility value.

Parameters
value: String

Value to match.

See also
StateDescription

hasTestTag

fun hasTestTag(testTag: String): SemanticsMatcher

Returns whether the node is annotated by the given test tag.

Parameters
testTag: String

Value to match.

See also
TestTag

hasText

fun hasText(text: String, substring: Boolean = false, ignoreCase: Boolean = false): SemanticsMatcher

Returns whether the node's text contains the given text.

This will also search in SemanticsProperties.EditableText.

Note that in merged semantics tree there can be a list of text items that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to use.

Parameters
text: String

Value to match as one of the items in the list of text values.

substring: Boolean = false

Whether to use substring matching.

ignoreCase: Boolean = false

Whether case should be ignored.

See also
Text
EditableText

hasTextExactly

fun hasTextExactly(
    vararg textValues: String,
    includeEditableText: Boolean = true
): SemanticsMatcher

Returns whether the node's text contains exactly the given textValues and nothing else.

This will also search in SemanticsProperties.EditableText by default.

Note that in merged semantics tree there can be a list of text items that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to use.

Parameters
vararg textValues: String

List of values to match (the order does not matter)

includeEditableText: Boolean = true

Whether to also assert against the editable text

See also
Text
EditableText

isDialog

fun isDialog(): SemanticsMatcher

Returns whether the node is a dialog.

This only checks if the node itself is a dialog, not if it is part of a dialog. Use hasAnyAncestorThat(isDialog()) for that.

See also
IsDialog

isEditable

fun isEditable(): SemanticsMatcher

Returns whether the node is editable.

See also
IsEditable

isEnabled

fun isEnabled(): SemanticsMatcher

Returns whether the node is enabled.

See also
Disabled

isFocusable

fun isFocusable(): SemanticsMatcher

Return whether the node is able to receive focus

See also
Focused

isFocused

fun isFocused(): SemanticsMatcher

Returns whether the node is focused.

See also
Focused

isHeading

fun isHeading(): SemanticsMatcher

Returns whether the node is marked as an accessibility header.

See also
Heading

isNotEnabled

fun isNotEnabled(): SemanticsMatcher

Returns whether the node is not enabled.

See also
Disabled

isNotFocusable

fun isNotFocusable(): SemanticsMatcher

Return whether the node is not able to receive focus.

See also
Focused

isNotFocused

fun isNotFocused(): SemanticsMatcher

Returns whether the node is not focused.

See also
Focused

isNotSelected

fun isNotSelected(): SemanticsMatcher

Returns whether the node is not selected.

See also
Selected

isOff

fun isOff(): SemanticsMatcher

Returns whether the node is not toggled.

See also
ToggleableState

isOn

fun isOn(): SemanticsMatcher

Returns whether the node is toggled.

See also
ToggleableState

isPopup

fun isPopup(): SemanticsMatcher

Returns whether the node is a popup.

This only checks if the node itself is a popup, not if it is part of a popup. Use hasAnyAncestorThat(isPopup()) for that.

See also
IsPopup

isRoot

fun isRoot(): SemanticsMatcher

Return whether the node is the root semantics node.

There is always one root in every node tree, added implicitly by Compose.

isSelectable

fun isSelectable(): SemanticsMatcher

Return whether the node is selectable.

See also
Selected

isSelected

fun isSelected(): SemanticsMatcher

Returns whether the node is selected.

See also
Selected

isToggleable

fun isToggleable(): SemanticsMatcher

Return whether the node is checkable.

See also
ToggleableState

removeGlobalAssertion

@ExperimentalTestApi
fun removeGlobalAssertion(name: String): Unit

Removes a named assertion from the collection of assertions to be executed before test actions.

Parameters
name: String

An identifier that was previously used in a call to addGlobalAssertion.

runAndroidComposeUiTest

@ExperimentalTestApi
inline fun <A : ComponentActivity> runAndroidComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    noinline block: AndroidComposeUiTest<A>.() -> Unit
): Unit

Variant of runComposeUiTest that allows you to specify which Activity should be launched. Be aware that if the Activity sets content during its launch, you cannot use setContent on the ComposeUiTest anymore as this would override the content and can lead to subtle bugs.

Parameters
<A : ComponentActivity>

The Activity type to be launched, which typically (but not necessarily) hosts the Compose content

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.

noinline block: AndroidComposeUiTest<A>.() -> Unit

The test function.

runAndroidComposeUiTest

@ExperimentalTestApi
fun <A : ComponentActivity> runAndroidComposeUiTest(
    activityClass: Class<A>,
    effectContext: CoroutineContext = EmptyCoroutineContext,
    block: AndroidComposeUiTest<A>.() -> Unit
): Unit

Variant of runComposeUiTest that allows you to specify which Activity should be launched. Be aware that if the Activity sets content during its launch, you cannot use setContent on the ComposeUiTest anymore as this would override the content and can lead to subtle bugs.

Parameters
<A : ComponentActivity>

The Activity type to be launched, which typically (but not necessarily) hosts the Compose content

activityClass: Class<A>

The Class of the Activity type to be launched, corresponding to A.

effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.

block: AndroidComposeUiTest<A>.() -> Unit

The test function.

runComposeUiTest

@ExperimentalTestApi
fun runComposeUiTest(
    effectContext: CoroutineContext = EmptyCoroutineContext,
    block: ComposeUiTest.() -> Unit
): Unit

Sets up the test environment, runs the given test and then tears down the test environment. Use the methods on ComposeUiTest in the test to find Compose content and make assertions on it. If you need access to platform specific elements (such as the Activity on Android), use one of the platform specific variants of this method, e.g. runAndroidComposeUiTest on Android.

Implementations of this method will launch a Compose host (such as an Activity on Android) for you. If your test needs to launch its own host, use a platform specific variant that doesn't launch anything for you (if available), e.g. runEmptyComposeUiTest on Android. Always make sure that the Compose content is set during execution of the test lambda so the test framework is aware of the content. Whether you need to launch the host from within the test lambda as well depends on the platform.

Keeping a reference to the ComposeUiTest outside of this function is an error.

Parameters
effectContext: CoroutineContext = EmptyCoroutineContext

The CoroutineContext used to run the composition. The context for LaunchedEffects and rememberCoroutineScope will be derived from this context. If this context contains a TestDispatcher or TestCoroutineScheduler (in that order), it will be used for composition and the MainTestClock.

block: ComposeUiTest.() -> Unit

The test function.

runEmptyComposeUiTest

@ExperimentalTestApi
fun runEmptyComposeUiTest(block: ComposeUiTest.() -> Unit): Unit

Variant of runComposeUiTest that does not launch an Activity to host Compose content in and thus acts as an "empty shell". Use this if you need to have control over the timing and method of launching the Activity, for example when you want to launch it with a custom Intent, or if you have a complex test setup.

When using this method, calling ComposeUiTest.setContent will throw an IllegalStateException. Instead, you'll have to set the content in the Activity that you have launched yourself, either directly on the Activity or on an androidx.compose.ui.platform.AbstractComposeView. You will need to do this from within the test lambda, or the test framework will not be able to find the content.

Extension functions

DarkMode

fun DeviceConfigurationOverride.Companion.DarkMode(isDarkMode: Boolean): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the dark mode or light mode theme for the contained content. Inside the content under test, isSystemInDarkTheme() will return isDarkMode.

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.ui.test.DarkMode
import androidx.compose.ui.test.DeviceConfigurationOverride

DeviceConfigurationOverride(DeviceConfigurationOverride.DarkMode(true)) {
    isSystemInDarkTheme() // will be true
}

FontScale

fun DeviceConfigurationOverride.Companion.FontScale(fontScale: Float): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the font scale for the contained content.

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.FontScale

DeviceConfigurationOverride(DeviceConfigurationOverride.FontScale(1.5f)) {
    MyScreen() // will be rendered with a larger than default font scale
}

FontWeightAdjustment

@RequiresApi(value = 31)
fun DeviceConfigurationOverride.Companion.FontWeightAdjustment(
    fontWeightAdjustment: Int
): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the font weight adjustment for the contained content.

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.FontWeightAdjustment

DeviceConfigurationOverride(DeviceConfigurationOverride.FontWeightAdjustment(200)) {
    MyComponent() // will be rendered with adjusted font weight
}

ForcedSize

fun DeviceConfigurationOverride.Companion.ForcedSize(size: DpSize): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the available size for the contained content.

This is only suitable for tests, since this will override LocalDensity to ensure that the size is met (as opposed to Modifier.requiredSize which will result in clipping).

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.ForcedSize
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp

DeviceConfigurationOverride(DeviceConfigurationOverride.ForcedSize(DpSize(1280.dp, 800.dp))) {
    MyScreen() // will be rendered in the space for 1280dp by 800dp without clipping
}

LayoutDirection

fun DeviceConfigurationOverride.Companion.LayoutDirection(
    layoutDirection: LayoutDirection
): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the layout direction for the contained content.

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.LayoutDirection
import androidx.compose.ui.unit.LayoutDirection

DeviceConfigurationOverride(DeviceConfigurationOverride.LayoutDirection(LayoutDirection.Rtl)) {
    MyComponent() // will be rendered with a right-to-left layout direction
}

Locales

fun DeviceConfigurationOverride.Companion.Locales(locales: LocaleList): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the locales for the contained content.

This will change resource resolution for the content under test, and also override the layout direction as specified by the locales.

import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.Locales
import androidx.compose.ui.text.intl.LocaleList

DeviceConfigurationOverride(DeviceConfigurationOverride.Locales(LocaleList("es-ES"))) {
    MyScreen() // will be rendered with overridden locale
}

RoundScreen

@RequiresApi(value = 23)
fun DeviceConfigurationOverride.Companion.RoundScreen(
    isScreenRound: Boolean
): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides whether the screen is round for the contained content.

import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.RoundScreen

DeviceConfigurationOverride(DeviceConfigurationOverride.RoundScreen(true)) {
    LocalConfiguration.current.isScreenRound // will be true
}

WindowInsets

fun DeviceConfigurationOverride.Companion.WindowInsets(
    windowInsets: WindowInsetsCompat
): DeviceConfigurationOverride

A DeviceConfigurationOverride that overrides the window insets for the contained content.

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.WindowInsets
import androidx.compose.ui.unit.DpRect
import androidx.compose.ui.unit.IntRect
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.roundToIntRect
import androidx.core.view.WindowInsetsCompat

fun IntRect.toAndroidXInsets() = androidx.core.graphics.Insets.of(left, top, right, bottom)

DeviceConfigurationOverride(
    DeviceConfigurationOverride.WindowInsets(
        WindowInsetsCompat.Builder()
            .setInsets(
                WindowInsetsCompat.Type.captionBar(),
                with(LocalDensity.current) { DpRect(0.dp, 64.dp, 0.dp, 0.dp).toRect() }
                    .roundToIntRect()
                    .toAndroidXInsets()
            )
            .setInsets(
                WindowInsetsCompat.Type.navigationBars(),
                with(LocalDensity.current) { DpRect(24.dp, 0.dp, 48.dp, 24.dp).toRect() }
                    .roundToIntRect()
                    .toAndroidXInsets()
            )
            .build()
    )
) {
    Box(
        Modifier.background(Color.Blue)
            // Will apply 64dp padding on the top, 24dp padding on the sides, and 48dp on the
            // bottom
            .safeDrawingPadding()
            .background(Color.Red)
    )
}

advanceEventTime

@ExperimentalTestApi
fun GestureScope.advanceEventTime(durationMillis: Long): Unit

Adds the given durationMillis to the current event time, delaying the next event by that time. Only valid when a gesture has already been started, or when a finished gesture is resumed.

animateMoveAlong

fun MouseInjectionScope.animateMoveAlong(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds. The mouse will initially be moved to the start of the path, curve(0), if it is not already there. The positions defined by the curve are in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Example of moving the mouse along a curve:

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.test.animateMoveAlong
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // Hover over the node, making a full circle with a radius of 100px
    val r = 100f
    animateMoveAlong(
        curve = {
            val angle = 2 * PI * it / 1000
            center + Offset(r * cos(angle).toFloat(), r * sin(angle).toFloat())
        },
        durationMillis = 1000L
    )
}
Parameters
curve: (timeMillis: Long) -> Offset

The function that defines the position of the mouse over time for this gesture, in the node's local coordinate system. The argument passed to the function is the time in milliseconds since the start of the animated move, and the return value is the location of the mouse at that point in time

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

animateMoveBy

fun MouseInjectionScope.animateMoveBy(
    delta: Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse from the current position by the given delta, sending a stream of move events to get an animated path of durationMillis milliseconds.

Parameters
delta: Offset

The position where to move the mouse to, relative to the current position of the mouse. For example, `delta = Offset(100.px, -100.px) will move the mouse 100 pixels to the right and 100 pixels upwards.

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

animateMoveTo

fun MouseInjectionScope.animateMoveTo(
    position: Offset,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Move the mouse from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds. Move the mouse to the desired start position if you want to start from a different position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Example of moving the mouse along a line:

import androidx.compose.ui.test.animateMoveTo
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // Hover over the node, making an X shape
    moveTo(topLeft)
    animateMoveTo(bottomRight)
    // Note that an actual user wouldn't be able to instantly
    // move from the bottom right to the top right
    moveTo(topRight)
    animateMoveTo(bottomLeft)
}
Parameters
position: Offset

The position where to move the mouse to, in the node's local coordinate system

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

assert

fun SemanticsNodeInteraction.assert(
    matcher: SemanticsMatcher,
    messagePrefixOnError: (() -> String)? = null
): SemanticsNodeInteraction

Asserts that the provided matcher is satisfied for this node.

Parameters
matcher: SemanticsMatcher

Matcher to verify.

messagePrefixOnError: (() -> String)? = null

Prefix to be put in front of an error that gets thrown in case this assert fails. This can be helpful in situations where this assert fails as part of a bigger operation that used this assert as a precondition check.

Throws
kotlin.AssertionError

if the matcher does not match or the node can no longer be found.

assertAll

fun SemanticsNodeInteractionCollection.assertAll(
    matcher: SemanticsMatcher
): SemanticsNodeInteractionCollection

Asserts that all the nodes in this collection satisfy the given matcher.

This passes also for empty collections.

Parameters
matcher: SemanticsMatcher

Matcher that has to be satisfied by all the nodes in the collection.

Throws
kotlin.AssertionError

if the collection contains at least one element that does not satisfy the given matcher.

assertAny

fun SemanticsNodeInteractionCollection.assertAny(
    matcher: SemanticsMatcher
): SemanticsNodeInteractionCollection

Asserts that this collection contains at least one element that satisfies the given matcher.

Parameters
matcher: SemanticsMatcher

Matcher that has to be satisfied by at least one of the nodes in the collection.

Throws
kotlin.AssertionError

if not at least one matching node was node.

assertContentDescriptionContains

fun SemanticsNodeInteraction.assertContentDescriptionContains(
    value: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false
): SemanticsNodeInteraction

Asserts that the node's content description contains the given value.

Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.

Throws AssertionError if the node's value does not contain value, or if the node has no value

Parameters
value: String

Value to match as one of the items in the list of content descriptions.

substring: Boolean = false

Whether this can be satisfied as a substring match of an item in the list of descriptions.

ignoreCase: Boolean = false

Whether case should be ignored.

assertContentDescriptionEquals

fun SemanticsNodeInteraction.assertContentDescriptionEquals(
    vararg values: String
): SemanticsNodeInteraction

Asserts that the node's content description contains exactly the given values and nothing else.

Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.

Throws AssertionError if the node's descriptions don't contain all items from values, or if the descriptions contain extra items that are not in values.

Parameters
vararg values: String

List of values to match (the order does not matter)

assertCountEquals

fun SemanticsNodeInteractionCollection.assertCountEquals(
    expectedSize: Int
): SemanticsNodeInteractionCollection

Asserts that this collection of nodes is equal to the given expectedSize.

Provides a detailed error message on failure.

Throws
kotlin.AssertionError

if the size is not equal to expectedSize

assertHasClickAction

fun SemanticsNodeInteraction.assertHasClickAction(): SemanticsNodeInteraction

Asserts that the current semantics node has a click action.

Throws AssertionError if the node is doesn't have a click action.

assertHasNoClickAction

fun SemanticsNodeInteraction.assertHasNoClickAction(): SemanticsNodeInteraction

Asserts that the current semantics node has doesn't have a click action.

Throws AssertionError if the node has a click action.

assertHeightIsAtLeast

fun SemanticsNodeInteraction.assertHeightIsAtLeast(expectedMinHeight: Dp): SemanticsNodeInteraction

Asserts that the layout of this node has height that is greater than or equal to expectedMinHeight.

Throws
kotlin.AssertionError

if comparison fails.

assertHeightIsEqualTo

fun SemanticsNodeInteraction.assertHeightIsEqualTo(expectedHeight: Dp): SemanticsNodeInteraction

Asserts that the layout of this node has height equal to expectedHeight.

Throws
kotlin.AssertionError

if comparison fails.

assertIsDisplayed

fun SemanticsNodeInteraction.assertIsDisplayed(): SemanticsNodeInteraction

Asserts that the current semantics node is displayed on screen.

Specifically, the node must be composed, placed and at least a portion of its bounds must be visible on screen after clipping is applied.

Throws AssertionError if the node is not displayed.

assertIsEnabled

fun SemanticsNodeInteraction.assertIsEnabled(): SemanticsNodeInteraction

Asserts that the current semantics node is enabled.

Throws AssertionError if the node is not enabled or does not define the property at all.

assertIsEqualTo

fun Dp.assertIsEqualTo(expected: Dp, subject: String, tolerance: Dp = Dp(.5f)): Unit

Asserts that this value is equal to the given expected value.

Performs the comparison with the given tolerance or the default one if none is provided. It is recommended to use tolerance when comparing positions and size coming from the framework as there can be rounding operation performed by individual layouts so the values can be slightly off from the expected ones.

Parameters
expected: Dp

The expected value to which this one should be equal to.

subject: String

Used in the error message to identify which item this assertion failed on.

tolerance: Dp = Dp(.5f)

The tolerance within which the values should be treated as equal.

Throws
kotlin.AssertionError

if comparison fails.

assertIsFocused

fun SemanticsNodeInteraction.assertIsFocused(): SemanticsNodeInteraction

Asserts that the current semantics node has a focus.

Throws AssertionError if the node is not in the focus or does not defined the property at all.

assertIsNotDisplayed

fun SemanticsNodeInteraction.assertIsNotDisplayed(): SemanticsNodeInteraction

Asserts that the current semantics node is not displayed on screen.

Throws AssertionError if the node is displayed.

assertIsNotEnabled

fun SemanticsNodeInteraction.assertIsNotEnabled(): SemanticsNodeInteraction

Asserts that the current semantics node is not enabled.

Throws AssertionError if the node is enabled or does not defined the property at all.

assertIsNotFocused

fun SemanticsNodeInteraction.assertIsNotFocused(): SemanticsNodeInteraction

Asserts that the current semantics node does not have a focus.

Throws AssertionError if the node is in the focus or does not defined the property at all.

assertIsNotSelected

fun SemanticsNodeInteraction.assertIsNotSelected(): SemanticsNodeInteraction

Asserts that the current semantics node is not selected.

Throws AssertionError if the node is selected or not selectable.

assertIsOff

fun SemanticsNodeInteraction.assertIsOff(): SemanticsNodeInteraction

Asserts that the current semantics node is unchecked.

Throws AssertionError if the node is checked, indeterminate, or not toggleable.

assertIsOn

fun SemanticsNodeInteraction.assertIsOn(): SemanticsNodeInteraction

Asserts that the current semantics node is checked.

Throws AssertionError if the node is not unchecked, indeterminate, or not toggleable.

assertIsSelectable

fun SemanticsNodeInteraction.assertIsSelectable(): SemanticsNodeInteraction

Asserts that the current semantics node is selectable.

Throws AssertionError if the node is not selectable.

assertIsSelected

fun SemanticsNodeInteraction.assertIsSelected(): SemanticsNodeInteraction

Asserts that the current semantics node is selected.

Throws AssertionError if the node is unselected or not selectable.

assertIsToggleable

fun SemanticsNodeInteraction.assertIsToggleable(): SemanticsNodeInteraction

Asserts that the current semantics node is toggleable.

Throws AssertionError if the node is not toggleable.

assertLeftPositionInRootIsEqualTo

fun SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(
    expectedLeft: Dp
): SemanticsNodeInteraction

Asserts that the layout of this node has the left position in the root composable that is equal to the given position.

Parameters
expectedLeft: Dp

The left (x) position to assert.

Throws
kotlin.AssertionError

if comparison fails.

assertPositionInRootIsEqualTo

fun SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
    expectedLeft: Dp,
    expectedTop: Dp
): SemanticsNodeInteraction

Asserts that the layout of this node has position in the root composable that is equal to the given position.

Parameters
expectedLeft: Dp

The left (x) position to assert.

expectedTop: Dp

The top (y) position to assert.

Throws
kotlin.AssertionError

if comparison fails.

assertRangeInfoEquals

fun SemanticsNodeInteraction.assertRangeInfoEquals(
    value: ProgressBarRangeInfo
): SemanticsNodeInteraction

Asserts the node's range info equals the given value.

For further details please check SemanticsProperties.ProgressBarRangeInfo. Throws AssertionError if the node's value is not equal to value, or if the node has no value

assertTextContains

fun SemanticsNodeInteraction.assertTextContains(
    value: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false
): SemanticsNodeInteraction

Asserts that the node's text contains the given value.

This will also search in SemanticsProperties.EditableText.

Note that in merged semantics tree there can be a list of text items that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to use.

Throws AssertionError if the node's value does not contain value, or if the node has no value

Parameters
value: String

Value to match as one of the items in the list of text values.

substring: Boolean = false

Whether this can be satisfied as a substring match of an item in the list of text.

ignoreCase: Boolean = false

Whether case should be ignored.

See also
Text

assertTextEquals

fun SemanticsNodeInteraction.assertTextEquals(
    vararg values: String,
    includeEditableText: Boolean = true
): SemanticsNodeInteraction

Asserts that the node's text contains exactly the given values and nothing else.

This will also search in SemanticsProperties.EditableText by default.

Note that in merged semantics tree there can be a list of text items that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to use.

Throws AssertionError if the node's text values don't contain all items from values, or if the text values contain extra items that are not in values.

Parameters
vararg values: String

List of values to match (the order does not matter)

includeEditableText: Boolean = true

Whether to also assert against the editable text.

assertTopPositionInRootIsEqualTo

fun SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(
    expectedTop: Dp
): SemanticsNodeInteraction

Asserts that the layout of this node has the top position in the root composable that is equal to the given position.

Parameters
expectedTop: Dp

The top (y) position to assert.

Throws
kotlin.AssertionError

if comparison fails.

assertTouchHeightIsEqualTo

fun SemanticsNodeInteraction.assertTouchHeightIsEqualTo(
    expectedHeight: Dp
): SemanticsNodeInteraction

Asserts that the touch bounds of this node has height equal to expectedHeight.

Throws
kotlin.AssertionError

if comparison fails.

assertTouchWidthIsEqualTo

fun SemanticsNodeInteraction.assertTouchWidthIsEqualTo(expectedWidth: Dp): SemanticsNodeInteraction

Asserts that the touch bounds of this node has width equal to expectedWidth.

Throws
kotlin.AssertionError

if comparison fails.

assertValueEquals

fun SemanticsNodeInteraction.assertValueEquals(value: String): SemanticsNodeInteraction

Asserts the node's value equals the given value.

For further details please check SemanticsProperties.StateDescription. Throws AssertionError if the node's value is not equal to value, or if the node has no value

assertWidthIsAtLeast

fun SemanticsNodeInteraction.assertWidthIsAtLeast(expectedMinWidth: Dp): SemanticsNodeInteraction

Asserts that the layout of this node has width that is greater than or equal to expectedMinWidth.

Throws
kotlin.AssertionError

if comparison fails.

assertWidthIsEqualTo

fun SemanticsNodeInteraction.assertWidthIsEqualTo(expectedWidth: Dp): SemanticsNodeInteraction

Asserts that the layout of this node has width equal to expectedWidth.

Throws
kotlin.AssertionError

if comparison fails.

cancel

fun GestureScope.cancel(): Unit

Sends a cancel event to cancel the current gesture. The cancel event contains the current position of all active pointers.

captureToImage

@RequiresApi(value = 26)
fun SemanticsNodeInteraction.captureToImage(): ImageBitmap

Captures the underlying semantics node's surface into bitmap. This can be used to capture nodes in a normal composable, a dialog if API >=28 and in a Popup. Note that the mechanism used to capture the bitmap from a Popup is not the same as from a normal composable, since a PopUp is in a different window.

Throws
kotlin.IllegalArgumentException

if we attempt to capture a bitmap of a dialog before API 28.

fun GestureScope.click(position: Offset = center): Unit

Performs a click gesture at the given position on the associated node, or in the center if the position is omitted. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default position is the center of the node.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center position will be used.

fun TouchInjectionScope.click(position: Offset = center): Unit

Performs a click gesture (aka a tap) on the associated node.

The click is done at the given position, or in the center if the position is omitted. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used.

fun MouseInjectionScope.click(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to click on position, or on the current mouse position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button. There is a small 60ms delay between the press and release events to have a realistic simulation.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

doubleClick

fun MouseInjectionScope.doubleClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to double-click on position, or on the current mouse position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

doubleClick

fun GestureScope.doubleClick(
    position: Offset = center,
    delayMillis: Long = doubleClickDelayMillis
): Unit

Performs a double click gesture at the given position on the associated node, or in the center if the position is omitted. By default, the delayMillis between the first and the second click is 145 milliseconds (empirically established). The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the double click, in the node's local coordinate system. If omitted, the center position will be used.

delayMillis: Long = doubleClickDelayMillis

The time between the up event of the first click and the down event of the second click

doubleClick

fun TouchInjectionScope.doubleClick(
    position: Offset = center,
    delayMillis: Long = viewConfiguration.defaultDoubleTapDelayMillis
): Unit

Performs a double click gesture (aka a double tap) on the associated node.

The double click is done at the given position or in the center if the position is omitted. By default, the delayMillis between the first and the second click is half way in between the minimum and maximum required delay for a double click. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the double click, in the node's local coordinate system. If omitted, the center position will be used.

delayMillis: Long = viewConfiguration.defaultDoubleTapDelayMillis

The time between the up event of the first click and the down event of the second click

fun GestureScope.down(position: Offset): Unit

Sends a down event for the default pointer at position on the associated node. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default pointer has pointerId = 0.

If no pointers are down yet, this will start a new gesture. If a gesture is already in progress, this event is sent with at the same timestamp as the last event. If the default pointer is already down, an IllegalArgumentException will be thrown.

Parameters
position: Offset

The position of the down event, in the node's local coordinate system

fun GestureScope.down(pointerId: Int, position: Offset): Unit

Sends a down event for the pointer with the given pointerId at position on the associated node. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

If no pointers are down yet, this will start a new gesture. If a gesture is already in progress, this event is sent with at the same timestamp as the last event. If the given pointer is already down, an IllegalArgumentException will be thrown.

Subsequent events for this or other gestures can be spread out over both this and future invocations of performGesture. An entire gesture starts with a down event, followed by several down, move or up events, and ends with an up or a cancel event. Movement can be expressed with moveTo and moveBy to move a single pointer at a time, or movePointerTo and movePointerBy to move multiple pointers at a time. The movePointer[To|By] methods do not send the move event directly, use move to send the move event. Some other methods can send a move event as well. All events, regardless the method used, will always contain the current position of all pointers.

Down and up events are sent at the same time as the previous event, but will send an extra move event just before the down or up event if movePointerTo or movePointerBy has been called and no move event has been sent yet. This does not happen for cancel events, but the cancel event will contain the up to date position of all pointers. Move and cancel events will advance the event time by 16 milliseconds.

Because gestures don't have to be defined all in the same performGesture block, keep in mind that while the gesture is not complete, all code you execute in between blocks that progress the gesture, will be executed while imaginary fingers are actively touching the screen.

In the context of testing, it is not necessary to complete a gesture with an up or cancel event, if the test ends before it expects the finger to be lifted from the screen.

Parameters
pointerId: Int

The id of the pointer, can be any number not yet in use by another pointer

position: Offset

The position of the down event, in the node's local coordinate system

dragAndDrop

fun MouseInjectionScope.dragAndDrop(
    start: Offset,
    end: Offset,
    button: MouseButton = MouseButton.Primary,
    durationMillis: Long = DefaultMouseGestureDurationMillis
): Unit

Use button to drag and drop something from start to end in durationMillis milliseconds. The mouse position is updated to the start position before starting the gesture. The positions defined by the start and end are in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
start: Offset

The position where to press the primary mouse button and initiate the drag, in the node's local coordinate system.

end: Offset

The position where to release the primary mouse button and end the drag, in the node's local coordinate system.

button: MouseButton = MouseButton.Primary

The button to drag with. Uses the primary by default.

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

filter

fun SemanticsNodeInteractionCollection.filter(matcher: SemanticsMatcher): SemanticsNodeInteractionCollection

Returns all the nodes matching the given matcher.

Parameters
matcher: SemanticsMatcher

Matcher to use for the filtering.

filterToOne

fun SemanticsNodeInteractionCollection.filterToOne(
    matcher: SemanticsMatcher
): SemanticsNodeInteraction

Expects to return exactly one node matching the given matcher.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if no element is found.

Parameters
matcher: SemanticsMatcher

Matcher to use for the filtering.

getAlignmentLinePosition

fun SemanticsNodeInteraction.getAlignmentLinePosition(
    alignmentLine: AlignmentLine
): Dp

Returns the position of an alignment line, or Dp.Unspecified if the line is not provided.

getBoundsInRoot

fun SemanticsNodeInteraction.getBoundsInRoot(): DpRect

Returns the bounds of the layout of this node as clipped to the root. The bounds are relative to the root composable.

getFirstLinkBounds

fun SemanticsNodeInteraction.getFirstLinkBounds(
    predicate: (AnnotatedString.Range<LinkAnnotation>) -> Boolean = { true }
): Rect?

Returns the bounds of the first link matching the predicate, or if that link spans multiple lines, returns the bounds of the first line of the link.

A link in a Text composable is defined by a LinkAnnotation of the AnnotatedString.

The bounds are in the text node's coordinate system.

You can pass an offset from within the bounds to injection methods to operate them on the link, for example TouchInjectionScope.click or MouseInjectionScope.moveTo.

import androidx.compose.ui.test.getFirstLinkBounds
import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performMouseInput
import androidx.compose.ui.text.LinkAnnotation

// Example of hovering over the first link in test
val firstLinkBounds =
    composeTestRule.onNodeWithText("YOUR_TEXT_WITH_LINK").getFirstLinkBounds {
        (it.item as? LinkAnnotation.Url)?.url == "YOUR_URL"
    }

composeTestRule.onNodeWithText("YOUR_TEXT_WITH_LINK").performMouseInput {
    moveTo(firstLinkBounds!!.center)
}

getUnclippedBoundsInRoot

fun SemanticsNodeInteraction.getUnclippedBoundsInRoot(): DpRect

Returns the bounds of the layout of this node. The bounds are relative to the root composable.

invokeGlobalAssertions

@ExperimentalTestApi
fun SemanticsNodeInteraction.invokeGlobalAssertions(): SemanticsNodeInteraction

Executes all of the assertions registered by addGlobalAssertion. This may be useful in a custom test action.

Returns
SemanticsNodeInteraction

the SemanticsNodeInteraction that is the receiver of this method

invokeGlobalAssertions

@ExperimentalTestApi
fun SemanticsNodeInteractionCollection.invokeGlobalAssertions(): SemanticsNodeInteractionCollection

Executes all of the assertions registered by addGlobalAssertion, each of which will receive the first node of this collection. This may be useful in a custom test action.

Returns
SemanticsNodeInteractionCollection

the SemanticsNodeInteractionCollection that is the receiver of this method

isDisplayed

fun SemanticsNodeInteraction.isDisplayed(): Boolean

Returns true if the matched node is displayed on screen.

Specifically, the node must be composed, placed and at least a portion of its bounds must be visible on screen after clipping is applied. If no matching node is found, returns false. If multiple nodes match, throws an AssertionError.

import androidx.compose.ui.test.isDisplayed
import androidx.compose.ui.test.onNodeWithTag

val interaction = composeTestRule.onNodeWithTag("test")
composeTestRule.waitUntil { interaction.isDisplayed() }
Throws
kotlin.AssertionError

If multiple nodes match this SemanticsNodeInteraction.

isNotDisplayed

fun SemanticsNodeInteraction.isNotDisplayed(): Boolean

Asserts that the current semantics node is not displayed on screen.

If no matching node is found, returns true. If multiple nodes match, throws an AssertionError.

import androidx.compose.ui.test.isNotDisplayed
import androidx.compose.ui.test.onNodeWithTag

val interaction = composeTestRule.onNodeWithTag("test")
composeTestRule.waitUntil { interaction.isNotDisplayed() }
Throws
kotlin.AssertionError

If multiple nodes match this SemanticsNodeInteraction.

longClick

fun MouseInjectionScope.longClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to long-click on position, or on the current mouse position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

longClick

fun GestureScope.longClick(
    position: Offset = center,
    durationMillis: Long = LongPressTimeoutMillis + 100
): Unit

Performs a long click gesture at the given position on the associated node, or in the center if the position is omitted. By default, the durationMillis of the press is LongPressTimeoutMillis + 100 milliseconds. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the long click, in the node's local coordinate system. If omitted, the center position will be used.

durationMillis: Long = LongPressTimeoutMillis + 100

The time between the down and the up event

longClick

fun TouchInjectionScope.longClick(
    position: Offset = center,
    durationMillis: Long = viewConfiguration.longPressTimeoutMillis + 100
): Unit

Performs a long click gesture (aka a long press) on the associated node.

The long click is done at the given position, or in the center if the position is omitted. By default, the durationMillis of the press is 100ms longer than the minimum required duration for a long press. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position of the long click, in the node's local coordinate system. If omitted, the center of the node will be used.

durationMillis: Long = viewConfiguration.longPressTimeoutMillis + 100

The time between the down and the up event

move

fun GestureScope.move(): Unit

Sends a move event without updating any of the pointer positions. This can be useful when batching movement of multiple pointers together, which can be done with movePointerTo and movePointerBy.

fun GestureScope.moveBy(delta: Offset): Unit

Sends a move event on the associated node, with the position of the default pointer moved by the given delta. The default pointer has pointerId = 0.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

fun GestureScope.moveBy(pointerId: Int, delta: Offset): Unit

Sends a move event on the associated node, with the position of the pointer with the given pointerId moved by the given delta.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

movePointerBy

fun GestureScope.movePointerBy(pointerId: Int, delta: Offset): Unit

Moves the position of the pointer with the given pointerId by the given delta, but does not send a move event. The move event can be sent with move.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

delta: Offset

The position for this move event, relative to the last sent position of the pointer. For example, `delta = Offset(10.px, -10.px) will add 10.px to the pointer's last x-position, and subtract 10.px from the pointer's last y-position.

movePointerTo

fun GestureScope.movePointerTo(pointerId: Int, position: Offset): Unit

Updates the position of the pointer with the given pointerId to the given position, but does not send a move event. The move event can be sent with move. The position is in the node's local coordinate system, where (0.px, 0.px) is the top left corner of the node.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

position: Offset

The new position of the pointer, in the node's local coordinate system

fun GestureScope.moveTo(position: Offset): Unit

Sends a move event on the associated node, with the position of the default pointer updated to position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default pointer has pointerId = 0.

If the default pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
position: Offset

The new position of the pointer, in the node's local coordinate system

fun GestureScope.moveTo(pointerId: Int, position: Offset): Unit

Sends a move event on the associated node, with the position of the pointer with the given pointerId updated to position. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

If the pointer is not yet down, an IllegalArgumentException will be thrown.

Parameters
pointerId: Int

The id of the pointer to move, as supplied in down

position: Offset

The new position of the pointer, in the node's local coordinate system

multiTouchSwipe

fun TouchInjectionScope.multiTouchSwipe(
    curves: List<(timeMillis: Long) -> Offset>,
    durationMillis: Long = 200,
    keyTimes: List<Long> = emptyList()
): Unit

Performs a multi touch swipe gesture on the associated node.

Each pointer follows curves[i] from 0 till durationMillis. Sampling of an event is forced at all times defined in keyTimes. The time between events is kept as close to eventPeriodMillis as possible, given the constraints. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Parameters
curves: List<(timeMillis: Long) -> Offset>

The functions that describe the gesture. Function i defines the position over time for pointer id i. The argument passed to each function is the time in milliseconds since the start of the swipe, and the return value is the location of that pointer at that point in time.

durationMillis: Long = 200

The duration of the gesture

keyTimes: List<Long> = emptyList()

An optional list of timestamps in milliseconds at which a move event must be sampled

onAllNodesWithContentDescription

fun SemanticsNodeInteractionsProvider.onAllNodesWithContentDescription(
    label: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteractionCollection

Finds all semantics nodes with the given label as content description.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
label: String

The text to search for.

substring: Boolean = false

If true, allows matches where the label is a substring of the content description.

ignoreCase: Boolean = false

If true, does a case-insensitive search.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onAllNodes

for more information.

onAllNodesWithTag

fun SemanticsNodeInteractionsProvider.onAllNodesWithTag(
    testTag: String,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteractionCollection

Finds all semantics nodes identified by the given tag.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
testTag: String

The tag to search for. Looks for exact matches only.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onAllNodes

for more information.

onAllNodesWithText

fun SemanticsNodeInteractionsProvider.onAllNodesWithText(
    text: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteractionCollection

Finds all semantics nodes with the given text.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
text: String

The text to search for.

substring: Boolean = false

If true, allows matches where the label is a substring of the content description.

ignoreCase: Boolean = false

If true, does a case-insensitive search.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onAllNodes

for more information.

onAncestors

fun SemanticsNodeInteraction.onAncestors(): SemanticsNodeInteractionCollection

Returns all the ancestors of this node.

Example: For the following tree

|-A
|-B
|-C <- this node
Returns B, A

onChild

fun SemanticsNodeInteraction.onChild(): SemanticsNodeInteraction

Returns exactly one child of this node.

Use this only if this node has exactly one child.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if none or more than one element is found.

onChildAt

fun SemanticsNodeInteraction.onChildAt(index: Int): SemanticsNodeInteraction

Returns child of this node at the given index.

This is just a shortcut for "childrenindex".

onChildren

fun SemanticsNodeInteraction.onChildren(): SemanticsNodeInteractionCollection

Returns children of this node.

onFirst

fun SemanticsNodeInteractionCollection.onFirst(): SemanticsNodeInteraction

Returns the first node in this collection.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if no element is found.

onLast

fun SemanticsNodeInteractionCollection.onLast(): SemanticsNodeInteraction

Returns the last node in this collection.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if no element is found.

onNodeWithContentDescription

fun SemanticsNodeInteractionsProvider.onNodeWithContentDescription(
    label: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteraction

Finds a semantics node with the given content description.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
label: String

The text to search for.

substring: Boolean = false

If true, allows matches where the label is a substring of the content description.

ignoreCase: Boolean = false

If true, does a case-insensitive search.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onNode

for more information.

onNodeWithTag

fun SemanticsNodeInteractionsProvider.onNodeWithTag(
    testTag: String,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteraction

Finds a semantics node identified by the given tag.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
testTag: String

The tag to search for. Looks for an exact match only.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onNode

for more information.

onNodeWithText

fun SemanticsNodeInteractionsProvider.onNodeWithText(
    text: String,
    substring: Boolean = false,
    ignoreCase: Boolean = false,
    useUnmergedTree: Boolean = false
): SemanticsNodeInteraction

Finds a semantics node with the given text.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
text: String

The text to search for.

substring: Boolean = false

If true, allows matches where the label is a substring of the content description.

ignoreCase: Boolean = false

If true, does a case-insensitive search.

useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

See also
onNode

for more information.

onParent

fun SemanticsNodeInteraction.onParent(): SemanticsNodeInteraction

Returns a parent of this node.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if none or more than one element is found.

onRoot

fun SemanticsNodeInteractionsProvider.onRoot(
    useUnmergedTree: Boolean = false
): SemanticsNodeInteraction

Finds the root semantics node of the Compose tree.

Useful for example for screenshot tests of the entire scene.

For usage patterns and semantics concepts see SemanticsNodeInteraction

Parameters
useUnmergedTree: Boolean = false

If true, searches the unmerged semantics tree instead of the merged semantics tree.

onSibling

fun SemanticsNodeInteraction.onSibling(): SemanticsNodeInteraction

Returns exactly one sibling of this node.

Use this only if this node has exactly one sibling.

Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if none or more than one element is found.

onSiblings

fun SemanticsNodeInteraction.onSiblings(): SemanticsNodeInteractionCollection

Returns all siblings of this node.

Example: For the following tree

|-A
|-B1
|-B2 <- this node
|-B3
Returns B1, B3

percentOffset

fun GestureScope.percentOffset(x: Float = 0.0f, y: Float = 0.0f): Offset

Creates an Offset relative to the size of the node we're interacting with. x and y are fractions of the width and height, between -1 and 1. Note that percentOffset(1f, 1f) != bottomRight, see right and bottom.

For example: percentOffset(.5f, .5f) is the same as the center; centerLeft + percentOffset(.1f, 0f) is a point 10% inward from the middle of the left edge; and bottomRight - percentOffset(.2f, .1f) is a point 20% to the left and 10% to the top of the bottom right corner.

performClick

fun SemanticsNodeInteraction.performClick(): SemanticsNodeInteraction

Performs a click action on the element represented by the given semantics node. Depending on the platform this may be implemented by a touch click (tap), a mouse click, or another more appropriate method for that platform.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performCustomAccessibilityActionWithLabel

@ExperimentalTestApi
fun SemanticsNodeInteraction.performCustomAccessibilityActionWithLabel(
    label: String
): SemanticsNodeInteraction

Finds the CustomAccessibilityAction in the node's CustomActions list whose label is equal to label and then invokes it.

To use your own logic to find the action to perform instead of matching on the full label, use performCustomAccessibilityActionWithLabelMatching.

Parameters
label: String

The exact label of the CustomAccessibilityAction to perform.

Throws
kotlin.AssertionError

If no SemanticsNode is found, or no CustomAccessibilityAction has label, or more than one CustomAccessibilityAction has label.

performCustomAccessibilityActionWithLabelMatching

@ExperimentalTestApi
fun SemanticsNodeInteraction.performCustomAccessibilityActionWithLabelMatching(
    predicateDescription: String? = null,
    labelPredicate: (label: String) -> Boolean
): SemanticsNodeInteraction

Finds the CustomAccessibilityAction in the node's CustomActions list whose label satisfies a predicate function and then invokes it.

Parameters
predicateDescription: String? = null

A description of labelPredicate that will be included in the error message if zero or >1 actions match.

labelPredicate: (label: String) -> Boolean

A predicate function used to select the CustomAccessibilityAction to perform.

performFirstLinkClick

fun SemanticsNodeInteraction.performFirstLinkClick(
    predicate: (AnnotatedString.Range<LinkAnnotation>) -> Boolean = { true }
): SemanticsNodeInteraction

For a first link matching the predicate performs a click on it.

A link in a Text composable is defined by a LinkAnnotation of the AnnotatedString.

import androidx.compose.ui.test.onNodeWithText
import androidx.compose.ui.test.performFirstLinkClick
import androidx.compose.ui.text.LinkAnnotation

// Example of clicking on a link in test
composeTestRule.onNodeWithText("YOUR_TEXT_WITH_LINK").performFirstLinkClick {
    (it.item as? LinkAnnotation.Url)?.url == "YOUR_URL"
}

performGesture

fun SemanticsNodeInteraction.performGesture(block: GestureScope.() -> Unit): SemanticsNodeInteraction

Executes the (partial) gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of performGesture. The event time is initialized to the current time of the MainTestClock.

Be aware that if you split a gesture over multiple invocations of performGesture, everything that happens in between will run as if the gesture is still ongoing (imagine a finger still touching the screen).

All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.

Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.

Example of performing a click:

import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performGesture

composeTestRule.onNodeWithTag("myComponent").performGesture { click() }
Parameters
block: GestureScope.() -> Unit

A lambda with GestureScope as receiver that describes the gesture by sending all touch events.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performImeAction

fun SemanticsNodeInteraction.performImeAction(): Unit

Sends to this node the IME action associated with it in a similar way to the IME.

The node needs to define its IME action in semantics via SemanticsPropertyReceiver.onImeAction.

Throws
kotlin.AssertionError

if the node does not support input or does not define IME action.

kotlin.IllegalStateException

if the node did is not an editor or would not be able to establish an input connection (e.g. does not define ImeAction or OnImeAction or is not focused).

performKeyInput

@ExperimentalTestApi
fun SemanticsNodeInteraction.performKeyInput(block: KeyInjectionScope.() -> Unit): SemanticsNodeInteraction

Executes the key input gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of one of the perform.*Input methods. The event time is initialized to the current time of the MainTestClock.

All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.

Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.

Parameters
block: KeyInjectionScope.() -> Unit

A lambda with KeyInjectionScope as receiver that describes the gesture by sending all key press events.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performKeyPress

fun SemanticsNodeInteraction.performKeyPress(keyEvent: KeyEvent): Boolean

Send the specified KeyEvent to the focused component.

Returns
Boolean

true if the event was consumed. False otherwise.

performMouseInput

fun SemanticsNodeInteraction.performMouseInput(block: MouseInjectionScope.() -> Unit): SemanticsNodeInteraction

Executes the mouse gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of one of the perform.*Input methods. The event time is initialized to the current time of the MainTestClock.

Be aware that if you split a gesture over multiple invocations of perform.*Input, everything that happens in between will run as if the gesture is still ongoing (imagine a mouse button still being pressed).

All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.

Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.

Example of performing a mouse click:

import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule.onNodeWithTag("myComponent").performMouseInput {
    // Click in the middle of the node
    click(center)
}

Example of scrolling the mouse wheel while the mouse button is pressed:

import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput

composeTestRule
    .onNodeWithTag("verticalScrollable")
    // Scroll downwards while keeping a button pressed:
    .performMouseInput {
        // Presses the primary mouse button
        press()
        // Scroll the scroll wheel by 6 units
        repeat(6) {
            advanceEventTime()
            scroll(1f)
        }
        // And release the mouse button
        advanceEventTime()
        release()
    }
Parameters
block: MouseInjectionScope.() -> Unit

A lambda with MouseInjectionScope as receiver that describes the gesture by sending all mouse events.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performMultiModalInput

fun SemanticsNodeInteraction.performMultiModalInput(block: MultiModalInjectionScope.() -> Unit): SemanticsNodeInteraction

Executes the multi-modal gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of one of the perform.*Input methods. The event time is initialized to the current time of the MainTestClock. If only a single modality is needed (e.g. touch, mouse, stylus, keyboard, etc), you should use the perform.*Input of that modality instead.

Functions for each modality can be called by invoking that modality's function, like touch to inject touch events. This allows you to inject events for each modality.

Be aware that if you split a gesture over multiple invocations of perform.*Input, everything that happens in between will run as if the gesture is still ongoing (imagine a finger still touching the screen).

All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.

Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.

Parameters
block: MultiModalInjectionScope.() -> Unit

A lambda with MultiModalInjectionScope as receiver that describes the gesture by sending all multi modal events.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performRotaryScrollInput

@ExperimentalTestApi
fun SemanticsNodeInteraction.performRotaryScrollInput(block: RotaryInjectionScope.() -> Unit): SemanticsNodeInteraction

Send the specified RotaryScrollEvent to the focused component.

Returns
SemanticsNodeInteraction

true if the event was consumed. False otherwise.

performScrollTo

fun SemanticsNodeInteraction.performScrollTo(): SemanticsNodeInteraction

Scrolls the closest enclosing scroll parent by the smallest amount such that this node is fully visible in its viewport. If this node is larger than the viewport, scrolls the scroll parent by the smallest amount such that this node fills the entire viewport. A scroll parent is a parent node that has the semantics action SemanticsActions.ScrollBy (usually implemented by defining scrollBy).

This action should be performed on the node that is part of the scrollable content, not on the scrollable container.

Throws an AssertionError if there is no scroll parent.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performScrollToIndex

fun SemanticsNodeInteraction.performScrollToIndex(index: Int): SemanticsNodeInteraction

Scrolls a scrollable container with items to the item with the given index.

Note that not all scrollable containers have item indices. For example, a scrollable doesn't have items with an index, while LazyColumn does.

This action should be performed on a node that is a scrollable container, not on a node that is part of the content of that container.

Throws an AssertionError if the node doesn't have ScrollToIndex defined.

Parameters
index: Int

The index of the item to scroll to

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performScrollToKey

fun SemanticsNodeInteraction.performScrollToKey(key: Any): SemanticsNodeInteraction

Scrolls a scrollable container with keyed items to the item with the given key, such as LazyColumn or LazyRow.

This action should be performed on a node that is a scrollable container, not on a node that is part of the content of that container.

Throws an AssertionError if the node doesn't have IndexForKey or ScrollToIndex defined.

Parameters
key: Any

The key of the item to scroll to

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

performScrollToNode

fun SemanticsNodeInteraction.performScrollToNode(
    matcher: SemanticsMatcher
): SemanticsNodeInteraction

Scrolls a scrollable container to the content that matches the given matcher. If the content isn't yet visible, the scrollable container will be scrolled from the start till the end till it finds the content we're looking for. It is not defined where in the viewport the content will be on success of this function, but it will be either fully within the viewport if it is smaller than the viewport, or it will cover the whole viewport if it is larger than the viewport. If it doesn't find the content, the scrollable will be left at the end of the content and an AssertionError is thrown.

This action should be performed on a node that is a scrollable container, not on a node that is part of the content of that container. If the container is a lazy container, it must support the semantics actions ScrollToIndex, ScrollBy, and either HorizontalScrollAxisRange or VerticalScrollAxisRange, for example LazyColumn and LazyRow. If the container is not lazy, it must support the semantics action ScrollBy, for example, Row or Column.

Throws an AssertionError if the scrollable node doesn't support the necessary semantics actions.

Parameters
matcher: SemanticsMatcher

A matcher that identifies the content where the scrollable container needs to scroll to

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method. Note that this is not an interaction for the node that is identified by the matcher.

performSemanticsAction

fun SemanticsNodeInteraction.performSemanticsAction(
    key: SemanticsPropertyKey<AccessibilityAction<() -> Boolean>>
): SemanticsNodeInteraction

Provides support to call custom semantics actions on this node.

This method is for calling actions that have no parameters.

This will properly verify that the actions exists and provide clear error message in case it does not. It also handle synchronization and performing the action on the UI thread. This call is blocking until the action is performed

Parameters
key: SemanticsPropertyKey<AccessibilityAction<() -> Boolean>>

Key of the action to be performed.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

Throws
kotlin.AssertionError

If the semantics action is not defined on this node.

performSemanticsAction

fun <T : () -> Boolean> SemanticsNodeInteraction.performSemanticsAction(
    key: SemanticsPropertyKey<AccessibilityAction<T>>,
    invocation: (T) -> Unit
): SemanticsNodeInteraction

Provides support to call custom semantics actions on this node.

This method is supposed to be used for actions with parameters.

This will properly verify that the actions exists and provide clear error message in case it does not. It also handle synchronization and performing the action on the UI thread. This call is blocking until the action is performed

Parameters
key: SemanticsPropertyKey<AccessibilityAction<T>>

Key of the action to be performed.

invocation: (T) -> Unit

Place where you call your action. In the argument is provided the underlying action from the given Semantics action.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

Throws
kotlin.AssertionError

If the semantics action is not defined on this node.

performTextClearance

fun SemanticsNodeInteraction.performTextClearance(): Unit

Clears the text in this node in similar way to IME.

performTextInput

fun SemanticsNodeInteraction.performTextInput(text: String): Unit

Sends the given text to this node in similar way to IME.

Parameters
text: String

Text to send.

performTextInputSelection

@ExperimentalTestApi
fun SemanticsNodeInteraction.performTextInputSelection(
    selection: TextRange
): Unit

Sends the given selection to this node in similar way to IME.

Parameters
selection: TextRange

selection to send

performTextReplacement

fun SemanticsNodeInteraction.performTextReplacement(text: String): Unit

Replaces existing text with the given text in this node in similar way to IME.

This does not reflect text selection. All the text gets cleared out and new inserted.

Parameters
text: String

Text to send.

performTouchInput

fun SemanticsNodeInteraction.performTouchInput(block: TouchInjectionScope.() -> Unit): SemanticsNodeInteraction

Executes the touch gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of one of the perform.*Input methods. The event time is initialized to the current time of the MainTestClock.

Be aware that if you split a gesture over multiple invocations of perform.*Input, everything that happens in between will run as if the gesture is still ongoing (imagine a finger still touching the screen).

All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.

Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.

Example of performing a swipe up:

import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeUp

composeTestRule.onNodeWithTag("myComponent").performTouchInput { swipeUp() }

Example of performing an off-center click:

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput

composeTestRule.onNodeWithTag("myComponent").performTouchInput {
    click(percentOffset(.2f, .5f))
}

Example of doing an assertion during a click:

import androidx.compose.ui.test.assertHasClickAction
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput

composeTestRule
    .onNodeWithTag("myComponent")
    .performTouchInput { down(topLeft) }
    .assertHasClickAction()
    .performTouchInput { up() }

Example of performing a click-and-drag:

import androidx.compose.ui.test.click
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performTouchInput
import androidx.compose.ui.test.swipeUp

composeTestRule.onNodeWithTag("myComponent").performTouchInput {
    click()
    advanceEventTime(100)
    swipeUp()
}
Parameters
block: TouchInjectionScope.() -> Unit

A lambda with TouchInjectionScope as receiver that describes the gesture by sending all touch events.

Returns
SemanticsNodeInteraction

The SemanticsNodeInteraction that is the receiver of this method

fun GestureScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long = 400
): Unit

Performs a pinch gesture on the associated node.

For each pair of start and end Offsets, the motion events are linearly interpolated. The coordinates are in the node's local coordinate system where (0, 0) is the top left corner of the node. The default duration is 400 milliseconds.

Parameters
start0: Offset

The start position of the first gesture in the node's local coordinate system

end0: Offset

The end position of the first gesture in the node's local coordinate system

start1: Offset

The start position of the second gesture in the node's local coordinate system

end1: Offset

The end position of the second gesture in the node's local coordinate system

durationMillis: Long = 400

the duration of the gesture

fun TouchInjectionScope.pinch(
    start0: Offset,
    end0: Offset,
    start1: Offset,
    end1: Offset,
    durationMillis: Long = 400
): Unit

Performs a pinch gesture on the associated node.

For each pair of start and end Offsets, the motion events are linearly interpolated. The coordinates are in the node's local coordinate system where (0, 0) is the top left corner of the node. The default duration is 400 milliseconds.

Parameters
start0: Offset

The start position of the first gesture in the node's local coordinate system

end0: Offset

The end position of the first gesture in the node's local coordinate system

start1: Offset

The start position of the second gesture in the node's local coordinate system

end1: Offset

The end position of the second gesture in the node's local coordinate system

durationMillis: Long = 400

the duration of the gesture

pressKey

fun KeyInjectionScope.pressKey(
    key: Key,
    pressDurationMillis: Long = DefaultKeyPressDurationMillis
): Unit

Holds down the given key for the given pressDurationMillis by sending a key down event, advancing the event time and sending a key up event.

If the given key is already down, an IllegalStateException will be thrown.

Parameters
key: Key

The key to be pressed down.

pressDurationMillis: Long = DefaultKeyPressDurationMillis

Duration of press in milliseconds.

printToLog

fun SemanticsNodeInteraction.printToLog(
    tag: String,
    maxDepth: Int = Int.MAX_VALUE
): Unit

Prints all the semantics nodes information into logs (as debug level).

By default this also prints all the sub-hierarchy. This can be changed by setting a custom max depth in maxDepth.

Note that this will fetch the latest snapshot of nodes it sees in the hierarchy for the IDs it collected before. So the output can change over time if the tree changes.

Parameters
tag: String

The tag to be used in the log messages.

maxDepth: Int = Int.MAX_VALUE

Max depth of the nodes in hierarchy to print. Zero will print just this node. Must not be negative.

printToLog

fun SemanticsNodeInteractionCollection.printToLog(
    tag: String,
    maxDepth: Int = 0
): Unit

Prints all the semantics nodes information into logs (as debug level).

By default this does not print nodes sub-hierarchies. This can be changed by setting a custom max depth in maxDepth.

Note that this will fetch the latest snapshot of nodes it sees in the hierarchy for the IDs it collected before. So the output can change over time if the tree changes.

Parameters
tag: String

The tag to be used in the log messages. Must not be negative.

maxDepth: Int = 0

Max depth of the nodes in hierarchy to print. Zero will print nodes in this collection only.

printToString

fun SemanticsNodeInteraction.printToString(maxDepth: Int = Int.MAX_VALUE): String

Prints all the semantics nodes information it holds into string.

By default this also prints all the sub-hierarchy. This can be changed by setting a custom max depth in maxDepth.

Note that this will fetch the latest snapshot of nodes it sees in the hierarchy for the IDs it collected before. So the output can change over time if the tree changes.

Parameters
maxDepth: Int = Int.MAX_VALUE

Max depth of the nodes in hierarchy to print. Zero will print just this node. Must not be negative.

printToString

fun SemanticsNodeInteractionCollection.printToString(maxDepth: Int = 0): String

Prints all the semantics nodes information it holds into string.

By default this does not print nodes sub-hierarchies. This can be changed by setting a custom max depth in maxDepth.

Note that this will fetch the latest snapshot of nodes it sees in the hierarchy for the IDs it collected before. So the output can change over time if the tree changes.

Parameters
maxDepth: Int = 0

Max depth of the nodes in hierarchy to print. Zero will print nodes in this collection only. Must not be negative.

requestFocus

fun SemanticsNodeInteraction.requestFocus(): SemanticsNodeInteraction

Requests the focus system to give focus to this node by invoking the RequestFocus semantics action.

rightClick

fun MouseInjectionScope.rightClick(position: Offset = center): Unit

Secondary-click on position, or on the current mouse position if position is unspecified. While the secondary mouse button is not necessarily the right mouse button (e.g. on left-handed mice), this method is still called rightClick for it's widespread use. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

smoothScroll

fun MouseInjectionScope.smoothScroll(
    scrollAmount: Float,
    durationMillis: Long = DefaultMouseGestureDurationMillis,
    scrollWheel: ScrollWheel = ScrollWheel.Vertical
): Unit

Rotate the mouse's scrollWheel by the given scrollAmount. The total scroll delta is linearly smoothed out over a stream of scroll events between each scroll event.

Positive scrollAmount values correspond to scrolling forward (new content appears at the bottom of a column, or at the end of a row), negative values correspond to scrolling backward (new content appears at the top of a column, or at the start of a row).

Example of a horizontal smooth scroll:

import androidx.compose.ui.test.ScrollWheel
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performMouseInput
import androidx.compose.ui.test.smoothScroll

composeTestRule.onNodeWithTag("horizontalScrollable").performMouseInput {
    // Scroll forwards horizontally, which is rightwards
    // unless scroll direction is reversed
    smoothScroll(100f, durationMillis = 500L, ScrollWheel.Horizontal)
    // The 100f scroll delta is equally divided into smaller scrolls,
    // such that the time in between two scroll events is more or less
    // equal to the default time between events, 16ms.
}
Parameters
scrollAmount: Float

The total delta to scroll the scrollWheel by

durationMillis: Long = DefaultMouseGestureDurationMillis

The duration of the gesture. By default 300 milliseconds.

scrollWheel: ScrollWheel = ScrollWheel.Vertical

Which scroll wheel will be rotated. By default ScrollWheel.Vertical.

See also
scroll

swipe

fun TouchInjectionScope.swipe(
    curve: (timeMillis: Long) -> Offset,
    durationMillis: Long = 200,
    keyTimes: List<Long> = emptyList()
): Unit

Performs a swipe gesture on the associated node.

The swipe follows the curve from 0 till durationMillis. Will force sampling of an event at all times defined in keyTimes. The time between events is kept as close to eventPeriodMillis as possible, given the constraints. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Parameters
curve: (timeMillis: Long) -> Offset

The function that describes the gesture. The argument passed to the function is the time in milliseconds since the start of the swipe, and the return value is the location of the pointer at that point in time.

durationMillis: Long = 200

The duration of the gesture

keyTimes: List<Long> = emptyList()

An optional list of timestamps in milliseconds at which a move event must be sampled

fun GestureScope.swipe(start: Offset, end: Offset, durationMillis: Long = 200): Unit

Performs the swipe gesture on the associated node. The motion events are linearly interpolated between start and end. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

durationMillis: Long = 200

The duration of the gesture

fun TouchInjectionScope.swipe(
    start: Offset,
    end: Offset,
    durationMillis: Long = 200
): Unit

Performs a swipe gesture on the associated node.

The motion events are linearly interpolated between start and end. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

durationMillis: Long = 200

The duration of the gesture

swipeDown

fun GestureScope.swipeDown(): Unit

Performs a swipe down gesture along the centerX of the associated node. The gesture starts slightly below the top of the node and ends at the bottom.

swipeDown

@ExperimentalTestApi
fun GestureScope.swipeDown(
    startY: Float = topFuzzed,
    endY: Float = bottom,
    durationMillis: Long = 200
): Unit

Performs a swipe down gesture along the centerX of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = topFuzzed

The y-coordinate of the start of the swipe. Must be less than or equal to the endY. By default slightly below the top of the node.

endY: Float = bottom

The y-coordinate of the end of the swipe. Must be greater than or equal to the startY. By default the bottom of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeDown

fun TouchInjectionScope.swipeDown(
    startY: Float = top,
    endY: Float = bottom,
    durationMillis: Long = 200
): Unit

Performs a swipe down gesture along x = [centerX] of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = top

The y-coordinate of the start of the swipe. Must be less than or equal to the endY. By default the top of the node.

endY: Float = bottom

The y-coordinate of the end of the swipe. Must be greater than or equal to the startY. By default the bottom of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeLeft

fun GestureScope.swipeLeft(): Unit

Performs a swipe left gesture along the centerY of the associated node. The gesture starts slightly left of the right side of the node and ends at the left side.

swipeLeft

@ExperimentalTestApi
fun GestureScope.swipeLeft(
    startX: Float = rightFuzzed,
    endX: Float = left,
    durationMillis: Long = 200
): Unit

Performs a swipe left gesture along the centerY of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = rightFuzzed

The x-coordinate of the start of the swipe. Must be greater than or equal to the endX. By default slightly left of the right of the node.

endX: Float = left

The x-coordinate of the end of the swipe. Must be less than or equal to the startX. By default the left of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeLeft

fun TouchInjectionScope.swipeLeft(
    startX: Float = right,
    endX: Float = left,
    durationMillis: Long = 200
): Unit

Performs a swipe left gesture along y = [centerY] of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = right

The x-coordinate of the start of the swipe. Must be greater than or equal to the endX. By default the right of the node.

endX: Float = left

The x-coordinate of the end of the swipe. Must be less than or equal to the startX. By default the left of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeRight

fun GestureScope.swipeRight(): Unit

Performs a swipe right gesture along the centerY of the associated node. The gesture starts slightly right of the left side of the node and ends at the right side.

swipeRight

@ExperimentalTestApi
fun GestureScope.swipeRight(
    startX: Float = leftFuzzed,
    endX: Float = right,
    durationMillis: Long = 200
): Unit

Performs a swipe right gesture along the centerY of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = leftFuzzed

The x-coordinate of the start of the swipe. Must be less than or equal to the endX. By default slightly right of the left of the node.

endX: Float = right

The x-coordinate of the end of the swipe. Must be greater than or equal to the startX. By default the right of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeRight

fun TouchInjectionScope.swipeRight(
    startX: Float = left,
    endX: Float = right,
    durationMillis: Long = 200
): Unit

Performs a swipe right gesture along y = [centerY] of the associated node, from startX till endX, taking durationMillis milliseconds.

Parameters
startX: Float = left

The x-coordinate of the start of the swipe. Must be less than or equal to the endX. By default the left of the node.

endX: Float = right

The x-coordinate of the end of the swipe. Must be greater than or equal to the startX. By default the right of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeUp

fun GestureScope.swipeUp(): Unit

Performs a swipe up gesture along the centerX of the associated node. The gesture starts slightly above the bottom of the node and ends at the top.

swipeUp

@ExperimentalTestApi
fun GestureScope.swipeUp(
    startY: Float = bottomFuzzed,
    endY: Float = top,
    durationMillis: Long = 200
): Unit

Performs a swipe up gesture along the centerX of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = bottomFuzzed

The y-coordinate of the start of the swipe. Must be greater than or equal to the endY. By default slightly above the bottom of the node.

endY: Float = top

The y-coordinate of the end of the swipe. Must be less than or equal to the startY. By default the top of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeUp

fun TouchInjectionScope.swipeUp(
    startY: Float = bottom,
    endY: Float = top,
    durationMillis: Long = 200
): Unit

Performs a swipe up gesture along x = [centerX] of the associated node, from startY till endY, taking durationMillis milliseconds.

Parameters
startY: Float = bottom

The y-coordinate of the start of the swipe. Must be greater than or equal to the endY. By default the bottom of the node.

endY: Float = top

The y-coordinate of the end of the swipe. Must be less than or equal to the startY. By default the top of the node.

durationMillis: Long = 200

The duration of the swipe. By default 200 milliseconds.

swipeWithVelocity

fun GestureScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long = 200
): Unit

Performs the swipe gesture on the associated node, such that the velocity when the gesture is finished is roughly equal to endVelocity. The MotionEvents are linearly interpolated between start and end. The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is 200 milliseconds.

Note that due to imprecisions, no guarantees can be made on the precision of the actual velocity at the end of the gesture, but generally it is within 0.1% of the desired velocity.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

endVelocity: Float

The velocity of the gesture at the moment it ends. Must be positive.

durationMillis: Long = 200

The duration of the gesture in milliseconds. Must be long enough that at least 3 input events are generated, which happens with a duration of 25ms or more.

swipeWithVelocity

fun TouchInjectionScope.swipeWithVelocity(
    start: Offset,
    end: Offset,
    endVelocity: Float,
    durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(start, end, endVelocity)
): Unit

Performs a swipe gesture on the associated node such that it ends with the given endVelocity.

The swipe will go through start at t=0 and through end at t=durationMillis. In between, the swipe will go monotonically from start and end, but not strictly. Due to imprecision, no guarantees can be made for the actual velocity at the end of the gesture, but generally it is within 0.1 of the desired velocity.

When a swipe cannot be created that results in the desired velocity (because the input is too restrictive), an exception will be thrown with suggestions to fix the input.

The coordinates are in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default duration is calculated such that a feasible swipe can be created that ends in the given velocity.

Parameters
start: Offset

The start position of the gesture, in the node's local coordinate system

end: Offset

The end position of the gesture, in the node's local coordinate system

endVelocity: Float

The velocity of the gesture at the moment it ends in px/second. Must be positive.

durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(start, end, endVelocity)

The duration of the gesture in milliseconds. Must be long enough that at least 3 input events are generated, which happens with a duration of 40ms or more. If omitted, a duration is calculated such that a valid swipe with velocity can be created.

Throws
kotlin.IllegalArgumentException

When no swipe can be generated that will result in the desired velocity. The error message will suggest changes to the input parameters such that a swipe will become feasible.

then

infix fun DeviceConfigurationOverride.then(other: DeviceConfigurationOverride): DeviceConfigurationOverride

Combines this override with the other override into a single override, by applying this override as the outer override first, then the other override as an inner override, and then the content.

import androidx.compose.material.Text
import androidx.compose.ui.test.DeviceConfigurationOverride
import androidx.compose.ui.test.FontScale
import androidx.compose.ui.test.FontWeightAdjustment
import androidx.compose.ui.test.then

DeviceConfigurationOverride(
    DeviceConfigurationOverride.FontScale(1.5f) then
        DeviceConfigurationOverride.FontWeightAdjustment(200)
) {
    Text(text = "text with increased scale and weight")
}

tripleClick

fun MouseInjectionScope.tripleClick(
    position: Offset = center,
    button: MouseButton = MouseButton.Primary
): Unit

Use button to triple-click on position, or on the current mouse position if position is unspecified. The position is in the node's local coordinate system, where (0, 0) is the top left corner of the node. The default button is the primary button.

Parameters
position: Offset = center

The position where to click, in the node's local coordinate system. If omitted, the center of the node will be used. If unspecified, clicks on the current mouse position.

button: MouseButton = MouseButton.Primary

The button to click with. Uses the primary by default.

tryPerformAccessibilityChecks

fun SemanticsNodeInteractionCollection.tryPerformAccessibilityChecks(): SemanticsNodeInteractionCollection

Tries to perform accessibility checks on the current screen. This will only actually do something if (1) accessibility checks are enabled and (2) accessibility checks are implemented for the platform on which the test runs.

Throws
kotlin.AssertionError

if accessibility problems are found

tryPerformAccessibilityChecks

fun SemanticsNodeInteraction.tryPerformAccessibilityChecks(): SemanticsNodeInteraction

Tries to perform accessibility checks on the current screen. This will only actually do something if (1) accessibility checks are enabled and (2) accessibility checks are implemented for the platform on which the test runs.

Throws
kotlin.AssertionError

if accessibility problems are found

up

fun GestureScope.up(pointerId: Int = 0): Unit

Sends an up event for the pointer with the given pointerId, or the default pointer if pointerId is omitted, on the associated node. If any pointers have been moved with movePointerTo or movePointerBy and no move event has been sent yet, a move event will be sent right before the up event.

Parameters
pointerId: Int = 0

The id of the pointer to lift up, as supplied in down

waitUntilAtLeastOneExists

@ExperimentalTestApi
fun ComposeUiTest.waitUntilAtLeastOneExists(
    matcher: SemanticsMatcher,
    timeoutMillis: Long
): Unit

Blocks until at least one node matches the given matcher.

Parameters
matcher: SemanticsMatcher

The matcher that will be used to filter nodes.

timeoutMillis: Long

The time after which this method throws an exception if no nodes match the given matcher. This observes wall clock time, not frame time.

Throws
androidx.compose.ui.test.ComposeTimeoutException

If no nodes match the given matcher after timeoutMillis (in wall clock time).

See also
waitUntil

waitUntilDoesNotExist

@ExperimentalTestApi
fun ComposeUiTest.waitUntilDoesNotExist(
    matcher: SemanticsMatcher,
    timeoutMillis: Long
): Unit

Blocks until no nodes match the given matcher.

Parameters
matcher: SemanticsMatcher

The matcher that will be used to filter nodes.

timeoutMillis: Long

The time after which this method throws an exception if any nodes match the given matcher. This observes wall clock time, not frame time.

Throws
androidx.compose.ui.test.ComposeTimeoutException

If any nodes match the given matcher after timeoutMillis (in wall clock time).

See also
waitUntil

waitUntilExactlyOneExists

@ExperimentalTestApi
fun ComposeUiTest.waitUntilExactlyOneExists(
    matcher: SemanticsMatcher,
    timeoutMillis: Long
): Unit

Blocks until exactly one node matches the given matcher.

Parameters
matcher: SemanticsMatcher

The matcher that will be used to filter nodes.

timeoutMillis: Long

The time after which this method throws an exception if exactly one node does not match the given matcher. This observes wall clock time, not frame time.

Throws
androidx.compose.ui.test.ComposeTimeoutException

If exactly one node does not match the given matcher after timeoutMillis (in wall clock time).

See also
waitUntil

waitUntilNodeCount

@ExperimentalTestApi
fun ComposeUiTest.waitUntilNodeCount(
    matcher: SemanticsMatcher,
    count: Int,
    timeoutMillis: Long
): Unit

Blocks until the number of nodes matching the given matcher is equal to the given count.

Parameters
matcher: SemanticsMatcher

The matcher that will be used to filter nodes.

count: Int

The number of nodes that are expected to be matched.

timeoutMillis: Long

The time after which this method throws an exception if the number of nodes that match the matcher is not count. This observes wall clock time, not frame time.

Throws
androidx.compose.ui.test.ComposeTimeoutException

If the number of nodes that match the matcher is not count after timeoutMillis (in wall clock time).

See also
waitUntil

withKeyDown

fun KeyInjectionScope.withKeyDown(key: Key, block: KeyInjectionScope.() -> Unit): Unit

Executes the keyboard sequence specified in the given block, whilst holding down the given key. This key must not be used within the block.

If the given key is already down, an IllegalStateException will be thrown.

Parameters
key: Key

The key to be held down during injection of the block.

block: KeyInjectionScope.() -> Unit

Sequence of KeyInjectionScope methods to be injected with the given key down.

withKeyToggled

fun KeyInjectionScope.withKeyToggled(key: Key, block: KeyInjectionScope.() -> Unit): Unit

Executes the keyboard sequence specified in the given block, in between presses to the given key. This key can also be used within the block, as long as it is not down at the end of the block.

If the given key is already down, an IllegalStateException will be thrown.

Parameters
key: Key

The key to be toggled around the injection of the block.

block: KeyInjectionScope.() -> Unit

Sequence of KeyInjectionScope methods to be injected with the given key down.

withKeysDown

fun KeyInjectionScope.withKeysDown(keys: List<Key>, block: KeyInjectionScope.() -> Unit): Unit

Executes the keyboard sequence specified in the given block, whilst holding down the each of the given keys. Each of the keys will be pressed down and released simultaneously. These keys must not be used within the block.

If any of the given keys are already down, an IllegalStateException will be thrown.

Parameters
keys: List<Key>

List of keys to be held down during injection of the block.

block: KeyInjectionScope.() -> Unit

Sequence of KeyInjectionScope methods to be injected with the given keys down.

withKeysToggled

fun KeyInjectionScope.withKeysToggled(keys: List<Key>, block: KeyInjectionScope.() -> Unit): Unit

Executes the keyboard sequence specified in the given block, in between presses to the given keys. Each of the keys will be toggled simultaneously.These keys can also be used within the block, as long as they are not down at the end of the block.

If any of the given keys are already down, an IllegalStateException will be thrown.

Parameters
keys: List<Key>

The keys to be toggled around the injection of the block.

block: KeyInjectionScope.() -> Unit

Sequence of KeyInjectionScope methods to be injected with the given keys down.

Extension properties

bottom

val GestureScope.bottomFloat

Returns the y-coordinate for the bottom of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that, unless height == 0, bottom != height. In particular, bottom == height - 1f, because pixels are 0-based. If height == 0, bottom == 0 too.

bottomCenter

val GestureScope.bottomCenterOffset

Returns the center of the bottom edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomCenter.y != height, see bottom.

bottomLeft

val GestureScope.bottomLeftOffset

Returns the bottom left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomLeft.y != height, see bottom.

bottomRight

val GestureScope.bottomRightOffset

Returns the bottom right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that bottomRight.x != width and bottomRight.y != height, see right and bottom.

center

val GestureScope.centerOffset

Returns the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerLeft

val GestureScope.centerLeftOffset

Returns the center of the left edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerRight

val GestureScope.centerRightOffset

Returns the center of the right edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that centerRight.x != width, see right.

centerX

val GestureScope.centerXFloat

Returns the x-coordinate for the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

centerY

val GestureScope.centerYFloat

Returns the y-coordinate for the center of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

frameDelayMillis

@ExperimentalTestApi
val TestMonotonicFrameClock.frameDelayMillisLong

The frame delay time for the TestMonotonicFrameClock in milliseconds.

height

val GestureScope.heightInt

Shorthand for size.height

isAltDown

val KeyInjectionScope.isAltDownBoolean

Verifies whether either of the alt keys are down.

Returns
Boolean

true if an alt key is currently down, false otherwise.

isCtrlDown

val KeyInjectionScope.isCtrlDownBoolean

Verifies whether either of the control keys are down.

Returns
Boolean

true if a control key is currently down, false otherwise.

isFnDown

val KeyInjectionScope.isFnDownBoolean

Verifies whether the function key is down.

Returns
Boolean

true if the function key is currently down, false otherwise.

isMetaDown

val KeyInjectionScope.isMetaDownBoolean

Verifies whether either of the meta keys are down.

Returns
Boolean

true if a meta key is currently down, false otherwise.

isShiftDown

val KeyInjectionScope.isShiftDownBoolean

Verifies whether either of the shift keys are down.

Returns
Boolean

true if a shift key is currently down, false otherwise.

left

val GestureScope.leftFloat

Returns the x-coordinate for the left edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

right

val GestureScope.rightFloat

Returns the x-coordinate for the right edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that, unless width == 0, right != width. In particular, right == width - 1f, because pixels are 0-based. If width == 0, right == 0 too.

top

val GestureScope.topFloat

Returns the y-coordinate for the bottom of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topCenter

val GestureScope.topCenterOffset

Returns the center of the top edge of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topLeft

val GestureScope.topLeftOffset

Returns the top left corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node.

topRight

val GestureScope.topRightOffset

Returns the top right corner of the node we're interacting with, in the node's local coordinate system, where (0, 0) is the top left corner of the node. Note that topRight.x != width, see right.

width

val GestureScope.widthInt

Shorthand for size.width