Selectors
Identify UI elements with core, relational, and state selectors on Android and iOS.
Selectors identify the UI element a command acts on, for example the target of tapOn, assertVisible, copyTextFrom or scrollUntilVisible. Astra Scout uses the accessibility tree of the device to find elements, so your flows interact with the app the way a user would.
This page covers the selector fields that Astra Scout supports on Android and iOS. The syntax is identical to Maestro flow YAML.
Support at a glance
| Selector | Android | iOS | Notes |
|---|---|---|---|
text | Yes | Yes | Regular expression, matches the whole text. |
id | Yes | Yes | Regular expression. |
index | Yes | Yes | 0-based. |
point | Yes | Yes | Coordinates, used by tapOn and similar commands. |
above, below, leftOf, rightOf | Yes | Yes | Position relative to an anchor. |
childOf, containsChild, containsDescendants | Yes | Yes | Hierarchy relations. |
enabled, selected, focused | Yes | Yes | Boolean state. |
checked | Yes | No | Ignored on iOS with a warning. |
width, height, tolerance | Yes | Yes | Size in pixels as reported by the accessibility tree. |
traits | No | No | Parsed but never matched. See Not supported. |
css | No | No | Web only; Astra Scout does not run web flows. |
When a flow uses a selector field the current platform does not support, the field is ignored and the run log shows a warning such as "checked" is not supported on ios. The step then runs with the remaining fields, so it may match a different element than you expect.
Core selectors
Regular expressions
text and id are regex-based, so dynamic values are easy to handle. Remember to escape special characters such as $ or [ with a backslash (\).
Platform specifics
- Flutter: Use visible text or Semantics Labels (for
text), or Semantics Identifiers (forid). Internal Flutter keys are not supported. - Android Compose: Use
Modifier.semantics { testTagsAsResourceId = true }so your test tags are discoverable as IDs.
text
The text selector finds elements by the string displayed on screen. On Android this includes contentDescription, and on iOS it includes accessibilityLabel.
- Regex by default: every text selector is treated as a regular expression.
- Shorthand: you can skip the key and pass a string directly to commands such as
tapOnorassertVisible.
- tapOn: Login # Shorthand (matches exactly "Login")
- tapOn:
text: ".*Continue.*" # Regex for partial match
- assertVisible: Submit # Shorthand for visibility checkid
The id selector targets the technical identifier of a view. It is recommended for dynamic content, icons without text, and localized apps where the visible text changes with the language.
- Android: maps to the resource ID.
- iOS: maps to the
accessibilityIdentifier.
- tapOn:
id: login_button
- assertVisible:
id: header_iconindex
When several elements match the same criteria (for example three Add to Cart buttons on one screen), index picks one. The index is 0-based.
# Taps the third element with the ID "buy_button"
- tapOn:
id: buy_button
index: 2point
The point selector targets screen coordinates. Use it for elements that are not in the accessibility tree, or to tap a specific area of a large view.
- Relative position: percentages, for example
"50%, 50%"for the center. - Absolute coordinates: exact pixels, for example
"100, 200".
- tapOn:
point: "50%, 50%" # Taps the center of the screen
- tapOn:
point: "100, 250" # Taps 100 pixels from the left, 250 from the topRelational selectors
Relational selectors identify a view by its relationship to another view. They are useful when elements have generic names (like several "Buy" buttons) or lack a stable text or id but always sit near a known anchor.
| Selector | Description |
|---|---|
above | Matches a view located vertically above an anchor element. |
below | Matches a view located vertically below an anchor element. |
leftOf | Matches a view located to the left of an anchor element. |
rightOf | Matches a view located to the right of an anchor element. |
containsChild | Matches a parent that has a direct child matching the given criteria. |
childOf | Matches an element that is a direct child of the given parent. |
containsDescendants | Matches a view that contains all the given descendants, at any depth. |
Usage tips
- Compound selectors: the positional selectors (
above,below,leftOf,rightOf) compare screen bounds.leftOfmeans "left of" by coordinate only, not necessarily next to or aligned with the anchor. Combine them with other fields (id,text,enabled, and so on) for precision:tapOn: { id: "icon", rightOf: "Settings", enabled: true }. - Anchor reliability: use the most stable element (typically static text or a unique ID) as the anchor.
Alignment selectors
above and below match views above or below a reference element:
# Tap a view located below the "Email" label
- tapOn:
below: Email
# Tap a view located above the "Checkout" title
- tapOn:
above: CheckoutleftOf and rightOf match views positioned side by side, such as icons next to labels:
# Tap the view to the right of an input field
- tapOn:
rightOf:
id: input_text
# Tap the view to the left of a specific phrase
- tapOn:
leftOf: I agree to the termsYou can nest above or below to assert vertical order:
- assertVisible:
text: Top Thing
above:
text: Middle Thing
above:
text: Bottom ThingParent-child relationships
These selectors navigate the accessibility tree instead of using screen position.
containsChild (direct child only)
Matches a parent that has a direct child matching the given selector.
# Tap the container that directly contains the text "Order 12345"
- tapOn:
containsChild:
text: Order 12345childOf (direct parent only)
Matches an element that is a direct child of a specific parent. Useful when the same child exists in several containers.
# Tap the Delete button inside the Basket
- tapOn:
text: Delete
childOf:
id: basket_containercontainsDescendants
Matches a view that contains all the specified descendants at any depth, not only direct children. Use it for cards, rows and grouped layouts where the relevant elements are nested.
# Find a list item that contains both a product name and a price
- assertVisible:
id: list_item
containsDescendants:
- text: Wireless Headphones
- text: $99.99State selectors
State selectors filter elements by their current status. Use them to check that an element is ready, that a previous action updated it, or to find one element among several identical ones (for example the selected tab). All state selectors take a boolean.
| Selector | Android | iOS | Description |
|---|---|---|---|
enabled | Yes | Yes | Whether the element is interactive or grayed out. |
selected | Yes | Yes | Whether the element is marked as selected (tabs, segmented controls). |
focused | Yes | Yes | Whether the element has keyboard input focus. |
checked | Yes | No | Toggle state of checkboxes, radio buttons and switches. |
Usage tips
State selectors work best combined with core selectors, for example tapOn: { text: "Next", enabled: true }.
# Assert that the login button is disabled initially
- assertVisible:
id: login_button
enabled: false
# Tap the button once it becomes active
- tapOn:
id: login_button
enabled: true
# Verify that the search field has focus
- assertVisible:
id: search_input
focused: true
# Find the Profile tab only if it is the selected one
- tapOn:
text: Profile
selected: trueOn Android, checked works for checkboxes, radio buttons and switches:
- assertVisible:
id: remember_me_checkbox
checked: trueWARNING
checked is not supported on iOS. The field is ignored with a warning, so the step matches regardless of the toggle state. On iOS, assert on the element's visible label or value instead.
Dimension matchers
Dimension selectors match elements by their size on screen.
| Selector | Description |
|---|---|
width | Matches an element with a specific width in pixels. |
height | Matches an element with a specific height in pixels. |
tolerance | Allows minor rendering or rounding differences when matching dimensions. |
Usage tips
Be careful with hardcoded pixel values when you run flows on devices with different screen densities. Combine width and height with other selectors, and use a higher tolerance to keep flows stable across devices.
width and height match the pixel dimensions reported by the accessibility tree:
# Taps a button that is exactly 200px wide
- tapOn:
id: action_button
width: 200
# Asserts that the profile header has a height of 350px
- assertVisible:
id: profile_header
height: 350tolerance sets a buffer, because a 100px button may report 99px or 101px depending on scaling. With tolerance: 5, any element within plus or minus 5 pixels of the target dimension matches.
# Matches an icon that is 48px square, with 2px of wiggle room
- assertVisible:
id: settings_icon
width: 48
height: 48
tolerance: 2Not supported
These selector fields from Maestro are not available in Astra Scout:
traits(text,long-text,square): the field is parsed but not used for matching, so the step behaves as if it were absent. Usetext,id,width/heightwithtolerance, or relational selectors instead.css: for web apps only. Astra Scout runs Android and iOS flows.
For the commands that accept selectors, see the command reference.
