Bỏ qua, đến nội dung

Lấy phần tử khớp cuối cùng ​

Chọn phần tử cuối cùng trong danh sách bằng index selector và JavaScript.

Trong một flow, nhắm vào một view cụ thể thường đơn giản nhờ index. Ví dụ, nếu muốn nút Add to Basket thứ ba, bạn chỉ cần dùng index: 2:

yaml
- tapOn:
    text: Add to Basket
    index: 2   # Mục thứ 3. Index bắt đầu từ 0

Nhưng với danh sách có số mục thay đổi, như giỏ hàng, chuỗi tin nhắn hay thư viện ảnh, bạn không biết trước mục cuối là số mấy. Dùng một subflow dùng lại được để tìm index của mục cuối, rồi chạm vào mục đó.

Quy trình ​

Astra Scout không có index: last, nên bạn tự tìm index cuối bằng cách thử lần lượt từng index. Logic là một vòng lặp:

  1. Bắt đầu từ index: 0.
  2. Kiểm tra phần tử có tồn tại ở index hiện tại không.
  3. Nếu có, tăng bộ đếm và kiểm tra index tiếp theo.
  4. Khi một index không hiện ra (not visible), index ngay trước đó là cái cuối cùng.

1. Flow tìm kiếm tái sử dụng ​

Tạo một subflow tiện ích (ví dụ utils/find_last_element.yaml) chứa toàn bộ vòng lặp. Subflow này tìm index cuối rồi trả về cho flow chính.

yaml
# utils/find_last_element.yaml
# Cách dùng: truyền SELECTOR_TYPE ("id" hoặc "text") và SELECTOR_VALUE
# Kết quả: index được lưu trong ${output.lastElementIndex}

# Bước 1: trước hết cần khởi tạo trạng thái tìm kiếm
- evalScript: ${output.lastElementIndex = -1}
- evalScript: ${output._findLastElement_complete = false}

# Bước 2: kiểm tra loại đầu vào để tránh lỗi
# Ví dụ này chỉ hỗ trợ selector "id" và "text"
- runFlow:
    when:
      true: ${SELECTOR_TYPE != "id" && SELECTOR_TYPE != "text"}
    commands:
      - evalScript: |
          throw new Error("Invalid SELECTOR_TYPE: " + SELECTOR_TYPE + ". Must be 'id' or 'text'");

# Bước 3: vòng lặp tìm kiếm
# Lặp cho đến khi gặp một index không tồn tại.
- repeat:
    while:
      true: ${!output._findLastElement_complete}
    commands:
      # Kiểm tra phần tử có tồn tại ở index hiện tại (selector id)
      - runFlow:
          when:
            true: ${SELECTOR_TYPE == "id"}
          commands:
            - runFlow:
                when:
                  visible:
                    id: "${SELECTOR_VALUE}"
                    index: ${output.lastElementIndex + 1}
                commands:
                   # Tìm thấy phần tử, cập nhật index và tiếp tục
                  - evalScript: ${output.lastElementIndex = output.lastElementIndex + 1}
            - runFlow:
                when:
                  notVisible:
                    id: "${SELECTOR_VALUE}"
                    index: ${output.lastElementIndex + 1}
                commands:
                  # Không thấy phần tử. Việc tìm kiếm kết thúc
                  - evalScript: ${output._findLastElement_complete = true}

      # Kiểm tra phần tử có tồn tại ở index hiện tại (selector text)
      - runFlow:
          when:
            true: ${SELECTOR_TYPE == "text"}
          commands:
            - runFlow:
                when:
                  visible:
                    text: "${SELECTOR_VALUE}"
                    index: ${output.lastElementIndex + 1}
                commands:
                  # Tìm thấy phần tử, cập nhật index và tiếp tục
                  - evalScript: ${output.lastElementIndex = output.lastElementIndex + 1}
            - runFlow:
                when:
                  notVisible:
                    text: "${SELECTOR_VALUE}"
                    index: ${output.lastElementIndex + 1}
                commands:
                  # Không thấy phần tử. Việc tìm kiếm kết thúc
                  - evalScript: ${output._findLastElement_complete = true}

# Bước 4: kiểm tra cuối cùng
- runFlow:
    when:
      true: ${output.lastElementIndex == -1}
    commands:
      - evalScript: |
          throw new Error("No elements found matching: " + SELECTOR_VALUE);

Về bản chất, subflow này thử lần lượt từng index cho đến khi hết (tìm tuyến tính), viết bằng YAML của flow. Các điểm chính:

  • Nó dùng biến output làm bộ đếm. Giá trị đặt bằng evalScript được giữ suốt lúc flow chạy, nên lần lặp sau dùng tiếp được index đã tăng.
  • repeat với điều kiện while dựa trên một cờ boolean (_findLastElement_complete, ban đầu là false) lặp cho đến khi hết danh sách, nên danh sách dài bao nhiêu cũng được.
  • Nếu vòng lặp kết thúc mà index vẫn là -1 (không tìm thấy phần tử nào), subflow báo một error rõ ràng và dừng, thay vì chạy tiếp với dữ liệu sai.

2. Triển khai ​

Gọi subflow bằng runFlow, rồi dùng ${output.lastElementIndex} ở command tiếp theo. Bạn cần truyền loại selector (id hoặc text) và giá trị của nó.

yaml
# main_test.yaml
# Tìm nút "Remove" cuối cùng trong giỏ hàng và chạm vào nó
- runFlow:
    file: ../utils/find_last_element.yaml
    env:
      SELECTOR_TYPE: "text"
      SELECTOR_VALUE: "Remove"

- tapOn:
    text: "Remove"
    index: ${output.lastElementIndex}

Các trang về những thành phần được dùng ở đây: