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.

Interfaces
AndroidComposeUiTest |
Variant of |
android
|
ComposeUiTest |
A test environment that allows you to test and control composables, either in isolation or in applications. |
Cmn
|
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
|
IdlingResourceOwner |
An interface for |
Cmn
|
IndirectPointerInjectionScope |
The receiver scope of the indirect pointer input injection lambda from |
Cmn
|
InjectionScope |
The receiver scope for input injection lambdas that are tied to a specific node, such as |
Cmn
|
KeyInjectionScope |
The receiver scope of the key input injection lambda from |
Cmn
|
MainTestClock |
The clock that drives |
Cmn
|
MouseInjectionScope |
The receiver scope of the mouse input injection lambda from |
Cmn
|
MultiModalInjectionScope |
The receiver scope of the multi-modal input injection lambda from |
Cmn
|
RotaryInjectionScope |
The receiver scope of rotary input injection lambda from |
Cmn
|
SemanticsNodeInteractionsProvider |
Provides the main entry point into testing. |
Cmn
|
TestFailureHandler |
Handles Compose UI test failures for custom diagnostics or artifact processing. |
Cmn
|
TouchInjectionScope |
The receiver scope of the touch input injection lambda from |
Cmn
|
TrackpadInjectionScope |
The receiver scope of the trackpad input injection lambda from |
Cmn
|
Classes
AndroidComposeUiTestEnvironment |
A test environment that can |
android
|
ComposeUiTestConfig |
Defines the configuration requirements for a Compose test environment. |
Cmn
android
|
FailureArtifact |
Represents a diagnostic artifact produced by the test failure pipeline when a Compose UI test fails. |
Cmn
|
FailureArtifact.Type |
Defines the category of a |
Cmn
|
FailureContext |
A contextual object provided to |
Cmn
|
GestureScope |
This class is deprecated. Replaced by TouchInjectionScope |
Cmn
|
MouseButton |
Representation of a mouse button with its associated |
Cmn
android
|
ScrollWheel |
Representation of a mouse scroll wheel axis. |
Cmn
|
SelectionResult |
Result of |
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 |
Cmn
|
TestFailurePolicy |
Configuration for the failure handling pipeline in Compose UI tests. |
Cmn
android
|
TestFailurePolicy.CaptureMode |
Represents a tri-state flag for failure artifact captures, allowing individual test configurations to explicitly override or fall back to suite-level runner arguments. |
Cmn
android
|
TestMonotonicFrameClock |
A |
android
|
TrackpadButton |
Representation of a trackpad button with its associated |
Cmn
android
|
Exceptions
ComposeTimeoutException |
Thrown in cases where Compose test can't satisfy a condition in a defined time limit. |
Cmn
|
Objects
AndroidComposeUiTestFlags |
This is a collection of flags which are used to guard against regressions in some of the "riskier" refactors or new feature support that is added to this module. |
android
|
ComposeUiTestFlags |
This is a collection of flags which are used to guard against regressions in some of the "riskier" refactors or new feature support that is added to this module. |
Cmn
|
DeviceConfigurationOverride.Companion |
Cmn
|
Annotations
ExperimentalTestApi |
Cmn
|
|
InternalTestApi |
Cmn
|
Composables
DeviceConfigurationOverride |
Applies |
Cmn
|
PlatformTextInputMethodTestOverride |
Installs a custom |
Cmn
|
Top-level functions summary
AndroidComposeUiTestEnvironment<A> |
@ExperimentalTestApiThis function is deprecated. Use `androidx.compose.ui.test.v2.AndroidComposeUiTestEnvironment` instead. |
android
|
Unit |
@ExperimentalTestApiThis function is deprecated. This API has been removed and its intended usage to run accessibility checks can now be done via `ComposeUiTest.enableAccessibilityChecks()` and `ComposeTestRule.enableAccessibilityChecks()` |
Cmn
|
SemanticsMatcher |
hasAnyAncestor(matcher: SemanticsMatcher)Returns whether the node has at least one ancestor that satisfies the given matcher. |
Cmn
|
SemanticsMatcher |
hasAnyChild(matcher: SemanticsMatcher)Returns whether the node has at least one child that satisfies the given matcher. |
Cmn
|
SemanticsMatcher |
hasAnyDescendant(matcher: SemanticsMatcher)Returns whether the node has at least one descendant that satisfies the given matcher. |
Cmn
|
SemanticsMatcher |
hasAnySibling(matcher: 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(Returns whether the node's content description contains the given |
Cmn
|
SemanticsMatcher |
hasContentDescriptionExactly(vararg values: String)Returns whether the node's content description contains exactly the given |
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 |
hasParent(matcher: SemanticsMatcher)Returns whether the node's parent satisfies the given matcher. |
Cmn
|
SemanticsMatcher |
Returns whether the node defines a semantics action to perform the |
Cmn
|
SemanticsMatcher |
hasProgressBarRangeInfo(rangeInfo: ProgressBarRangeInfo)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 |
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 |
hasStateDescription(value: String)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 |
Returns whether the node's text contains the given |
Cmn
|
SemanticsMatcher |
hasTextExactly(Returns whether the node's text contains exactly the given |
Cmn
|
SemanticsMatcher |
isDialog()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 hidden from accessibility. |
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 |
isOff()Returns whether the node is not toggled. |
Cmn
|
SemanticsMatcher |
isOn()Returns whether the node is toggled. |
Cmn
|
SemanticsMatcher |
isPopup()Returns whether the node is a popup. |
Cmn
|
SemanticsMatcher |
isRoot()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 |
This function is deprecated. This API has been removed and its intended usage to run accessibility checks can now be done via `ComposeUiTest.disableAccessibilityChecks()` and `ComposeTestRule.disableAccessibilityChecks()` |
Cmn
|
inline Unit |
@ExperimentalTestApiThis function is deprecated. Use `androidx.compose.ui.test.v2.runAndroidComposeUiTest` instead. |
android
|
Unit |
@ExperimentalTestApiThis function is deprecated. Use `androidx.compose.ui.test.v2.runAndroidComposeUiTest` instead. |
android
|
Unit |
@ExperimentalTestApiThis function is deprecated. Use `androidx.compose.ui.test.v2.runComposeUiTest` instead. |
Cmn
android
|
Unit |
@ExperimentalTestApiThis function is deprecated. Use `androidx.compose.ui.test.v2.runEmptyComposeUiTest` instead. |
android
|
Extension functions summary
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.DarkMode(isDarkMode: Boolean)A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.FontScale(fontScale: Float)A |
Cmn
android
|
DeviceConfigurationOverride |
@RequiresApi(value = 31)A |
android
|
DeviceConfigurationOverride |
A |
Cmn
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.Keyboard(A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.LayoutDirection(A |
Cmn
android
|
DeviceConfigurationOverride |
A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.Navigation(A |
android
|
DeviceConfigurationOverride |
@RequiresApi(value = 23)A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.Touchscreen(A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.UiMode(uiModeType: Int)A |
android
|
DeviceConfigurationOverride |
DeviceConfigurationOverride.Companion.WindowInsets(A |
android
|
DeviceConfigurationOverride |
A |
Cmn
android
|
Unit |
@ExperimentalTestApiThis function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
MouseInjectionScope.animateMoveAlong(Move the mouse along the given |
Cmn
|
Unit |
TrackpadInjectionScope.animateMoveAlong(Move the trackpad along the given |
Cmn
|
Unit |
MouseInjectionScope.animateMoveBy(delta: Offset, durationMillis: Long)Move the mouse from the |
Cmn
|
Unit |
TrackpadInjectionScope.animateMoveBy(Move the trackpad from the |
Cmn
|
Unit |
MouseInjectionScope.animateMoveTo(Move the mouse from the |
Cmn
|
Unit |
TrackpadInjectionScope.animateMoveTo(Move the trackpad from the |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assert(Asserts that the provided |
Cmn
|
SemanticsNodeInteractionCollection |
Asserts that all the nodes in this collection satisfy the given |
Cmn
|
SemanticsNodeInteractionCollection |
Asserts that this collection contains at least one element that satisfies the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertContentDescriptionContains(Asserts that the node's list of content descriptions contains the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertContentDescriptionEquals(Asserts that the node's list of content descriptions contains exactly the given |
Cmn
|
SemanticsNodeInteractionCollection |
SemanticsNodeInteractionCollection.assertCountEquals(Asserts that this collection of nodes is equal to the given |
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 |
SemanticsNodeInteraction.assertHeightIsAtLeast(expectedMinHeight: Dp)Asserts that the layout of this node has height that is greater than or equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertHeightIsEqualTo(Asserts that the layout of this node has height equal to |
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 |
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 |
SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(Asserts that the layout of this node has the left position in the root composable that is equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertPositionInRootIsEqualTo(Asserts that the layout of this node has position in the root composable that is equal to the |
Cmn
|
SemanticsNodeInteraction |
Asserts the node's range info equals the given value. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTextContains(Asserts that the node's list of text values contains the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTextEquals(Asserts that the node's list of text values contains exactly the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(Asserts that the layout of this node has the top position in the root composable that is equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTouchHeightIsEqualTo(Asserts that the touch bounds of this node has height equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTouchWidthIsEqualTo(Asserts that the touch bounds of this node has width equal to |
Cmn
|
SemanticsNodeInteraction |
Asserts the node's value equals the given value. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertWidthIsAtLeast(expectedMinWidth: Dp)Asserts that the layout of this node has width that is greater than or equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertWidthIsEqualTo(Asserts that the layout of this node has width equal to |
Cmn
|
Unit |
This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
ImageBitmap |
@RequiresApi(value = 26)Captures the underlying semantics node's surface into an |
android
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.click(position: Offset)Performs a click gesture (aka a tap) on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.click(position: Offset)Performs a click gesture (aka a tap) on the associated node. |
Cmn
|
Unit |
MouseInjectionScope.click(position: Offset, button: MouseButton)Use |
Cmn
|
Unit |
TrackpadInjectionScope.click(position: Offset, button: TrackpadButton)Use |
Cmn
|
Unit |
MouseInjectionScope.doubleClick(position: Offset, button: MouseButton)Use |
Cmn
|
Unit |
TrackpadInjectionScope.doubleClick(Use |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.doubleClick(Performs a double click gesture (aka a double tap) on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.doubleClick(position: Offset, delayMillis: Long)Performs a double click gesture (aka a double tap) on the associated node. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
MouseInjectionScope.dragAndDrop(Use |
Cmn
|
Unit |
TrackpadInjectionScope.dragAndDrop(Use |
Cmn
|
SemanticsNodeInteractionCollection |
Returns all the nodes matching the given |
Cmn
|
SemanticsNodeInteraction |
Expects to return exactly one node matching the given |
Cmn
|
Dp |
SemanticsNodeInteraction.getAlignmentLinePosition(Returns the position of an |
Cmn
|
DpRect |
Returns the bounds of the layout of this node as clipped to the root. |
Cmn
|
Rect? |
SemanticsNodeInteraction.getFirstLinkBounds(Returns the bounds of the first link matching the |
Cmn
|
DpRect |
Returns the bounds of the layout of this node. |
Cmn
|
SemanticsNodeInteraction |
This function is deprecated. This API has been removed and its intended usage to run accessibility checks can now be done via `SemanticsNodeInteraction.tryPerformAccessibilityChecks()` |
Cmn
|
SemanticsNodeInteractionCollection |
This function is deprecated. This API has been removed and its intended usage to run accessibility checks can now be done via `SemanticsNodeInteraction.tryPerformAccessibilityChecks()` |
Cmn
|
Boolean |
Returns true if the matched node is displayed on screen. |
Cmn
|
Boolean |
Capability query to determine if the current |
Cmn
|
Boolean |
Returns true if no matching node is displayed on screen. |
Cmn
|
Unit |
MouseInjectionScope.longClick(position: Offset, button: MouseButton)Use |
Cmn
|
Unit |
TrackpadInjectionScope.longClick(Use |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.longClick(Performs a long click gesture (aka a long press) on nodes in the focus path. |
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 |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.multiTouchSwipe(Performs a multitouch swipe gesture on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.multiTouchSwipe(Performs a multi touch swipe gesture on the associated node. |
Cmn
|
SemanticsNodeInteractionCollection |
SemanticsNodeInteractionsProvider.onAllNodesWithContentDescription(Finds all semantics nodes with the given label as content description. |
Cmn
|
SemanticsNodeInteractionCollection |
SemanticsNodeInteractionsProvider.onAllNodesWithTag(Finds all semantics nodes identified by the given tag. |
Cmn
|
SemanticsNodeInteractionCollection |
SemanticsNodeInteractionsProvider.onAllNodesWithText(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 |
SemanticsNodeInteraction.onChildAt(index: Int)Returns child of this node at the given index. |
Cmn
|
SemanticsNodeInteractionCollection |
Returns children of this node at the moment of invocation, it only captures nodes that are currently present in the semantic tree. |
Cmn
|
SemanticsNodeInteractionCollection |
Returns all the descendants of this node in Depth-First Search order. |
Cmn
|
SemanticsNodeInteraction |
Returns the first node in this collection. |
Cmn
|
SemanticsNodeInteraction |
Returns the last node in this collection. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteractionsProvider.onNodeWithContentDescription(Finds a semantics node with the given content description. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteractionsProvider.onNodeWithTag(Finds a semantics node identified by the given tag. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteractionsProvider.onNodeWithText(Finds a semantics node with the given text. |
Cmn
|
SemanticsNodeInteraction |
Returns a parent of this node. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteractionsProvider.onRoot(useUnmergedTree: Boolean)Finds the root semantics node of the Compose tree. |
Cmn
|
SemanticsNodeInteractionsProvider |
ComposeUiTest.onRootWithViewInteraction(interaction: ViewInteraction)Scopes Compose interactions to the |
android
|
SemanticsNodeInteraction |
Returns exactly one sibling of this node. |
Cmn
|
SemanticsNodeInteractionCollection |
Returns all siblings of this node. |
Cmn
|
Unit |
TrackpadInjectionScope.pan(offset: Offset)Sends a pan gesture with the given total |
Cmn
|
Unit |
TrackpadInjectionScope.pan(Sends a pan gesture with the offsets in the panning coordinate space following the given |
Cmn
|
Unit |
TrackpadInjectionScope.panWithVelocity(Performs a pan gesture on the associated node such that it ends with the given |
Cmn
|
Offset |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
SemanticsNodeInteraction |
Performs a click action on the element represented by the given semantics node. |
Cmn
|
SemanticsNodeInteraction |
@ExperimentalTestApiFinds the |
Cmn
|
SemanticsNodeInteraction |
@ExperimentalTestApiFinds the |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.performFirstLinkClick(For a first link matching the |
Cmn
|
SemanticsNodeInteraction |
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 |
SemanticsNodeInteraction.performKeyInput(block: KeyInjectionScope.() -> Unit)Executes the key input gesture specified in the given |
Cmn
|
Boolean |
SemanticsNodeInteraction.performKeyPress(keyEvent: KeyEvent)Send the specified |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.performMouseInput(block: MouseInjectionScope.() -> Unit)Executes the mouse gesture specified in the given |
Cmn
|
SemanticsNodeInteraction |
Executes the multi-modal gesture specified in the given |
Cmn
|
SemanticsNodeInteraction |
Executes the rotary input specified in the given |
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 |
Cmn
|
SemanticsNodeInteraction |
Scrolls a scrollable container with keyed items to the item with the given |
Cmn
|
SemanticsNodeInteraction |
Scrolls a scrollable container to the content that matches the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.performSemanticsAction(Provides support to call custom semantics actions on this node. |
Cmn
|
SemanticsNodeInteraction |
<T : () -> Boolean> SemanticsNodeInteraction.performSemanticsAction(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 |
SemanticsNodeInteraction.performTextInputSelection(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 |
SemanticsNodeInteraction.performTouchInput(block: TouchInjectionScope.() -> Unit)Executes the touch gesture specified in the given |
Cmn
|
SemanticsNodeInteraction |
Executes the trackpad gesture specified in the given |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.pinch(Performs a pinch gesture on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.pinch(Performs a pinch gesture on the associated node. |
Cmn
|
Unit |
KeyInjectionScope.pressKey(key: Key, pressDurationMillis: Long)Holds down the given |
Cmn
|
Unit |
SemanticsNodeInteraction.printToLog(tag: String, maxDepth: Int)Prints all the semantics nodes information into logs (as debug level). |
Cmn
|
Unit |
SemanticsNodeInteractionCollection.printToLog(Prints all the semantics nodes information into logs (as debug level). |
Cmn
|
String |
SemanticsNodeInteraction.printToString(maxDepth: Int)Prints all the semantics nodes information it holds into string. |
Cmn
|
String |
SemanticsNodeInteractionCollection.printToString(maxDepth: Int)Prints all the semantics nodes information it holds into string. |
Cmn
|
Boolean |
ComposeUiTest.registerIdlingResource(idlingResource: IdlingResource)Attempts to register an |
Cmn
|
SemanticsNodeInteraction |
Requests the focus system to give focus to this node by invoking the |
Cmn
|
Unit |
MouseInjectionScope.rightClick(position: Offset)Secondary-click on |
Cmn
|
Unit |
TrackpadInjectionScope.rightClick(position: Offset)Secondary-click on |
Cmn
|
Unit |
TrackpadInjectionScope.scale(Sends a scale event with the given |
Cmn
|
Unit |
SemanticsNodeInteractionsProvider.sendIndirectPointerInput(Sends an indirect pointer gesture globally, targeting the currently focused Compose UI (from root to the focused node). |
Cmn
|
Unit |
MouseInjectionScope.smoothScroll(Rotate the mouse's |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipe(Performs a swipe gesture on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.swipe(Performs a swipe gesture on the associated node. |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipe(Performs a swipe gesture on nodes in the focus path. |
Cmn
|
Unit |
TouchInjectionScope.swipe(Performs a swipe gesture on the associated node. |
Cmn
|
Unit |
This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
@ExperimentalTestApiThis function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipeDown(Performs a swipe down gesture on nodes in the focus path along |
Cmn
|
Unit |
TouchInjectionScope.swipeDown(Performs a swipe down gesture along |
Cmn
|
Unit |
This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
@ExperimentalTestApiThis function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipeLeft(Performs a swipe left gesture on nodes in the focus path along |
Cmn
|
Unit |
TouchInjectionScope.swipeLeft(Performs a swipe left gesture along |
Cmn
|
Unit |
This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
@ExperimentalTestApiThis function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipeRight(Performs a swipe right gesture on nodes in the focus path along |
Cmn
|
Unit |
TouchInjectionScope.swipeRight(Performs a swipe right gesture along |
Cmn
|
Unit |
This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
@ExperimentalTestApiThis function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipeUp(Performs a swipe up gesture on nodes in the focus path along |
Cmn
|
Unit |
TouchInjectionScope.swipeUp(Performs a swipe up gesture along |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
IndirectPointerInjectionScope.swipeWithVelocity(Performs a swipe gesture on nodes in the focus path such that it ends with the given |
Cmn
|
Unit |
TouchInjectionScope.swipeWithVelocity(Performs a swipe gesture on the associated node such that it ends with the given |
Cmn
|
infix DeviceConfigurationOverride |
Combines this override with the |
Cmn
|
Unit |
MouseInjectionScope.tripleClick(position: Offset, button: MouseButton)Use |
Cmn
|
Unit |
TrackpadInjectionScope.tripleClick(Use |
Cmn
|
SemanticsNodeInteractionCollection |
Tries to perform accessibility checks on the current screen. |
Cmn
|
SemanticsNodeInteraction |
Tries to perform accessibility checks on the current screen. |
Cmn
android
|
Boolean |
ComposeUiTest.unregisterIdlingResource(idlingResource: IdlingResource)Attempts to unregister an |
Cmn
|
Unit |
GestureScope.This function is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Unit |
ComposeUiTest.waitUntilAtLeastOneExists(Blocks until at least one node matches the given |
Cmn
|
Unit |
ComposeUiTest.waitUntilDoesNotExist(Blocks until no nodes match the given |
Cmn
|
Unit |
ComposeUiTest.waitUntilExactlyOneExists(Blocks until exactly one node matches the given |
Cmn
|
Unit |
ComposeUiTest.waitUntilNodeCount(Blocks until the number of nodes matching the given |
Cmn
|
Unit |
KeyInjectionScope.withKeyDown(key: Key, block: KeyInjectionScope.() -> Unit)Executes the keyboard sequence specified in the given |
Cmn
|
Unit |
KeyInjectionScope.withKeyToggled(key: Key, block: KeyInjectionScope.() -> Unit)Executes the keyboard sequence specified in the given |
Cmn
|
Unit |
KeyInjectionScope.withKeysDown(keys: List<Key>, block: KeyInjectionScope.() -> Unit)Executes the keyboard sequence specified in the given |
Cmn
|
Unit |
KeyInjectionScope.withKeysToggled(keys: List<Key>, block: KeyInjectionScope.() -> Unit)Executes the keyboard sequence specified in the given |
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 |
android
|
Int |
This property is deprecated. Replaced by TouchInjectionScope. |
Cmn
|
Float |
The y-coordinate for the bottom of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The center of the bottom edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The bottom left corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The bottom right corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The center of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The center of the left edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The center of the right edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Float |
The x-coordinate for the center of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Float |
The y-coordinate for the center of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Int |
The height of the external indirect pointer input device that provide the height boundary for indirect input. |
Cmn
|
Float |
The x-coordinate for the left edge of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Float |
The x-coordinate for the right edge of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Float |
The y-coordinate for the top of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The center of the top edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The top left corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Offset |
The top right corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. |
Cmn
|
Int |
The width of the external indirect pointer input device that provide the width boundary for indirect input. |
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
fun <A : ComponentActivity>AndroidComposeUiTestEnvironment(
effectContext: CoroutineContext = EmptyCoroutineContext,
runTestContext: CoroutineContext = EmptyCoroutineContext,
testTimeout: Duration = 60.seconds,
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 |
runTestContext: CoroutineContext = EmptyCoroutineContext |
The |
testTimeout: Duration = 60.seconds |
The |
activityProvider: () -> A? |
A lambda that should return the current Activity instance of type |
addGlobalAssertion
@ExperimentalTestApi
funaddGlobalAssertion(
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 |
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. |
| See also | |
|---|---|
ContentDescription |
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) |
| See also | |
|---|---|
ContentDescription |
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.
| See also | |
|---|---|
InsertTextAtCursor |
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. |
| See also | |
|---|---|
ProgressBarRangeInfo |
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 and SemanticsProperties.InputText.
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,
includeInputText: Boolean = false
): SemanticsMatcher
Returns whether the node's text contains exactly the given textValues and nothing else.
By default, this searches in SemanticsProperties.Text and SemanticsProperties.EditableText. To also evaluate SemanticsProperties.InputText (which holds the raw user input of fields like passwords, bypassing visual transformations), set includeInputText to true.
Note that in the 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. Defaults to true. |
includeInputText: Boolean = false |
Whether to also assert against the un-transformed input text. Defaults to false. |
| See also | |
|---|---|
Text |
|
EditableText |
|
InputText |
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 |
isFocusable
fun isFocusable(): SemanticsMatcher
Return whether the node is able to receive focus
| See also | |
|---|---|
Focused |
isHeading
fun isHeading(): SemanticsMatcher
Returns whether the node is marked as an accessibility header.
| See also | |
|---|---|
Heading |
isHiddenFromAccessibility
fun isHiddenFromAccessibility(): SemanticsMatcher
Returns whether the node is hidden from accessibility.
This only checks if the node itself is hidden from accessibility. To check if it is in a hidden subtree, use hasAnyAncestor(isHiddenFromAccessibility()).
| See also | |
|---|---|
HideFromAccessibility |
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 |
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
funremoveGlobalAssertion(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 |
runAndroidComposeUiTest
@ExperimentalTestApi
inline fun <A : ComponentActivity>runAndroidComposeUiTest(
effectContext: CoroutineContext = EmptyCoroutineContext,
runTestContext: CoroutineContext = EmptyCoroutineContext,
testTimeout: Duration = 60.seconds,
noinline block: suspend 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.
Avoid using androidx.compose.ui.test.junit4.ComposeTestRule (e.g., createComposeRule) inside runAndroidComposeUiTest or any of their respective variants. Since these APIs independently manage the test environment, mixing them may lead to unexpected behavior.
| Parameters | |
|---|---|
<A : ComponentActivity> |
The Activity type to be launched, which typically (but not necessarily) hosts the Compose content |
effectContext: CoroutineContext = EmptyCoroutineContext |
The |
runTestContext: CoroutineContext = EmptyCoroutineContext |
The |
testTimeout: Duration = 60.seconds |
The |
noinline block: suspend AndroidComposeUiTest<A>.() -> Unit |
The test function. |
runAndroidComposeUiTest
@ExperimentalTestApi
fun <A : ComponentActivity>runAndroidComposeUiTest(
activityClass: Class<A>,
effectContext: CoroutineContext = EmptyCoroutineContext,
runTestContext: CoroutineContext = EmptyCoroutineContext,
testTimeout: Duration = 60.seconds,
block: suspend 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.
Avoid using androidx.compose.ui.test.junit4.ComposeTestRule (e.g., createComposeRule) inside runAndroidComposeUiTest or any of their respective variants. Since these APIs independently manage the test environment, mixing them may lead to unexpected behavior.
| Parameters | |
|---|---|
<A : ComponentActivity> |
The Activity type to be launched, which typically (but not necessarily) hosts the Compose content |
activityClass: Class<A> |
The |
effectContext: CoroutineContext = EmptyCoroutineContext |
The |
runTestContext: CoroutineContext = EmptyCoroutineContext |
The |
testTimeout: Duration = 60.seconds |
The |
block: suspend AndroidComposeUiTest<A>.() -> Unit |
The test function. |
runComposeUiTest
@ExperimentalTestApi
funrunComposeUiTest(
effectContext: CoroutineContext = EmptyCoroutineContext,
runTestContext: CoroutineContext = EmptyCoroutineContext,
testTimeout: Duration = 60.seconds,
block: suspend 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.
This function follows the semantics of kotlinx.coroutines.test.runTest. On JVM and Native it behaves similarly to runBlocking. On web targets it returns a TestResult backed by a Promise.
For multiplatform tests, make the test return TestResult and immediately return the result of runComposeUiTest. Keep assertions inside the block, and do not execute code after this call.
Example:
@Test
fun myTest(): TestResult = runComposeUiTest {
setContent { /* content under test */}
}
Keeping a reference to the ComposeUiTest outside of this function is an error.
See also:
import androidx.compose.foundation.layout.Column import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.mutableIntStateOf import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.test.assert import androidx.compose.ui.test.hasText import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.compose.ui.test.v2.runComposeUiTest runComposeUiTest { var counter by mutableIntStateOf(1) setContent { Column { Text(text = "Count: $counter", modifier = Modifier.testTag("text_tag")) Button(onClick = { counter++ }, modifier = Modifier.testTag("button_tag")) { Text("Click Me!") } } } onNodeWithTag("button_tag").performClick() onNodeWithTag("text_tag").assert(hasText("Count: 2")) }
| Parameters | |
|---|---|
effectContext: CoroutineContext = EmptyCoroutineContext |
The |
runTestContext: CoroutineContext = EmptyCoroutineContext |
The |
testTimeout: Duration = 60.seconds |
The |
block: suspend ComposeUiTest.() -> Unit |
The test function. |
runEmptyComposeUiTest
@ExperimentalTestApi
funrunEmptyComposeUiTest(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.
Avoid using androidx.compose.ui.test.junit4.ComposeTestRule (e.g., createComposeRule) inside runEmptyComposeUiTest or any of their respective variants. Since these APIs independently manage the test environment, mixing them may lead to unexpected behavior.
Extension functions
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
isDarkMode: Boolean |
if |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
fontScale: Float |
the font scale to use for the content under test. |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
fontWeightAdjustment: Int |
the font weight adjustment to use to render the content under test. |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
size: DpSize |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.Keyboard
fun DeviceConfigurationOverride.Companion.Keyboard(
keyboardType: Int,
isHardKeyboardHidden: Boolean = false,
isHidden: Boolean = false
): DeviceConfigurationOverride
A DeviceConfigurationOverride that overrides the current keyboard type.
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.Keyboard DeviceConfigurationOverride( DeviceConfigurationOverride.Keyboard(Configuration.KEYBOARD_QWERTY) ) { LocalConfiguration.current.keyboard // will be Configuration.KEYBOARD_QWERTY }
| Parameters | |
|---|---|
keyboardType: Int |
the keyboard type to render content under test in. This should be one of the |
isHardKeyboardHidden: Boolean = false |
if |
isHidden: Boolean = false |
if |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
| See also | |
|---|---|
keyboard |
|
keyboardHidden |
|
hardKeyboardHidden |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
layoutDirection: LayoutDirection |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
locales: LocaleList |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.Navigation
fun DeviceConfigurationOverride.Companion.Navigation(
navigationType: Int,
isHidden: Boolean = false
): DeviceConfigurationOverride
A DeviceConfigurationOverride that overrides the current navigation type and whether it is hidden.
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.Navigation DeviceConfigurationOverride( DeviceConfigurationOverride.Navigation( navigationType = Configuration.NAVIGATION_DPAD, isHidden = false, ) ) { LocalConfiguration.current.navigation // will be Configuration.NAVIGATION_DPAD LocalConfiguration.current.navigationHidden // will be Configuration.NAVIGATIONHIDDEN_NO }
| Parameters | |
|---|---|
navigationType: Int |
the navigation type to render the content under test in. This should be one of the |
isHidden: Boolean = false |
if |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
| See also | |
|---|---|
navigation |
|
navigationHidden |
DeviceConfigurationOverride.Companion.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 }
| Parameters | |
|---|---|
isScreenRound: Boolean |
if |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.Touchscreen
fun DeviceConfigurationOverride.Companion.Touchscreen(
isTouchScreen: Boolean
): DeviceConfigurationOverride
A DeviceConfigurationOverride that overrides the current touchscreen type.
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.Touchscreen DeviceConfigurationOverride(DeviceConfigurationOverride.Touchscreen(false)) { LocalConfiguration.current.touchscreen // will be Configuration.TOUCHSCREEN_NOTOUCH }
DeviceConfigurationOverride.Companion.UiMode
fun DeviceConfigurationOverride.Companion.UiMode(uiModeType: Int): DeviceConfigurationOverride
A DeviceConfigurationOverride that overrides the current ui mode type.
import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.UiMode DeviceConfigurationOverride( DeviceConfigurationOverride.UiMode(Configuration.UI_MODE_TYPE_CAR) ) { // will be Configuration.UI_MODE_TYPE_CAR LocalConfiguration.current.uiMode and Configuration.UI_MODE_TYPE_MASK }
| Parameters | |
|---|---|
uiModeType: Int |
the uiMode type to render the content under test in. This should be one of the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.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) ) }
| Parameters | |
|---|---|
windowInsets: WindowInsetsCompat |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
DeviceConfigurationOverride.Companion.WindowSize
fun DeviceConfigurationOverride.Companion.WindowSize(size: DpSize): DeviceConfigurationOverride
A DeviceConfigurationOverride that overrides the window size for the contained content.
Like ForcedSize, 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).
Unlike ForcedSize, this override will override LocalWindowInfo and LocalConfiguration on Android to reflect the requested size.
import androidx.compose.ui.test.DeviceConfigurationOverride import androidx.compose.ui.test.WindowSize import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp DeviceConfigurationOverride(DeviceConfigurationOverride.WindowSize(DpSize(1280.dp, 800.dp))) { MyScreen() // will be rendered with an apparent window size of 1280dp by 800dp without // clipping }
| Parameters | |
|---|---|
size: DpSize |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a |
GestureScope.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.
MouseInjectionScope.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. |
TrackpadInjectionScope.animateMoveAlong
fun TrackpadInjectionScope.animateMoveAlong(
curve: (timeMillis: Long) -> Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad along the given curve, sending a stream of move events to get an animated path of durationMillis milliseconds. The trackpad 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 trackpad 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.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // 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 trackpad 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 trackpad at that point in time |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default, 300 milliseconds. |
MouseInjectionScope.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. |
TrackpadInjectionScope.animateMoveBy
fun TrackpadInjectionScope.animateMoveBy(
delta: Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad 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 trackpad to, relative to the current position of the trackpad. For example, `delta = Offset(100.px, -100.px) will move the trackpad 100 pixels to the right and 100 pixels upwards. |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default, 300 milliseconds. |
MouseInjectionScope.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 advanceEventTime() moveTo(topRight) animateMoveTo(bottomLeft) }
TrackpadInjectionScope.animateMoveTo
fun TrackpadInjectionScope.animateMoveTo(
position: Offset,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Move the trackpad from the current position to the given position, sending a stream of move events to get an animated path of durationMillis milliseconds. Move the trackpad 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 trackpad along a line:
import androidx.compose.ui.test.animateMoveTo import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // 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 advanceEventTime() moveTo(topRight) animateMoveTo(bottomLeft) }
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
if the matcher does not match or the node can no longer be found. |
SemanticsNodeInteractionCollection.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 | |
|---|---|
AssertionError |
if the collection contains at least one element that does not satisfy the given matcher. |
SemanticsNodeInteractionCollection.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 | |
|---|---|
AssertionError |
if not at least one matching node was node. |
SemanticsNodeInteraction.assertContentDescriptionContains
fun SemanticsNodeInteraction.assertContentDescriptionContains(
value: String,
substring: Boolean = false,
ignoreCase: Boolean = false
): SemanticsNodeInteraction
Asserts that the node's list of content descriptions contains the given value.
The ContentDescription property is represented as a list of strings. In the merged semantics tree (the default in Compose testing), this list often contains multiple descriptions merged from child nodes. This function evaluates whether any individual item in that list matches the provided value.
By default, this requires an exact string match with at least one complete item in the list.
Typically, accessibility tooling will decide based on its heuristics which descriptions to announce.
Throws AssertionError if the node's value list does not contain value, or if the node has no value.
import androidx.compose.foundation.layout.Row import androidx.compose.material3.Icon import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.compose.ui.test.assertContentDescriptionContains import androidx.compose.ui.test.onNodeWithTag composeTestRule.setContent { // Explicitly merging descendants to demonstrate list semantics Row(Modifier.semantics(mergeDescendants = true) { testTag = "iconRow" }) { Icon(ColorPainter(Color.Red), contentDescription = "Navigate Up") Icon(ColorPainter(Color.Yellow), contentDescription = "Go Home") } } // The merged content description list is: ["Navigate Up", "Go Home"] // "Navigate Up" is an exact match for one of the items in the list. composeTestRule.onNodeWithTag("iconRow").assertContentDescriptionContains("Navigate Up") // "Navigate" is a substring of an item in the list, and we explicitly enable substring // matching. composeTestRule .onNodeWithTag("iconRow") .assertContentDescriptionContains("Navigate", substring = true)
| Parameters | |
|---|---|
value: String |
Value to match against 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. Defaults to false. |
ignoreCase: Boolean = false |
Whether case should be ignored. Defaults to false. |
| See also | |
|---|---|
ContentDescription |
SemanticsNodeInteraction.assertContentDescriptionEquals
fun SemanticsNodeInteraction.assertContentDescriptionEquals(
vararg values: String
): SemanticsNodeInteraction
Asserts that the node's list of content descriptions contains exactly the given values and nothing else.
The ContentDescription property is represented as a list of strings. In the merged semantics tree (the default in Compose testing), this list often contains multiple descriptions merged from child nodes. This function evaluates the entire list.
The assertion will only pass if the node's list contains all the provided values, and contains no additional items. Note that the order of the elements does not matter.
Typically, accessibility tooling will decide based on its heuristics which descriptions 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.
import androidx.compose.foundation.layout.Row import androidx.compose.material3.Icon import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.painter.ColorPainter import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.compose.ui.test.assertContentDescriptionEquals import androidx.compose.ui.test.onNodeWithTag composeTestRule.setContent { // Explicitly merging descendants to demonstrate list semantics Row(Modifier.semantics(mergeDescendants = true) { testTag = "iconRow" }) { Icon(ColorPainter(Color.Red), contentDescription = "Navigate Up") Icon(ColorPainter(Color.Yellow), contentDescription = "Go Home") } } // The merged content description list is: ["Navigate Up", "Go Home"] // We provide all items exactly as they appear in the merged list. // Order does not matter. composeTestRule .onNodeWithTag("iconRow") .assertContentDescriptionEquals("Go Home", "Navigate Up")
| Parameters | |
|---|---|
vararg values: String |
List of values to match (the order does not matter). |
| See also | |
|---|---|
ContentDescription |
SemanticsNodeInteractionCollection.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 | |
|---|---|
AssertionError |
if the size is not equal to |
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
if comparison fails. |
SemanticsNodeInteraction.assertHeightIsEqualTo
fun SemanticsNodeInteraction.assertHeightIsEqualTo(
expectedHeight: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the layout of this node has height equal to expectedHeight within the given tolerance.
| Parameters | |
|---|---|
expectedHeight: Dp |
The expected height of the layout. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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.
Dp.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 | |
|---|---|
AssertionError |
if comparison fails. |
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.assertIsNotDisplayed
fun SemanticsNodeInteraction.assertIsNotDisplayed(): SemanticsNodeInteraction
Asserts that the current semantics node is not displayed on screen.
Throws AssertionError if the node is displayed.
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.assertIsNotSelected
fun SemanticsNodeInteraction.assertIsNotSelected(): SemanticsNodeInteraction
Asserts that the current semantics node is not selected.
Throws AssertionError if the node is selected or not selectable.
SemanticsNodeInteraction.assertIsOff
fun SemanticsNodeInteraction.assertIsOff(): SemanticsNodeInteraction
Asserts that the current semantics node is unchecked.
Throws AssertionError if the node is checked, indeterminate, or not toggleable.
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.assertIsSelectable
fun SemanticsNodeInteraction.assertIsSelectable(): SemanticsNodeInteraction
Asserts that the current semantics node is selectable.
Throws AssertionError if the node is not selectable.
SemanticsNodeInteraction.assertIsSelected
fun SemanticsNodeInteraction.assertIsSelected(): SemanticsNodeInteraction
Asserts that the current semantics node is selected.
Throws AssertionError if the node is unselected or not selectable.
SemanticsNodeInteraction.assertIsToggleable
fun SemanticsNodeInteraction.assertIsToggleable(): SemanticsNodeInteraction
Asserts that the current semantics node is toggleable.
Throws AssertionError if the node is not toggleable.
SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(
expectedLeft: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the layout of this node has the left position in the root composable that is equal to expectedLeft within the given tolerance.
| Parameters | |
|---|---|
expectedLeft: Dp |
The left (x) position to assert. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.assertPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
expectedLeft: Dp,
expectedTop: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the layout of this node has position in the root composable that is equal to the expectedLeft and expectedTop within the given tolerance.
| Parameters | |
|---|---|
expectedLeft: Dp |
The left (x) position to assert. |
expectedTop: Dp |
The top (y) position to assert. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.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
SemanticsNodeInteraction.assertTextContains
fun SemanticsNodeInteraction.assertTextContains(
value: String,
substring: Boolean = false,
ignoreCase: Boolean = false
): SemanticsNodeInteraction
Asserts that the node's list of text values contains the given value.
This will also search in SemanticsProperties.EditableText and SemanticsProperties.InputText.
The Text property is represented as a list of strings. In the merged semantics tree (the default in Compose testing), this list often contains multiple text items merged from child nodes. This function evaluates whether any individual item in that list matches the provided value.
By default, this requires an exact string match with at least one complete item in the list.
Typically, accessibility tooling will decide based on its heuristics which ones to use.
Throws AssertionError if the node's value list does not contain value, or if the node has no value.
import androidx.compose.foundation.layout.Row import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.compose.ui.semantics.text import androidx.compose.ui.test.assertTextContains import androidx.compose.ui.test.onNodeWithTag composeTestRule.setContent { // Explicitly merging descendants to demonstrate list semantics Row(Modifier.semantics(mergeDescendants = true) { testTag = "textRow" }) { Text("Hello") Text("World") } } // The merged text list is: ["Hello", "World"] // "Hello" is an exact match for one of the items in the list. composeTestRule.onNodeWithTag("textRow").assertTextContains("Hello") // "Hel" is a substring of an item in the list, and we explicitly enable substring matching. composeTestRule.onNodeWithTag("textRow").assertTextContains("Hel", substring = true)
| Parameters | |
|---|---|
value: String |
Value to match against 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. Defaults to false. |
ignoreCase: Boolean = false |
Whether case should be ignored. Defaults to false. |
| See also | |
|---|---|
Text |
SemanticsNodeInteraction.assertTextEquals
fun SemanticsNodeInteraction.assertTextEquals(
vararg values: String,
includeEditableText: Boolean = true,
includeInputText: Boolean = false
): SemanticsNodeInteraction
Asserts that the node's list of text values contains exactly the given values and nothing else.
By default, this searches in SemanticsProperties.Text and SemanticsProperties.EditableText. To also evaluate SemanticsProperties.InputText (which holds the raw user input of fields like passwords, bypassing visual transformations), set includeInputText to true.
The Text property is represented as a list of strings. In the merged semantics tree (the default in Compose testing), this list often contains multiple text items merged from child nodes. This function evaluates the entire list.
The assertion will only pass if the node's list contains all the provided values, and contains no additional items. Note that the order of the elements does not matter.
Typically, 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.
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.material3.Text import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.inputText import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTag import androidx.compose.ui.semantics.text import androidx.compose.ui.test.assertTextEquals import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.text.AnnotatedString composeTestRule.setContent { // Explicitly merging descendants to demonstrate list semantics Row(Modifier.semantics(mergeDescendants = true) { testTag = "textRow" }) { Text("First Name:") Text("Compose") } // Simulating a password field where the visual text is masked, // but the raw user input is stored in InputText. Box( Modifier.semantics { text = AnnotatedString("(000) 123-4567") inputText = AnnotatedString("0001234567") testTag = "phoneField" } ) } // The merged text list is: ["First Name:", "Compose"] // We provide all items exactly as they appear in the merged list. composeTestRule.onNodeWithTag("textRow").assertTextEquals("Compose", "First Name:") // By default, assertTextEquals evaluates Text (and EditableText), // but ignores InputText. The evaluated list is simply ["(000) 123-4567"]. composeTestRule.onNodeWithTag("phoneField").assertTextEquals("(000) 123-4567") // We explicitly opt in to evaluating the InputText property. composeTestRule .onNodeWithTag("phoneField") .assertTextEquals("0001234567", "(000) 123-4567", includeInputText = true)
| 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. Defaults to true. |
includeInputText: Boolean = false |
Whether to also assert against the un-transformed input text. Defaults to false. |
| See also | |
|---|---|
Text |
|
EditableText |
|
InputText |
SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(
expectedTop: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the layout of this node has the top position in the root composable that is equal to expectedTop within the given tolerance.
| Parameters | |
|---|---|
expectedTop: Dp |
The top (y) position to assert. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.assertTouchHeightIsEqualTo
fun SemanticsNodeInteraction.assertTouchHeightIsEqualTo(
expectedHeight: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the touch bounds of this node has height equal to expectedHeight within the given tolerance.
| Parameters | |
|---|---|
expectedHeight: Dp |
The expected touch height of the layout. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.assertTouchWidthIsEqualTo
fun SemanticsNodeInteraction.assertTouchWidthIsEqualTo(
expectedWidth: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the touch bounds of this node has width equal to expectedWidth within the given tolerance.
| Parameters | |
|---|---|
expectedWidth: Dp |
The expected touch width of the layout. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| See also | |
|---|---|
ComposeUiTestConfig |
SemanticsNodeInteraction.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
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
if comparison fails. |
SemanticsNodeInteraction.assertWidthIsEqualTo
fun SemanticsNodeInteraction.assertWidthIsEqualTo(
expectedWidth: Dp,
tolerance: Dp = Dp.Unspecified
): SemanticsNodeInteraction
Asserts that the layout of this node has width equal to expectedWidth within the given tolerance.
| Parameters | |
|---|---|
expectedWidth: Dp |
The expected width of the layout. |
tolerance: Dp = Dp.Unspecified |
The tolerance within which the values should be treated as equal. Defaults to the tolerance configured in |
| Throws | |
|---|---|
AssertionError |
if comparison fails. |
| See also | |
|---|---|
ComposeUiTestConfig |
GestureScope.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.
SemanticsNodeInteraction.captureToImage
@RequiresApi(value = 26)
fun SemanticsNodeInteraction.captureToImage(timeoutMillis: Long): ImageBitmap
Captures the underlying semantics node's surface into an ImageBitmap.
This can be used to capture nodes in a normal composable, as well as across multiple roots. Popups and Dialogs (if API >= 28) are specific cases of this, where they can be captured together with their anchor.
For example, selecting the root node (via onRoot()) when a popup or dialog is present will detect multiple roots. In this scenario, the resulting image is cropped to the combined bounding box of all nodes across the different roots. If a Dialog is present among the roots, the image is cropped to the window's visible display frame.
| Parameters | |
|---|---|
timeoutMillis: Long |
The maximum time (in ms) to wait for the drawing to complete. Default is 2000 ms. |
| Throws | |
|---|---|
IllegalArgumentException |
if an attempt is made to capture a bitmap of a dialog before API 28. |
ComposeTimeoutException |
if drawing does not complete within |
GestureScope.click
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. |
IndirectPointerInjectionScope.click
fun IndirectPointerInjectionScope.click(position: Offset = inputDeviceCenter): Unit
Performs a click gesture (aka a tap) on nodes in the focus path.
The click is done at the given position within the indirect pointer input device's bounds, or the inputDeviceCenter if the position is omitted. The position is NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize).
| Parameters | |
|---|---|
position: Offset = inputDeviceCenter |
The position where to click, in the indirect pointer input device's coordinate system ( |
TouchInjectionScope.click
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.
MouseInjectionScope.click
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 |
button: MouseButton = MouseButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.click
fun TrackpadInjectionScope.click(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to click on position, or on the current cursor 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 |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
MouseInjectionScope.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 |
button: MouseButton = MouseButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.doubleClick
fun TrackpadInjectionScope.doubleClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to double-click on position, or on the current trackpad 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 |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
GestureScope.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.
IndirectPointerInjectionScope.doubleClick
fun IndirectPointerInjectionScope.doubleClick(
position: Offset = inputDeviceCenter,
delayMillis: Long = viewConfiguration.defaultDoubleTapDelayMillis
): Unit
Performs a double click gesture (aka a double tap) on nodes in the focus path.
The double click is done at the given position within the indirect pointer input device's bounds or inputDeviceCenter if the position is omitted. By default, the delayMillis between the first and the second click is halfway in between the minimum and maximum required delay for a double click. The position is NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize).
| Parameters | |
|---|---|
position: Offset = inputDeviceCenter |
The position where to click, in the indirect pointer input device's coordinate system ( |
delayMillis: Long = viewConfiguration.defaultDoubleTapDelayMillis |
The time between the up event of the first click and the down event of the second click |
TouchInjectionScope.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 |
delayMillis: Long = viewConfiguration.defaultDoubleTapDelayMillis |
The time between the up event of the first click and the down event of the second click |
GestureScope.down
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 |
GestureScope.down
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.
MouseInjectionScope.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 |
durationMillis: Long = DefaultMouseGestureDurationMillis |
The duration of the gesture. By default 300 milliseconds. |
TrackpadInjectionScope.dragAndDrop
fun TrackpadInjectionScope.dragAndDrop(
start: Offset,
end: Offset,
button: TrackpadButton = TrackpadButton.Primary,
durationMillis: Long = DefaultTrackpadGestureDurationMillis
): Unit
Use button to drag and drop something from start to end in durationMillis milliseconds. The trackpad 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 button and initiate the drag, in the node's local coordinate system. |
end: Offset |
The position where to release the primary button and end the drag, in the node's local coordinate system. |
button: TrackpadButton = TrackpadButton.Primary |
The button to drag with. Uses the |
durationMillis: Long = DefaultTrackpadGestureDurationMillis |
The duration of the gesture. By default, 300 milliseconds. |
SemanticsNodeInteractionCollection.filter
fun SemanticsNodeInteractionCollection.filter(matcher: SemanticsMatcher): SemanticsNodeInteractionCollection
Returns all the nodes matching the given matcher.
| Parameters | |
|---|---|
matcher: SemanticsMatcher |
Matcher to use for the filtering. |
SemanticsNodeInteractionCollection.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. |
SemanticsNodeInteraction.getAlignmentLinePosition
fun SemanticsNodeInteraction.getAlignmentLinePosition(
alignmentLine: AlignmentLine
): Dp
Returns the position of an alignment line, or Dp.Unspecified if the line is not provided.
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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) }
| See also | |
|---|---|
performFirstLinkClick |
SemanticsNodeInteraction.getUnclippedBoundsInRoot
fun SemanticsNodeInteraction.getUnclippedBoundsInRoot(): DpRect
Returns the bounds of the layout of this node. The bounds are relative to the root composable.
SemanticsNodeInteraction.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 |
SemanticsNodeInteractionCollection.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 |
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
If multiple nodes match this |
| See also | |
|---|---|
assertIsDisplayed |
ComposeUiTest.isIdlingResourceSupported
fun ComposeUiTest.isIdlingResourceSupported(): Boolean
Capability query to determine if the current ComposeUiTest implementation supports registering an IdlingResource.
While IdlingResource is supported on Android and Desktop, currently it is not available on all targets (such as Web).
| Returns | |
|---|---|
Boolean |
true if the implementation supports |
| See also | |
|---|---|
IdlingResourceOwner |
SemanticsNodeInteraction.isNotDisplayed
fun SemanticsNodeInteraction.isNotDisplayed(): Boolean
Returns true if no matching node is displayed on screen.
Returns false if a matching node is currently displayed. 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 | |
|---|---|
AssertionError |
If multiple nodes match this |
| See also | |
|---|---|
assertIsNotDisplayed |
MouseInjectionScope.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 |
button: MouseButton = MouseButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.longClick
fun TrackpadInjectionScope.longClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to long-click on position, or on the current trackpad 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 |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
GestureScope.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.
IndirectPointerInjectionScope.longClick
fun IndirectPointerInjectionScope.longClick(
position: Offset = inputDeviceCenter,
durationMillis: Long = viewConfiguration.longPressTimeoutMillis + 100
): Unit
Performs a long click gesture (aka a long press) on nodes in the focus path.
The long click is done at the given position within the indirect pointer input device's bounds, or inputDeviceCenter 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 NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize).
| Parameters | |
|---|---|
position: Offset = inputDeviceCenter |
The position where to click, in the indirect pointer input device's coordinate system (see |
durationMillis: Long = viewConfiguration.longPressTimeoutMillis + 100 |
The time between the down and the up event. |
TouchInjectionScope.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.
GestureScope.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.
GestureScope.moveBy
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. |
GestureScope.moveBy
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 |
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. |
GestureScope.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 |
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. |
GestureScope.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.
GestureScope.moveTo
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 |
GestureScope.moveTo
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.
IndirectPointerInjectionScope.multiTouchSwipe
fun IndirectPointerInjectionScope.multiTouchSwipe(
curves: List<(timeMillis: Long) -> Offset>,
durationMillis: Long = 200,
keyTimes: List<Long> = emptyList()
): Unit
Performs a multitouch swipe gesture on nodes in the focus path.
Each pointer follows curves 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 NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize) and is usually used for focused movement (that is, a focused node would move to the next/previous focusable node in the hierarchy with a swipe).
| 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 (default duration is 200 milliseconds) |
keyTimes: List<Long> = emptyList() |
An optional list of timestamps in milliseconds at which a move event must be sampled |
TouchInjectionScope.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 |
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteraction.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
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.onChildAt
fun SemanticsNodeInteraction.onChildAt(index: Int): SemanticsNodeInteraction
Returns child of this node at the given index.
This is just a shortcut for "childrenindex".
SemanticsNodeInteraction.onChildren
fun SemanticsNodeInteraction.onChildren(): SemanticsNodeInteractionCollection
Returns children of this node at the moment of invocation, it only captures nodes that are currently present in the semantic tree.
This is especially relevant for lazy layouts like 'LazyColumn' or 'LazyRow' where only a subset of items are currently composed and exist in the tree. Therefore, this function will only return those currently composed items, not all the items in the backing data set.
SemanticsNodeInteraction.onDescendants
fun SemanticsNodeInteraction.onDescendants(): SemanticsNodeInteractionCollection
Returns all the descendants of this node in Depth-First Search order.
Example: For the following tree
|-A <- this node
|-B
|-C
|-D
|-E
Returns B, C, D, E
SemanticsNodeInteractionCollection.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.
SemanticsNodeInteractionCollection.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.
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteractionsProvider.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. |
SemanticsNodeInteraction.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.
SemanticsNodeInteractionsProvider.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. |
ComposeUiTest.onRootWithViewInteraction
fun ComposeUiTest.onRootWithViewInteraction(interaction: ViewInteraction): SemanticsNodeInteractionsProvider
Scopes Compose interactions to the View hierarchy matched by an Espresso ViewInteraction.
Resolves the View from interaction, locates all Compose roots within that hierarchy, and creates a scoped SemanticsNodeInteractionsProvider.
import androidx.compose.ui.test.junit4.onRootWithViewInteraction import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.performClick import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers.withId // Select the "Header" View container val headerInteraction = onView(withId(header_id)) // Scope the Compose interaction to only the Header composeTestRule .onRootWithViewInteraction(headerInteraction) .onNodeWithContentDescription("Settings") .performClick()
import androidx.compose.ui.test.assertIsDisplayed import androidx.compose.ui.test.junit4.onRootWithViewInteraction import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performClick import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers.hasDescendant import androidx.test.espresso.matcher.ViewMatchers.withId import androidx.test.espresso.matcher.ViewMatchers.withText // Select the specific View row containing "Item #5" val specificRowInteraction = onView(allOf(withId(recycler_item_root_id), hasDescendant(withText("Item #5")))) // Scope interaction to that specific row View composeTestRule .onRootWithViewInteraction(specificRowInteraction) .onNodeWithTag("fav_icon") .assertIsDisplayed() .performClick()
import androidx.compose.ui.test.assertIsEnabled import androidx.compose.ui.test.junit4.onRootWithViewInteraction import androidx.compose.ui.test.onNodeWithText import androidx.test.espresso.Espresso.onView import androidx.test.espresso.matcher.ViewMatchers.withId // Select the container for the Detail Fragment val detailContainerInteraction = onView(withId(detail_fragment_container_id)) // Assert that the submit button exists/is enabled only in the detail fragment composeTestRule .onRootWithViewInteraction(detailContainerInteraction) .onNodeWithText("Submit") .assertIsEnabled()
| Parameters | |
|---|---|
interaction: ViewInteraction |
|
| Returns | |
|---|---|
SemanticsNodeInteractionsProvider |
scoped |
SemanticsNodeInteraction.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.
SemanticsNodeInteraction.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
TrackpadInjectionScope.pan
fun TrackpadInjectionScope.pan(offset: Offset): Unit
Sends a pan gesture with the given total offset. The event will be sent starting at the current event time.
To send a pan gesture with a curve, use pan(curve, durationMillis, keyTimes).
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.pan import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("verticalScrollable").performTrackpadInput { pan(Offset(0f, 100f)) }
| Parameters | |
|---|---|
offset: Offset |
The amount of pan |
TrackpadInjectionScope.pan
fun TrackpadInjectionScope.pan(
curve: (timeMillis: Long) -> Offset,
durationMillis: Long = 200,
keyTimes: List<Long> = emptyList()
): Unit
Sends a pan gesture with the offsets in the panning coordinate space following the given curve. It is expected that the curve starts at Offset.Zero, as a pan gesture starts with no delta, and then move outward from the origin.
To send a pan with just a single amount, use pan(offset).
| 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 pan from the origin 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 pan move event must be sampled |
TrackpadInjectionScope.panWithVelocity
fun TrackpadInjectionScope.panWithVelocity(
offset: Offset,
endVelocity: @FloatRange(from = 0.0) Float,
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(Offset.Zero, offset, endVelocity)
): Unit
Performs a pan gesture on the associated node such that it ends with the given endVelocity.
The pan will go from Offset.Zero at t=0 to offset at t=durationMillis. In between, the pan will go monotonically from Offset.Zero and offset, 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 pan 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 pan coordinate system, which has the same scale as the display in pixel coordinates, where Offset.Zero indicates no panning.
Use pan(curve, duration, durationMillis) to directly control the curve of the pan.
| Parameters | |
|---|---|
offset: Offset |
The end position of the pan |
endVelocity: @FloatRange(from = 0.0) Float |
The velocity of the gesture at the moment it ends in px/second. Must be positive. |
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(Offset.Zero, offset, 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 pan with velocity can be created. |
| Throws | |
|---|---|
IllegalArgumentException |
When no pan can be generated that will result in the desired velocity. The error message will suggest changes to the input parameters such that a pan will become feasible. |
GestureScope.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.
SemanticsNodeInteraction.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.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 |
| Throws | |
|---|---|
AssertionError |
If no |
SemanticsNodeInteraction.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: (label: String) -> Boolean |
A predicate function used to select the |
| Throws | |
|---|---|
AssertionError |
If no |
SemanticsNodeInteraction.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" }
| See also | |
|---|---|
getFirstLinkBounds |
SemanticsNodeInteraction.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 |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
if the node does not support input or does not define IME action. |
IllegalStateException |
if the node did is not an editor or would not be able to establish an input connection (e.g. does not define |
SemanticsNodeInteraction.performKeyInput
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.
import androidx.compose.foundation.clickable import androidx.compose.foundation.text.BasicText import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.input.InputMode.Companion.Keyboard import androidx.compose.ui.input.InputModeManager import androidx.compose.ui.input.key.Key import androidx.compose.ui.platform.LocalInputModeManager import androidx.compose.ui.platform.testTag import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performKeyInput var counter = 0 val focusRequester = FocusRequester() lateinit var inputModeManager: InputModeManager composeTestRule.setContent { inputModeManager = LocalInputModeManager.current BasicText( "ClickableText", modifier = Modifier.testTag("myClickable").focusRequester(focusRequester).clickable { counter++ }, ) } composeTestRule.runOnIdle { inputModeManager.requestInputMode(Keyboard) focusRequester.requestFocus() } composeTestRule.onNodeWithTag("myClickable").performKeyInput { keyDown(Key.Enter) } composeTestRule.runOnIdle { assert(counter == 0) } composeTestRule.onNodeWithTag("myClickable").performKeyInput { keyUp(Key.Enter) } composeTestRule.runOnIdle { assert(counter == 1) }
| Parameters | |
|---|---|
block: KeyInjectionScope.() -> Unit |
A lambda with |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
KeyInjectionScope |
SemanticsNodeInteraction.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. |
SemanticsNodeInteraction.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 |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
MouseInjectionScope |
SemanticsNodeInteraction.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 |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
MultiModalInjectionScope |
SemanticsNodeInteraction.performRotaryScrollInput
fun SemanticsNodeInteraction.performRotaryScrollInput(block: RotaryInjectionScope.() -> Unit): SemanticsNodeInteraction
Executes the rotary input specified in the given block.
The block receives a RotaryInjectionScope which provides access to rotary input injection functions, such as RotaryInjectionScope.rotateToScrollVertically or RotaryInjectionScope.rotateToScrollHorizontally.
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.
Example of performing a scroll with three events:
import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performRotaryScrollInput composeTestRule.onNodeWithTag("myComponent").performRotaryScrollInput { rotateToScrollVertically(3.0f) rotateToScrollVertically(10.0f) rotateToScrollVertically(2.0f) }
| Parameters | |
|---|---|
block: RotaryInjectionScope.() -> Unit |
A lambda with |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
RotaryInjectionScope |
SemanticsNodeInteraction.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.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 |
| See also | |
|---|---|
hasScrollToIndexAction |
SemanticsNodeInteraction.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 |
| See also | |
|---|---|
hasScrollToKeyAction |
SemanticsNodeInteraction.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 |
| See also | |
|---|---|
hasScrollToNodeAction |
SemanticsNodeInteraction.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 |
| Throws | |
|---|---|
AssertionError |
If the semantics action is not defined on this node. |
SemanticsNodeInteraction.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 |
| Throws | |
|---|---|
AssertionError |
If the semantics action is not defined on this node. |
SemanticsNodeInteraction.performTextClearance
fun SemanticsNodeInteraction.performTextClearance(): Unit
Clears the text in this node in similar way to IME.
SemanticsNodeInteraction.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. |
SemanticsNodeInteraction.performTextInputSelection
fun SemanticsNodeInteraction.performTextInputSelection(
selection: TextRange,
relativeToOriginalText: Boolean = true
): Unit
Sends the given selection to this node in similar way to IME.
SemanticsNodeInteraction.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. |
SemanticsNodeInteraction.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 |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
TouchInjectionScope |
SemanticsNodeInteraction.performTrackpadInput
fun SemanticsNodeInteraction.performTrackpadInput(block: TrackpadInjectionScope.() -> Unit): SemanticsNodeInteraction
Executes the trackpad 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 trackpad 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 trackpad click:
import androidx.compose.ui.test.click import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput composeTestRule.onNodeWithTag("myComponent").performTrackpadInput { // Click in the middle of the node click(center) }
| Parameters | |
|---|---|
block: TrackpadInjectionScope.() -> Unit |
A lambda with |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
TrackpadInjectionScope |
GestureScope.pinch
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 |
IndirectPointerInjectionScope.pinch
fun IndirectPointerInjectionScope.pinch(
start0: Offset,
end0: Offset,
start1: Offset,
end1: Offset,
durationMillis: Long = 400
): Unit
Performs a pinch gesture on nodes in the focus path.
For each pair of start and end Offsets, the motion events are linearly interpolated.
The coordinates are NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize).
The default duration is 400 milliseconds.
| Parameters | |
|---|---|
start0: Offset |
The start position of the first pointer in the indirect pointer input device's coordinate system ( |
end0: Offset |
The end position of the first pointer in the indirect pointer input device's coordinate system ( |
start1: Offset |
The start position of the second pointer in the indirect pointer input device's coordinate system. |
end1: Offset |
The end position of the second pointer in the indirect pointer input device's coordinate system ( |
durationMillis: Long = 400 |
the duration of the pinch gesture |
TouchInjectionScope.pinch
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 |
KeyInjectionScope.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.
SemanticsNodeInteraction.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.
SemanticsNodeInteractionCollection.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.
SemanticsNodeInteraction.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. |
SemanticsNodeInteractionCollection.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. |
ComposeUiTest.registerIdlingResource
fun ComposeUiTest.registerIdlingResource(idlingResource: IdlingResource): Boolean
Attempts to register an IdlingResource in this test.
This implementation checks isIdlingResourceSupported before attempting to register the resource.
| Parameters | |
|---|---|
idlingResource: IdlingResource |
|
| Returns | |
|---|---|
Boolean |
true if the idling resource was successfully registered, or false if the implementation does not support idling resources. |
SemanticsNodeInteraction.requestFocus
fun SemanticsNodeInteraction.requestFocus(): SemanticsNodeInteraction
Requests the focus system to give focus to this node by invoking the RequestFocus semantics action.
MouseInjectionScope.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 |
TrackpadInjectionScope.rightClick
fun TrackpadInjectionScope.rightClick(position: Offset = center): Unit
Secondary-click on position, or on the current cursor position if position is unspecified. While the secondary button is not necessarily a physical right button (e.g. a multi-finger tap), this method is still called rightClick for its 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 |
TrackpadInjectionScope.scale
fun TrackpadInjectionScope.scale(
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float
): Unit
Sends a scale event with the given scaleFactor. The event will be sent starting at the current event time.
The scaleFactor is a multiplicative zoom factor. A scaleFactor of 1 represents no change. A scaleFactor less than 1 represents a "zoom out" gesture, while a factor of more than one represents a "zoom in" gesture.
import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.performTrackpadInput import androidx.compose.ui.test.scale composeTestRule.onNodeWithTag("transformable").performTrackpadInput { // Performs a scale with a factor of 0.9f, which corresponds to a "zoom out" gesture. scale(0.9f) }
| Parameters | |
|---|---|
scaleFactor: @FloatRange(from = 0.0, fromInclusive = false) Float |
The amount to scale. |
SemanticsNodeInteractionsProvider.sendIndirectPointerInput
fun SemanticsNodeInteractionsProvider.sendIndirectPointerInput(
indirectPointerEventPrimaryDirectionalMotionAxis: IndirectPointerEventPrimaryDirectionalMotionAxis,
inputDeviceSize: IntSize,
block: IndirectPointerInjectionScope.() -> Unit
): Unit
Sends an indirect pointer gesture globally, targeting the currently focused Compose UI (from root to the focused node).
This API requires an active focus state meaning developers need to request focus to the component or a child of the component via SemanticsNodeInteraction.requestFocus() before calling this function. If no component is currently focused, this will throw an AssertionError.
If there are multiple Compose roots present, this action will target the first focused root.
Indirect pointer input events are touch events that are from an external touchpad whose coordinates are not tied to the screen coordinates.
These events are dispatched through the focused tree, and components will only receive these events if they are focused, or an ancestor of a focused item.
The gesture doesn't need to be complete and can be resumed in a later invocation of sendIndirectPointerInput { ... }. The event time is initialized to the current time of the MainTestClock.
Be aware that if you split a gesture over multiple invocations of sendIndirectPointerInput { }, everything that happens in between will run as if the gesture is still ongoing (imagine a finger still touching the touchpad).
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.
Example of sending a swipe:
import androidx.compose.ui.input.indirect.IndirectPointerEventPrimaryDirectionalMotionAxis import androidx.compose.ui.test.inputDeviceLeft import androidx.compose.ui.test.inputDeviceRight import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.requestFocus import androidx.compose.ui.test.sendIndirectPointerInput import androidx.compose.ui.test.swipeRight import androidx.compose.ui.unit.IntSize // Ensure your node is within the focus path (otherwise, you won't get the event). composeTestRule.onNodeWithTag("myComponent").requestFocus() composeTestRule.sendIndirectPointerInput( indirectPointerEventPrimaryDirectionalMotionAxis = IndirectPointerEventPrimaryDirectionalMotionAxis.X, // Horizontal trackpad inputDeviceSize = IntSize(width = 5000, height = 1000), ) { swipeRight(startX = inputDeviceLeft, endX = inputDeviceRight) }
Examples of click:
import androidx.compose.ui.input.indirect.IndirectPointerEventPrimaryDirectionalMotionAxis import androidx.compose.ui.test.click import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.requestFocus import androidx.compose.ui.test.sendIndirectPointerInput import androidx.compose.ui.unit.IntSize // Ensure the node is within the focus path (otherwise, you won't get the event). composeTestRule.onNodeWithTag("myComponent").requestFocus() composeTestRule.sendIndirectPointerInput( indirectPointerEventPrimaryDirectionalMotionAxis = IndirectPointerEventPrimaryDirectionalMotionAxis.X, // Horizontal trackpad inputDeviceSize = IntSize(width = 5000, height = 1000), ) { click() }
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.input.indirect.IndirectPointerEventPrimaryDirectionalMotionAxis import androidx.compose.ui.test.inputDeviceCenterX import androidx.compose.ui.test.inputDeviceCenterY import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.requestFocus import androidx.compose.ui.test.sendIndirectPointerInput import androidx.compose.ui.unit.IntSize // Ensure the node is within the focus path (otherwise, you won't get the event). composeTestRule.onNodeWithTag("myComponent").requestFocus() composeTestRule.sendIndirectPointerInput( indirectPointerEventPrimaryDirectionalMotionAxis = IndirectPointerEventPrimaryDirectionalMotionAxis.X, // Horizontal trackpad inputDeviceSize = IntSize(width = 5000, height = 1000), ) { down(position = Offset(x = inputDeviceCenterX, y = inputDeviceCenterY)) } // Assert some pressed state is visible composeTestRule.sendIndirectPointerInput( indirectPointerEventPrimaryDirectionalMotionAxis = IndirectPointerEventPrimaryDirectionalMotionAxis.X, // Horizontal trackpad inputDeviceSize = IntSize(width = 5000, height = 1000), ) { up() }
Example of sending a click-and-drag:
import androidx.compose.ui.input.indirect.IndirectPointerEventPrimaryDirectionalMotionAxis import androidx.compose.ui.test.click import androidx.compose.ui.test.inputDeviceLeft import androidx.compose.ui.test.inputDeviceRight import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.test.requestFocus import androidx.compose.ui.test.sendIndirectPointerInput import androidx.compose.ui.test.swipeLeft import androidx.compose.ui.unit.IntSize // Ensure the node is within the focus path (otherwise, you won't get the event). composeTestRule.onNodeWithTag("myComponent").requestFocus() composeTestRule.sendIndirectPointerInput( indirectPointerEventPrimaryDirectionalMotionAxis = IndirectPointerEventPrimaryDirectionalMotionAxis.X, // Horizontal trackpad inputDeviceSize = IntSize(width = 5000, height = 1000), ) { click() advanceEventTime(durationMillis = 100) swipeLeft(startX = inputDeviceRight, endX = inputDeviceLeft) }
| Parameters | |
|---|---|
indirectPointerEventPrimaryDirectionalMotionAxis: IndirectPointerEventPrimaryDirectionalMotionAxis |
The main movement axis (horizontal or vertical) for single-directional scrolling when using the touchpad |
inputDeviceSize: IntSize |
The dimensions of the external indirect pointer input device that provide the boundaries for indirect input. If you go outside these dimensions, the tests will throw an exception. Note: This is not related to the screen coordinates. |
block: IndirectPointerInjectionScope.() -> Unit |
Block of code/events to execute in indirect scope. |
MouseInjectionScope.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 |
durationMillis: Long = DefaultMouseGestureDurationMillis |
The duration of the gesture. By default 300 milliseconds. |
scrollWheel: ScrollWheel = ScrollWheel.Vertical |
Which scroll wheel will be rotated. By default |
| See also | |
|---|---|
scroll |
IndirectPointerInjectionScope.swipe
fun IndirectPointerInjectionScope.swipe(
curve: (timeMillis: Long) -> Offset,
durationMillis: Long = 200,
keyTimes: List<Long> = emptyList()
): Unit
Performs a swipe gesture on nodes in the focus path.
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 NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize) and is usually used for focused movement (that is, a focused node would move to the next/previous focusable node in the hierarchy with a swipe).
| 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 (default duration is 200 milliseconds) |
keyTimes: List<Long> = emptyList() |
An optional list of timestamps in milliseconds at which a move event must be sampled |
TouchInjectionScope.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 |
GestureScope.swipe
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.
IndirectPointerInjectionScope.swipe
fun IndirectPointerInjectionScope.swipe(
start: Offset,
end: Offset,
durationMillis: Long = 200
): Unit
Performs a swipe gesture on nodes in the focus path.
The motion events are linearly interpolated between start and end.
The coordinates are NOT in the node's local coordinate system (see IndirectPointerInjectionScope.inputDeviceSize) and is usually used for focused movement (that is, a focused node would move to the next/previous focusable node in the hierarchy with a swipe).
| Parameters | |
|---|---|
start: Offset |
The position of the pointer starting the swipe gesture, in the indirect pointer input device's coordinate system ( |
end: Offset |
The position of the pointer ending the swipe gesture, in the indirect pointer input device's coordinate system ( |
durationMillis: Long = 200 |
The duration of the swipe gesture (default duration is 200 milliseconds) |
TouchInjectionScope.swipe
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.
GestureScope.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.
GestureScope.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: Float = bottom |
The y-coordinate of the end of the swipe. Must be greater than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
IndirectPointerInjectionScope.swipeDown
fun IndirectPointerInjectionScope.swipeDown(
startY: Float,
endY: Float,
durationMillis: Long = 200
): Unit
Performs a swipe down gesture on nodes in the focus path along x = [IndirectPointerInjectionScope.inputDeviceCenter].x, from startY till endY, taking durationMillis milliseconds.
TouchInjectionScope.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: Float = bottom |
The y-coordinate of the end of the swipe. Must be greater than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
GestureScope.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.
GestureScope.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: Float = left |
The x-coordinate of the end of the swipe. Must be less than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
IndirectPointerInjectionScope.swipeLeft
fun IndirectPointerInjectionScope.swipeLeft(
startX: Float,
endX: Float,
durationMillis: Long = 200
): Unit
Performs a swipe left gesture on nodes in the focus path along y = [IndirectPointerInjectionScope.inputDeviceCenter].y, from startX till endX, taking durationMillis milliseconds.
TouchInjectionScope.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: Float = left |
The x-coordinate of the end of the swipe. Must be less than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
GestureScope.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.
GestureScope.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: Float = right |
The x-coordinate of the end of the swipe. Must be greater than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
IndirectPointerInjectionScope.swipeRight
fun IndirectPointerInjectionScope.swipeRight(
startX: Float,
endX: Float,
durationMillis: Long = 200
): Unit
Performs a swipe right gesture on nodes in the focus path along y = [IndirectPointerInjectionScope.inputDeviceCenter].y, from startX till endX, taking durationMillis milliseconds.
TouchInjectionScope.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: Float = right |
The x-coordinate of the end of the swipe. Must be greater than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
GestureScope.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.
GestureScope.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: Float = top |
The y-coordinate of the end of the swipe. Must be less than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
IndirectPointerInjectionScope.swipeUp
fun IndirectPointerInjectionScope.swipeUp(
startY: Float,
endY: Float,
durationMillis: Long = 200
): Unit
Performs a swipe up gesture on nodes in the focus path along x = [IndirectPointerInjectionScope.inputDeviceCenter].x, from startY till endY, taking durationMillis milliseconds.
TouchInjectionScope.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: Float = top |
The y-coordinate of the end of the swipe. Must be less than or equal to the |
durationMillis: Long = 200 |
The duration of the swipe. By default 200 milliseconds. |
GestureScope.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. |
IndirectPointerInjectionScope.swipeWithVelocity
fun IndirectPointerInjectionScope.swipeWithVelocity(
start: Offset,
end: Offset,
endVelocity: @FloatRange(from = 0.0) Float,
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(start, end, endVelocity)
): Unit
Performs a swipe gesture on nodes in the focus path 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 NOT in the node's local coordinate system and is usually used for focused movement (that is, a focused node would move to the next focusable node in the hierarchy with a swipe).
The default duration is calculated such that a feasible swipe can be created that ends in the given velocity.
| Parameters | |
|---|---|
start: Offset |
The position of the pointer starting the swipe gesture, in the indirect pointer input device's coordinate system. |
end: Offset |
The position of the pointer ending the swipe gesture, in the indirect pointer input device's coordinate system. |
endVelocity: @FloatRange(from = 0.0) Float |
The velocity of the swipe gesture at the moment it ends in px/second. Must be positive. |
durationMillis: Long = VelocityPathFinder.calculateDefaultDuration(start, end, endVelocity) |
The duration of the swipe 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 | |
|---|---|
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. |
TouchInjectionScope.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 | |
|---|---|
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. |
DeviceConfigurationOverride.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.material3.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") }
| Parameters | |
|---|---|
other: DeviceConfigurationOverride |
the |
| Returns | |
|---|---|
DeviceConfigurationOverride |
a new |
MouseInjectionScope.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 |
button: MouseButton = MouseButton.Primary |
The button to click with. Uses the |
TrackpadInjectionScope.tripleClick
fun TrackpadInjectionScope.tripleClick(
position: Offset = center,
button: TrackpadButton = TrackpadButton.Primary
): Unit
Use button to triple-click on position, or on the current trackpad 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 |
button: TrackpadButton = TrackpadButton.Primary |
The button to click with. Uses the |
SemanticsNodeInteractionCollection.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 | |
|---|---|
AssertionError |
if accessibility problems are found |
SemanticsNodeInteraction.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 | |
|---|---|
AssertionError |
if accessibility problems are found |
ComposeUiTest.unregisterIdlingResource
fun ComposeUiTest.unregisterIdlingResource(idlingResource: IdlingResource): Boolean
Attempts to unregister an IdlingResource in this test.
This implementation checks isIdlingResourceSupported before attempting to unregister the resource.
| Parameters | |
|---|---|
idlingResource: IdlingResource |
|
| Returns | |
|---|---|
Boolean |
true if the idling resource was successfully unregistered, or false if the implementation does not support idling resources. |
GestureScope.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.
ComposeUiTest.waitUntilAtLeastOneExists
fun ComposeUiTest.waitUntilAtLeastOneExists(
matcher: SemanticsMatcher,
timeoutMillis: Long,
useUnmergedTree: Boolean = false
): 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 |
useUnmergedTree: Boolean = false |
If true, searches the unmerged semantics tree instead of the merged semantics tree. |
| Throws | |
|---|---|
androidx.compose.ui.test.ComposeTimeoutException |
If no nodes match the given |
| See also | |
|---|---|
waitUntil |
ComposeUiTest.waitUntilDoesNotExist
fun ComposeUiTest.waitUntilDoesNotExist(
matcher: SemanticsMatcher,
timeoutMillis: Long,
useUnmergedTree: Boolean = false
): 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 |
useUnmergedTree: Boolean = false |
If true, searches the unmerged semantics tree instead of the merged semantics tree. |
| Throws | |
|---|---|
androidx.compose.ui.test.ComposeTimeoutException |
If any nodes match the given |
| See also | |
|---|---|
waitUntil |
ComposeUiTest.waitUntilExactlyOneExists
fun ComposeUiTest.waitUntilExactlyOneExists(
matcher: SemanticsMatcher,
timeoutMillis: Long,
useUnmergedTree: Boolean = false
): 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 |
useUnmergedTree: Boolean = false |
If true, searches the unmerged semantics tree instead of the merged semantics tree. |
| Throws | |
|---|---|
androidx.compose.ui.test.ComposeTimeoutException |
If exactly one node does not match the given |
| See also | |
|---|---|
waitUntil |
ComposeUiTest.waitUntilNodeCount
fun ComposeUiTest.waitUntilNodeCount(
matcher: SemanticsMatcher,
count: Int,
timeoutMillis: Long,
useUnmergedTree: Boolean = false
): 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 |
useUnmergedTree: Boolean = false |
If true, searches the unmerged semantics tree instead of the merged semantics tree. |
| Throws | |
|---|---|
androidx.compose.ui.test.ComposeTimeoutException |
If the number of nodes that match the |
| See also | |
|---|---|
waitUntil |
KeyInjectionScope.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: KeyInjectionScope.() -> Unit |
Sequence of KeyInjectionScope methods to be injected with the given key down. |
KeyInjectionScope.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: KeyInjectionScope.() -> Unit |
Sequence of KeyInjectionScope methods to be injected with the given key down. |
KeyInjectionScope.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: KeyInjectionScope.() -> Unit |
Sequence of KeyInjectionScope methods to be injected with the given keys down. |
KeyInjectionScope.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: KeyInjectionScope.() -> Unit |
Sequence of KeyInjectionScope methods to be injected with the given keys down. |
Extension properties
GestureScope.bottom
val GestureScope.bottom: Float
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.
GestureScope.bottomCenter
val GestureScope.bottomCenter: Offset
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.
GestureScope.bottomLeft
val GestureScope.bottomLeft: Offset
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.
GestureScope.bottomRight
val GestureScope.bottomRight: Offset
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.
GestureScope.center
val GestureScope.center: Offset
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.
GestureScope.centerLeft
val GestureScope.centerLeft: Offset
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.
GestureScope.centerRight
val GestureScope.centerRight: Offset
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.
GestureScope.centerX
val GestureScope.centerX: Float
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.
GestureScope.centerY
val GestureScope.centerY: Float
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.
TestMonotonicFrameClock.frameDelayMillis
@ExperimentalTestApi
val TestMonotonicFrameClock.frameDelayMillis: Long
The frame delay time for the TestMonotonicFrameClock in milliseconds.
IndirectPointerInjectionScope.inputDeviceBottom
val IndirectPointerInjectionScope.inputDeviceBottom: Float
The y-coordinate for the bottom of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that, unless inputDeviceHeight == 0, inputDeviceBottom != inputDeviceHeight. In particular, inputDeviceBottom == inputDeviceHeight - 1f, because pixels are 0-based. If inputDeviceHeight == 0, inputDeviceBottom == 0 too.
IndirectPointerInjectionScope.inputDeviceBottomCenter
val IndirectPointerInjectionScope.inputDeviceBottomCenter: Offset
The center of the bottom edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that inputDeviceBottomCenter.y != inputDeviceHeight, see inputDeviceBottom.
IndirectPointerInjectionScope.inputDeviceBottomLeft
val IndirectPointerInjectionScope.inputDeviceBottomLeft: Offset
The bottom left corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that inputDeviceBottomLeft.y != inputDeviceHeight, see inputDeviceBottom.
IndirectPointerInjectionScope.inputDeviceBottomRight
val IndirectPointerInjectionScope.inputDeviceBottomRight: Offset
The bottom right corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that inputDeviceBottomRight.x != inputDeviceWidth and inputDeviceBottomRight.y != inputDeviceHeight, see inputDeviceRight and inputDeviceBottom.
IndirectPointerInjectionScope.inputDeviceCenter
val IndirectPointerInjectionScope.inputDeviceCenter: Offset
The center of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceCenterLeft
val IndirectPointerInjectionScope.inputDeviceCenterLeft: Offset
The center of the left edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceCenterRight
val IndirectPointerInjectionScope.inputDeviceCenterRight: Offset
The center of the right edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that inputDeviceCenterRight.x != inputDeviceWidth, see inputDeviceRight.
IndirectPointerInjectionScope.inputDeviceCenterX
val IndirectPointerInjectionScope.inputDeviceCenterX: Float
The x-coordinate for the center of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceCenterY
val IndirectPointerInjectionScope.inputDeviceCenterY: Float
The y-coordinate for the center of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceHeight
val IndirectPointerInjectionScope.inputDeviceHeight: Int
The height of the external indirect pointer input device that provide the height boundary for indirect input. If you go outside this height, the tests will throw an exception. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceLeft
val IndirectPointerInjectionScope.inputDeviceLeft: Float
The x-coordinate for the left edge of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceRight
val IndirectPointerInjectionScope.inputDeviceRight: Float
The x-coordinate for the right edge of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that, unless inputDeviceWidth == 0, inputDeviceRight != inputDeviceWidth. In particular, inputDeviceRight == inputDeviceWidth - 1f, because pixels are 0-based. If inputDeviceWidth == 0, inputDeviceRight == 0 too.
IndirectPointerInjectionScope.inputDeviceTop
val IndirectPointerInjectionScope.inputDeviceTop: Float
The y-coordinate for the top of the indirect pointer input device we're interacting with in px, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceTopCenter
val IndirectPointerInjectionScope.inputDeviceTopCenter: Offset
The center of the top edge of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceTopLeft
val IndirectPointerInjectionScope.inputDeviceTopLeft: Offset
The top left corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
IndirectPointerInjectionScope.inputDeviceTopRight
val IndirectPointerInjectionScope.inputDeviceTopRight: Offset
The top right corner of the indirect pointer input device we're interacting with, where (0, 0) is the top left corner of the indirect pointer input device. Note: This is not related to the screen coordinates.
Note that inputDeviceTopRight.x != inputDeviceWidth, see inputDeviceRight.
IndirectPointerInjectionScope.inputDeviceWidth
val IndirectPointerInjectionScope.inputDeviceWidth: Int
The width of the external indirect pointer input device that provide the width boundary for indirect input. If you go outside this width, the tests will throw an exception. Note: This is not related to the screen coordinates.
KeyInjectionScope.isAltDown
val KeyInjectionScope.isAltDown: Boolean
Verifies whether either of the alt keys are down.
| Returns | |
|---|---|
Boolean |
true if an alt key is currently down, false otherwise. |
KeyInjectionScope.isCtrlDown
val KeyInjectionScope.isCtrlDown: Boolean
Verifies whether either of the control keys are down.
| Returns | |
|---|---|
Boolean |
true if a control key is currently down, false otherwise. |
KeyInjectionScope.isFnDown
val KeyInjectionScope.isFnDown: Boolean
Verifies whether the function key is down.
| Returns | |
|---|---|
Boolean |
true if the function key is currently down, false otherwise. |
KeyInjectionScope.isMetaDown
val KeyInjectionScope.isMetaDown: Boolean
Verifies whether either of the meta keys are down.
| Returns | |
|---|---|
Boolean |
true if a meta key is currently down, false otherwise. |
KeyInjectionScope.isShiftDown
val KeyInjectionScope.isShiftDown: Boolean
Verifies whether either of the shift keys are down.
| Returns | |
|---|---|
Boolean |
true if a shift key is currently down, false otherwise. |
GestureScope.left
val GestureScope.left: Float
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.
GestureScope.right
val GestureScope.right: Float
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.
GestureScope.top
val GestureScope.top: Float
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.
GestureScope.topCenter
val GestureScope.topCenter: Offset
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.
GestureScope.topLeft
val GestureScope.topLeft: Offset
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.
GestureScope.topRight
val GestureScope.topRight: Offset
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.