SemanticsNodeInteraction
-
Cmn
class SemanticsNodeInteraction
Represents a semantics node and the path to fetch it from the semantics tree. One can interact with this node by performing actions such as performClick, assertions such as assertHasClickAction, or navigate to other nodes such as onChildren.
An instance of SemanticsNodeInteraction can be obtained from onNode and convenience methods that use a specific filter, such as onNodeWithText.
Here you can see how you can locate a checkbox, click it and verify that it's checked:
import androidx.compose.ui.test.assertIsOn import androidx.compose.ui.test.isToggleable import androidx.compose.ui.test.performClick composeTestRule.onNode(isToggleable()).performClick().assertIsOn()
useUnmergedTree is for tests with a special need to inspect implementation detail within children. For example:
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag import androidx.compose.ui.test.assertLeftPositionInRootIsEqualTo import androidx.compose.ui.test.assertTopPositionInRootIsEqualTo import androidx.compose.ui.test.onNodeWithTag import androidx.compose.ui.unit.dp composeTestRule.setContent { // Box is a semantically merging composable. All testTags of its // children are merged up into it in the merged semantics tree. Box(Modifier.testTag("box").padding(16.dp)) { Box(Modifier.testTag("icon").size(48.dp)) } } // Verify the position of the inner box. Without `useUnmergedTree`, the // test would check the position of the outer box (which is `(0, 0)`) // instead of the position of the inner box (which is `(16, 16)`). composeTestRule .onNodeWithTag("icon", useUnmergedTree = true) .assertLeftPositionInRootIsEqualTo(16.dp) .assertTopPositionInRootIsEqualTo(16.dp)
Summary
Public constructors |
|
|---|---|
SemanticsNodeInteraction( |
Cmn
|
SemanticsNodeInteraction( |
Cmn
|
Public functions |
||
|---|---|---|
Unit |
Asserts that no item was found or that the item is no longer in the hierarchy. |
Cmn
|
SemanticsNodeInteraction |
assertExists(errorMessageOnFail: String?)Asserts that the component was found and is part of the component tree. |
Cmn
|
Unit |
assertIsDeactivated(errorMessageOnFail: String?)Asserts that the component was found and it is deactivated. |
Cmn
|
SemanticsNode |
fetchSemanticsNode(errorMessageOnFail: String?)Returns the semantics node captured by this object. |
Cmn
|
Extension functions |
||
|---|---|---|
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
|
SemanticsNodeInteraction |
Executes the key input gesture specified in the given |
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 |
@ExperimentalTestApiSend the specified |
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
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.performTouchInput(block: TouchInjectionScope.() -> Unit)Executes the touch gesture specified in the given |
Cmn
|
SemanticsNodeInteraction |
Requests the focus system to give focus to this node by invoking the |
Cmn
|
SemanticsNodeInteraction |
Tries to perform accessibility checks on the current screen. |
Cmn
android
|
ImageBitmap |
@RequiresApi(value = 26)Captures the underlying semantics node's surface into bitmap. |
android
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assert(Asserts that the provided |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertContentDescriptionContains(Asserts that the node's content description contains the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertContentDescriptionEquals(Asserts that the node's content description contains exactly 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 |
Asserts that the current semantics node is displayed on screen. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is enabled. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node has a focus. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is not displayed on screen. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is not enabled. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node does not have a focus. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is not selected. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is unchecked. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is checked. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is selectable. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is selected. |
Cmn
|
SemanticsNodeInteraction |
Asserts that the current semantics node is toggleable. |
Cmn
|
SemanticsNodeInteraction |
Asserts the node's range info equals the given value. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTextContains(Asserts that the node's text contains the given |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTextEquals(Asserts that the node's text contains exactly the given |
Cmn
|
SemanticsNodeInteraction |
Asserts the node's value equals the given value. |
Cmn
|
Boolean |
Returns true if the matched node is displayed on screen. |
Cmn
|
Boolean |
Asserts that the current semantics node is not displayed on screen. |
Cmn
|
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(expectedHeight: Dp)Asserts that the layout of this node has height equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(Asserts that the layout of this node has the left position in the root composable that is equal to the given position. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertPositionInRootIsEqualTo(Asserts that the layout of this node has position in the root composable that is equal to the given position. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(Asserts that the layout of this node has the top position in the root composable that is equal to the given position. |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTouchHeightIsEqualTo(Asserts that the touch bounds of this node has height equal to |
Cmn
|
SemanticsNodeInteraction |
SemanticsNodeInteraction.assertTouchWidthIsEqualTo(expectedWidth: Dp)Asserts that the touch bounds of this node has width equal to |
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(expectedWidth: Dp)Asserts that the layout of this node has width equal to |
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
|
Boolean |
SemanticsNodeInteraction.performKeyPress(keyEvent: KeyEvent)Send the specified |
Cmn
|
Unit |
SemanticsNodeInteraction.printToLog(tag: String, maxDepth: Int)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
|
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
|
SemanticsNodeInteraction |
Returns a parent of this node. |
Cmn
|
SemanticsNodeInteraction |
Returns exactly one sibling of this node. |
Cmn
|
SemanticsNodeInteractionCollection |
Returns all siblings of this node. |
Cmn
|
Unit |
Sends to this node the IME action associated with it in a similar way to the IME. |
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
|
Public constructors
SemanticsNodeInteraction
SemanticsNodeInteraction(
testContext: TestContext,
useUnmergedTree: Boolean,
matcher: SemanticsMatcher
)
SemanticsNodeInteraction
SemanticsNodeInteraction(
testContext: TestContext,
useUnmergedTree: Boolean,
selector: SemanticsSelector
)
Public functions
assertDoesNotExist
fun assertDoesNotExist(): Unit
Asserts that no item was found or that the item is no longer in the hierarchy.
This will synchronize with the UI and fetch all the nodes again to ensure it has latest data.
| Throws | |
|---|---|
kotlin.AssertionError |
if the assert fails. |
assertExists
fun assertExists(errorMessageOnFail: String? = null): SemanticsNodeInteraction
Asserts that the component was found and is part of the component tree.
This will synchronize with the UI and fetch all the nodes again to ensure it has latest data. If you are using fetchSemanticsNode you don't need to call this. In fact you would just introduce additional overhead.
| Parameters | |
|---|---|
errorMessageOnFail: String? = null |
Error message prefix to be added to the message in case this asserts fails. This is typically used by operations that rely on this assert. Example prefix could be: "Failed to perform doOnClick.". |
| Throws | |
|---|---|
kotlin.AssertionError |
if the assert fails. |
assertIsDeactivated
fun assertIsDeactivated(errorMessageOnFail: String? = null): Unit
Asserts that the component was found and it is deactivated.
For example, the children of androidx.compose.ui.layout.SubcomposeLayout which are retained to be reused in future are considered deactivated.
| Throws | |
|---|---|
kotlin.AssertionError |
if the assert fails. |
fetchSemanticsNode
fun fetchSemanticsNode(errorMessageOnFail: String? = null): SemanticsNode
Returns the semantics node captured by this object.
Note: Accessing this object involves synchronization with your UI. If you are accessing this multiple times in one atomic operation, it is better to cache the result instead of calling this API multiple times.
This will fail if there is 0 or multiple nodes matching.
| Throws | |
|---|---|
kotlin.AssertionError |
if 0 or multiple nodes found. |
Extension functions
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 |
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 | |
|---|---|
kotlin.AssertionError |
If no |
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 | |
|---|---|
kotlin.AssertionError |
If no |
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 |
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 |
performKeyInput
@ExperimentalTestApi
fun SemanticsNodeInteraction.performKeyInput(block: KeyInjectionScope.() -> Unit): SemanticsNodeInteraction
Executes the key input gesture specified in the given block. The gesture doesn't need to be complete and can be resumed in a later invocation of one of the perform.*Input methods. The event time is initialized to the current time of the MainTestClock.
All events that are injected from the block are batched together and sent after block is complete. This method blocks while the events are injected. If an error occurs during execution of block or injection of the events, all (subsequent) events are dropped and the error is thrown here.
Due to the batching of events, all events in a block are sent together and no recomposition will take place in between events. Additionally all events will be generated before any of the events take effect. This means that the screen coordinates of all events are resolved before any of the events can cause the position of the node being injected into to change. This has certain advantages, for example, in the cases of nested scrolling or dragging an element around, it prevents the injection of events into a moving target since all events are enqueued before any of them has taken effect.
| Parameters | |
|---|---|
block: KeyInjectionScope.() -> Unit |
A lambda with |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| See also | |
|---|---|
KeyInjectionScope |
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 |
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 |
performRotaryScrollInput
@ExperimentalTestApi
fun SemanticsNodeInteraction.performRotaryScrollInput(block: RotaryInjectionScope.() -> Unit): SemanticsNodeInteraction
Send the specified RotaryScrollEvent to the focused component.
| Returns | |
|---|---|
SemanticsNodeInteraction |
true if the event was consumed. False otherwise. |
performScrollTo
fun SemanticsNodeInteraction.performScrollTo(): SemanticsNodeInteraction
Scrolls the closest enclosing scroll parent by the smallest amount such that this node is fully visible in its viewport. If this node is larger than the viewport, scrolls the scroll parent by the smallest amount such that this node fills the entire viewport. A scroll parent is a parent node that has the semantics action SemanticsActions.ScrollBy (usually implemented by defining scrollBy).
This action should be performed on the node that is part of the scrollable content, not on the scrollable container.
Throws an AssertionError if there is no scroll parent.
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
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 |
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 |
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 |
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 | |
|---|---|
kotlin.AssertionError |
If the semantics action is not defined on this node. |
performSemanticsAction
fun <T : () -> Boolean> SemanticsNodeInteraction.performSemanticsAction(
key: SemanticsPropertyKey<AccessibilityAction<T>>,
invocation: (T) -> Unit
): SemanticsNodeInteraction
Provides support to call custom semantics actions on this node.
This method is supposed to be used for actions with parameters.
This will properly verify that the actions exists and provide clear error message in case it does not. It also handle synchronization and performing the action on the UI thread. This call is blocking until the action is performed
| Parameters | |
|---|---|
key: SemanticsPropertyKey<AccessibilityAction<T>> |
Key of the action to be performed. |
invocation: (T) -> Unit |
Place where you call your action. In the argument is provided the underlying action from the given Semantics action. |
| Returns | |
|---|---|
SemanticsNodeInteraction |
The |
| Throws | |
|---|---|
kotlin.AssertionError |
If the semantics action is not defined on this node. |
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 |
requestFocus
fun SemanticsNodeInteraction.requestFocus(): SemanticsNodeInteraction
Requests the focus system to give focus to this node by invoking the RequestFocus semantics action.
tryPerformAccessibilityChecks
fun SemanticsNodeInteraction.tryPerformAccessibilityChecks(): SemanticsNodeInteraction
Tries to perform accessibility checks on the current screen. This will only actually do something if (1) accessibility checks are enabled and (2) accessibility checks are implemented for the platform on which the test runs.
| Throws | |
|---|---|
kotlin.AssertionError |
if accessibility problems are found |
captureToImage
@RequiresApi(value = 26)
fun SemanticsNodeInteraction.captureToImage(): ImageBitmap
Captures the underlying semantics node's surface into bitmap. This can be used to capture nodes in a normal composable, a dialog if API >=28 and in a Popup. Note that the mechanism used to capture the bitmap from a Popup is not the same as from a normal composable, since a PopUp is in a different window.
| Throws | |
|---|---|
kotlin.IllegalArgumentException |
if we attempt to capture a bitmap of a dialog before API 28. |
assert
fun SemanticsNodeInteraction.assert(
matcher: SemanticsMatcher,
messagePrefixOnError: (() -> String)? = null
): SemanticsNodeInteraction
Asserts that the provided matcher is satisfied for this node.
| Parameters | |
|---|---|
matcher: SemanticsMatcher |
Matcher to verify. |
messagePrefixOnError: (() -> String)? = null |
Prefix to be put in front of an error that gets thrown in case this assert fails. This can be helpful in situations where this assert fails as part of a bigger operation that used this assert as a precondition check. |
| Throws | |
|---|---|
kotlin.AssertionError |
if the matcher does not match or the node can no longer be found. |
assertContentDescriptionContains
fun SemanticsNodeInteraction.assertContentDescriptionContains(
value: String,
substring: Boolean = false,
ignoreCase: Boolean = false
): SemanticsNodeInteraction
Asserts that the node's content description contains the given value.
Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.
Throws AssertionError if the node's value does not contain value, or if the node has no value
| Parameters | |
|---|---|
value: String |
Value to match as one of the items in the list of content descriptions. |
substring: Boolean = false |
Whether this can be satisfied as a substring match of an item in the list of descriptions. |
ignoreCase: Boolean = false |
Whether case should be ignored. |
| See also | |
|---|---|
ContentDescription |
assertContentDescriptionEquals
fun SemanticsNodeInteraction.assertContentDescriptionEquals(
vararg values: String
): SemanticsNodeInteraction
Asserts that the node's content description contains exactly the given values and nothing else.
Note that in merged semantics tree there can be a list of content descriptions that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to announce.
Throws AssertionError if the node's descriptions don't contain all items from values, or if the descriptions contain extra items that are not in values.
| Parameters | |
|---|---|
vararg values: String |
List of values to match (the order does not matter) |
| See also | |
|---|---|
ContentDescription |
assertHasClickAction
fun SemanticsNodeInteraction.assertHasClickAction(): SemanticsNodeInteraction
Asserts that the current semantics node has a click action.
Throws AssertionError if the node is doesn't have a click action.
assertHasNoClickAction
fun SemanticsNodeInteraction.assertHasNoClickAction(): SemanticsNodeInteraction
Asserts that the current semantics node has doesn't have a click action.
Throws AssertionError if the node has a click action.
assertIsDisplayed
fun SemanticsNodeInteraction.assertIsDisplayed(): SemanticsNodeInteraction
Asserts that the current semantics node is displayed on screen.
Specifically, the node must be composed, placed and at least a portion of its bounds must be visible on screen after clipping is applied.
Throws AssertionError if the node is not displayed.
assertIsEnabled
fun SemanticsNodeInteraction.assertIsEnabled(): SemanticsNodeInteraction
Asserts that the current semantics node is enabled.
Throws AssertionError if the node is not enabled or does not define the property at all.
assertIsFocused
fun SemanticsNodeInteraction.assertIsFocused(): SemanticsNodeInteraction
Asserts that the current semantics node has a focus.
Throws AssertionError if the node is not in the focus or does not defined the property at all.
assertIsNotDisplayed
fun SemanticsNodeInteraction.assertIsNotDisplayed(): SemanticsNodeInteraction
Asserts that the current semantics node is not displayed on screen.
Throws AssertionError if the node is displayed.
assertIsNotEnabled
fun SemanticsNodeInteraction.assertIsNotEnabled(): SemanticsNodeInteraction
Asserts that the current semantics node is not enabled.
Throws AssertionError if the node is enabled or does not defined the property at all.
assertIsNotFocused
fun SemanticsNodeInteraction.assertIsNotFocused(): SemanticsNodeInteraction
Asserts that the current semantics node does not have a focus.
Throws AssertionError if the node is in the focus or does not defined the property at all.
assertIsNotSelected
fun SemanticsNodeInteraction.assertIsNotSelected(): SemanticsNodeInteraction
Asserts that the current semantics node is not selected.
Throws AssertionError if the node is selected or not selectable.
assertIsOff
fun SemanticsNodeInteraction.assertIsOff(): SemanticsNodeInteraction
Asserts that the current semantics node is unchecked.
Throws AssertionError if the node is checked, indeterminate, or not toggleable.
assertIsOn
fun SemanticsNodeInteraction.assertIsOn(): SemanticsNodeInteraction
Asserts that the current semantics node is checked.
Throws AssertionError if the node is not unchecked, indeterminate, or not toggleable.
assertIsSelectable
fun SemanticsNodeInteraction.assertIsSelectable(): SemanticsNodeInteraction
Asserts that the current semantics node is selectable.
Throws AssertionError if the node is not selectable.
assertIsSelected
fun SemanticsNodeInteraction.assertIsSelected(): SemanticsNodeInteraction
Asserts that the current semantics node is selected.
Throws AssertionError if the node is unselected or not selectable.
assertIsToggleable
fun SemanticsNodeInteraction.assertIsToggleable(): SemanticsNodeInteraction
Asserts that the current semantics node is toggleable.
Throws AssertionError if the node is not toggleable.
assertRangeInfoEquals
fun SemanticsNodeInteraction.assertRangeInfoEquals(
value: ProgressBarRangeInfo
): SemanticsNodeInteraction
Asserts the node's range info equals the given value.
For further details please check SemanticsProperties.ProgressBarRangeInfo. Throws AssertionError if the node's value is not equal to value, or if the node has no value
assertTextContains
fun SemanticsNodeInteraction.assertTextContains(
value: String,
substring: Boolean = false,
ignoreCase: Boolean = false
): SemanticsNodeInteraction
Asserts that the node's text contains the given value.
This will also search in SemanticsProperties.EditableText 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.
Throws AssertionError if the node's value does not contain value, or if the node has no value
| Parameters | |
|---|---|
value: String |
Value to match as one of the items in the list of text values. |
substring: Boolean = false |
Whether this can be satisfied as a substring match of an item in the list of text. |
ignoreCase: Boolean = false |
Whether case should be ignored. |
| See also | |
|---|---|
Text |
assertTextEquals
fun SemanticsNodeInteraction.assertTextEquals(
vararg values: String,
includeEditableText: Boolean = true
): SemanticsNodeInteraction
Asserts that the node's text contains exactly the given values and nothing else.
This will also search in SemanticsProperties.EditableText by default.
Note that in merged semantics tree there can be a list of text items that got merged from the child nodes. Typically an accessibility tooling will decide based on its heuristics which ones to use.
Throws AssertionError if the node's text values don't contain all items from values, or if the text values contain extra items that are not in values.
| Parameters | |
|---|---|
vararg values: String |
List of values to match (the order does not matter) |
includeEditableText: Boolean = true |
Whether to also assert against the editable text. |
| See also | |
|---|---|
ContentDescription |
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
isDisplayed
fun SemanticsNodeInteraction.isDisplayed(): Boolean
Returns true if the matched node is displayed on screen.
Specifically, the node must be composed, placed and at least a portion of its bounds must be visible on screen after clipping is applied. If no matching node is found, returns false. If multiple nodes match, throws an AssertionError.
import androidx.compose.ui.test.isDisplayed import androidx.compose.ui.test.onNodeWithTag val interaction = composeTestRule.onNodeWithTag("test") composeTestRule.waitUntil { interaction.isDisplayed() }
| Throws | |
|---|---|
kotlin.AssertionError |
If multiple nodes match this |
isNotDisplayed
fun SemanticsNodeInteraction.isNotDisplayed(): Boolean
Asserts that the current semantics node is not displayed on screen.
If no matching node is found, returns true. If multiple nodes match, throws an AssertionError.
import androidx.compose.ui.test.isNotDisplayed import androidx.compose.ui.test.onNodeWithTag val interaction = composeTestRule.onNodeWithTag("test") composeTestRule.waitUntil { interaction.isNotDisplayed() }
| Throws | |
|---|---|
kotlin.AssertionError |
If multiple nodes match this |
assertHeightIsAtLeast
fun SemanticsNodeInteraction.assertHeightIsAtLeast(expectedMinHeight: Dp): SemanticsNodeInteraction
Asserts that the layout of this node has height that is greater than or equal to expectedMinHeight.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertHeightIsEqualTo
fun SemanticsNodeInteraction.assertHeightIsEqualTo(expectedHeight: Dp): SemanticsNodeInteraction
Asserts that the layout of this node has height equal to expectedHeight.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertLeftPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertLeftPositionInRootIsEqualTo(
expectedLeft: Dp
): SemanticsNodeInteraction
Asserts that the layout of this node has the left position in the root composable that is equal to the given position.
| Parameters | |
|---|---|
expectedLeft: Dp |
The left (x) position to assert. |
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertPositionInRootIsEqualTo(
expectedLeft: Dp,
expectedTop: Dp
): SemanticsNodeInteraction
Asserts that the layout of this node has position in the root composable that is equal to the given position.
| Parameters | |
|---|---|
expectedLeft: Dp |
The left (x) position to assert. |
expectedTop: Dp |
The top (y) position to assert. |
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertTopPositionInRootIsEqualTo
fun SemanticsNodeInteraction.assertTopPositionInRootIsEqualTo(
expectedTop: Dp
): SemanticsNodeInteraction
Asserts that the layout of this node has the top position in the root composable that is equal to the given position.
| Parameters | |
|---|---|
expectedTop: Dp |
The top (y) position to assert. |
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertTouchHeightIsEqualTo
fun SemanticsNodeInteraction.assertTouchHeightIsEqualTo(
expectedHeight: Dp
): SemanticsNodeInteraction
Asserts that the touch bounds of this node has height equal to expectedHeight.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertTouchWidthIsEqualTo
fun SemanticsNodeInteraction.assertTouchWidthIsEqualTo(expectedWidth: Dp): SemanticsNodeInteraction
Asserts that the touch bounds of this node has width equal to expectedWidth.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertWidthIsAtLeast
fun SemanticsNodeInteraction.assertWidthIsAtLeast(expectedMinWidth: Dp): SemanticsNodeInteraction
Asserts that the layout of this node has width that is greater than or equal to expectedMinWidth.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
assertWidthIsEqualTo
fun SemanticsNodeInteraction.assertWidthIsEqualTo(expectedWidth: Dp): SemanticsNodeInteraction
Asserts that the layout of this node has width equal to expectedWidth.
| Throws | |
|---|---|
kotlin.AssertionError |
if comparison fails. |
getAlignmentLinePosition
fun SemanticsNodeInteraction.getAlignmentLinePosition(
alignmentLine: AlignmentLine
): Dp
Returns the position of an alignment line, or Dp.Unspecified if the line is not provided.
getBoundsInRoot
fun SemanticsNodeInteraction.getBoundsInRoot(): DpRect
Returns the bounds of the layout of this node as clipped to the root. The bounds are relative to the root composable.
getFirstLinkBounds
fun SemanticsNodeInteraction.getFirstLinkBounds(
predicate: (AnnotatedString.Range<LinkAnnotation>) -> Boolean = { true }
): Rect?
Returns the bounds of the first link matching the predicate, or if that link spans multiple lines, returns the bounds of the first line of the link.
A link in a Text composable is defined by a LinkAnnotation of the AnnotatedString.
The bounds are in the text node's coordinate system.
You can pass an offset from within the bounds to injection methods to operate them on the link, for example TouchInjectionScope.click or MouseInjectionScope.moveTo.
import androidx.compose.ui.test.getFirstLinkBounds import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performMouseInput import androidx.compose.ui.text.LinkAnnotation // Example of hovering over the first link in test val firstLinkBounds = composeTestRule.onNodeWithText("YOUR_TEXT_WITH_LINK").getFirstLinkBounds { (it.item as? LinkAnnotation.Url)?.url == "YOUR_URL" } composeTestRule.onNodeWithText("YOUR_TEXT_WITH_LINK").performMouseInput { moveTo(firstLinkBounds!!.center) }
| See also | |
|---|---|
performFirstLinkClick |
getUnclippedBoundsInRoot
fun SemanticsNodeInteraction.getUnclippedBoundsInRoot(): DpRect
Returns the bounds of the layout of this node. The bounds are relative to the root composable.
invokeGlobalAssertions
@ExperimentalTestApi
fun SemanticsNodeInteraction.invokeGlobalAssertions(): SemanticsNodeInteraction
Executes all of the assertions registered by addGlobalAssertion. This may be useful in a custom test action.
| Returns | |
|---|---|
SemanticsNodeInteraction |
the |
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. |
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.
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. |
onAncestors
fun SemanticsNodeInteraction.onAncestors(): SemanticsNodeInteractionCollection
Returns all the ancestors of this node.
Example: For the following tree
|-A
|-B
|-C <- this node
Returns B, A
onChild
fun SemanticsNodeInteraction.onChild(): SemanticsNodeInteraction
Returns exactly one child of this node.
Use this only if this node has exactly one child.
Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if none or more than one element is found.
onChildAt
fun SemanticsNodeInteraction.onChildAt(index: Int): SemanticsNodeInteraction
Returns child of this node at the given index.
This is just a shortcut for "childrenindex".
onChildren
fun SemanticsNodeInteraction.onChildren(): SemanticsNodeInteractionCollection
Returns children of this node 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.
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.
onSibling
fun SemanticsNodeInteraction.onSibling(): SemanticsNodeInteraction
Returns exactly one sibling of this node.
Use this only if this node has exactly one sibling.
Any subsequent operation on its result will expect exactly one element found (unless SemanticsNodeInteraction.assertDoesNotExist is used) and will throw AssertionError if none or more than one element is found.
onSiblings
fun SemanticsNodeInteraction.onSiblings(): SemanticsNodeInteractionCollection
Returns all siblings of this node.
Example: For the following tree
|-A
|-B1
|-B2 <- this node
|-B3
Returns B1, B3
performImeAction
fun SemanticsNodeInteraction.performImeAction(): Unit
Sends to this node the IME action associated with it in a similar way to the IME.
The node needs to define its IME action in semantics via SemanticsPropertyReceiver.onImeAction.
| Throws | |
|---|---|
kotlin.AssertionError |
if the node does not support input or does not define IME action. |
kotlin.IllegalStateException |
if the node did is not an editor or would not be able to establish an input connection (e.g. does not define |
performTextClearance
fun SemanticsNodeInteraction.performTextClearance(): Unit
Clears the text in this node in similar way to IME.
performTextInput
fun SemanticsNodeInteraction.performTextInput(text: String): Unit
Sends the given text to this node in similar way to IME.
| Parameters | |
|---|---|
text: String |
Text to send. |
performTextInputSelection
fun SemanticsNodeInteraction.performTextInputSelection(
selection: TextRange,
relativeToOriginalText: Boolean = true
): Unit
Sends the given selection to this node in similar way to IME.
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. |