Get the last matching element
Select the last element in a list using index selectors and JavaScript.
In a flow, targeting a specific view is usually straightforward using indexes. For example, if you want the third Add to Basket button, you simply use index: 2 :
- tapOn:
text: Add to Basket
index: 2 # 3rd item. Indexes start at 0But in a list whose size changes, like a shopping cart, a message thread, or a photo gallery, you do not know the number of the last item in advance. Use a reusable subflow that finds the index of the last item, then taps it.
The workflow
Astra Scout has no index: last, so you find the last index by trying each index in turn. The logic is a loop:
- Start at
index: 0. - Check if the element exists at the current index.
- If it exists, increment the counter and check the next
index. - When an
indexis not visible, the index right before it is the last one.
1. Reusable discovery Flow
Create a utility subflow (e.g., utils/find_last_element.yaml) that holds the whole loop. It finds the last index and returns it to your main flow.
# utils/find_last_element.yaml
# Usage: Pass SELECTOR_TYPE ("id" or "text") and SELECTOR_VALUE
# Result: The index is stored in ${output.lastElementIndex}
# Step 1: First, it's necessary to initialize the search state
- evalScript: ${output.lastElementIndex = -1}
- evalScript: ${output._findLastElement_complete = false}
# Step 2: Validate the input type to avoid failures
# Only "id" and "text" selector are supported in this example
- runFlow:
when:
true: ${SELECTOR_TYPE != "id" && SELECTOR_TYPE != "text"}
commands:
- evalScript: |
throw new Error("Invalid SELECTOR_TYPE: " + SELECTOR_TYPE + ". Must be 'id' or 'text'");
# Step 3: The Discovery Loop
# Repeat this until you hit an index that doesn't exist.
- repeat:
while:
true: ${!output._findLastElement_complete}
commands:
# Check if element exists at current index (id selector)
- runFlow:
when:
true: ${SELECTOR_TYPE == "id"}
commands:
- runFlow:
when:
visible:
id: "${SELECTOR_VALUE}"
index: ${output.lastElementIndex + 1}
commands:
# Element found, update index and continue
- evalScript: ${output.lastElementIndex = output.lastElementIndex + 1}
- runFlow:
when:
notVisible:
id: "${SELECTOR_VALUE}"
index: ${output.lastElementIndex + 1}
commands:
# Element not found. The search is done
- evalScript: ${output._findLastElement_complete = true}
# Check if element exists at current index (text selector)
- runFlow:
when:
true: ${SELECTOR_TYPE == "text"}
commands:
- runFlow:
when:
visible:
text: "${SELECTOR_VALUE}"
index: ${output.lastElementIndex + 1}
commands:
# Element found, update index and continue
- evalScript: ${output.lastElementIndex = output.lastElementIndex + 1}
- runFlow:
when:
notVisible:
text: "${SELECTOR_VALUE}"
index: ${output.lastElementIndex + 1}
commands:
# Element not found. The search is done
- evalScript: ${output._findLastElement_complete = true}
# Step 4: Final Validation
- runFlow:
when:
true: ${output.lastElementIndex == -1}
commands:
- evalScript: |
throw new Error("No elements found matching: " + SELECTOR_VALUE);In essence, this subflow tries each index in turn until none is left (a linear search), written in flow YAML. The key points:
- It uses an
outputvariable as a counter. A value set withevalScriptis kept while the flow runs, so the next loop iteration continues from the increased index. repeatwith awhilecondition based on a boolean flag (_findLastElement_complete,falseat first) loops until the list ends, so the list can be any length.- If the loop ends and the index is still
-1(no element was found), the subflow reports a clear error and stops, instead of continuing with wrong data.
2. Implementation
Call the subflow with runFlow, then use ${output.lastElementIndex} in the next command. Pass the selector type (id or text) and its value.
# main_test.yaml
# Find the last "Remove" button in a shopping cart and tap it
- runFlow:
file: ../utils/find_last_element.yaml
env:
SELECTOR_TYPE: "text"
SELECTOR_VALUE: "Remove"
- tapOn:
text: "Remove"
index: ${output.lastElementIndex}Related content
Pages about the building blocks used here:
- Loops: Learn the different ways to iterate in a flow, including
whileloops and count-based loops. - JavaScript overview: Discover how to use JavaScript to manage complex state and logic within your YAML files.
- How to use Selectors: Review the fundamentals of how Astra Scout identifies and differentiates between similar UI elements.
