Bỏ qua, đến nội dung

Selectors ​

Xác định phần tử UI bằng selector cơ bản, quan hệ và trạng thái trên Android và iOS.

Selector cho Astra Scout biết command cần tác động lên phần tử nào trên màn hình, ví dụ phần tử để tapOn, assertVisible, copyTextFrom hoặc scrollUntilVisible.

Để tìm phần tử, Astra Scout đọc accessibility tree của device. Đó là danh sách các phần tử mà hệ điều hành mô tả cho công cụ hỗ trợ như VoiceOver, kèm chữ, ID và vị trí của từng phần tử. Vì vậy selector khớp với những gì người dùng thấy hoặc những gì developer đã gắn nhãn trong app.

Astra Scout hỗ trợ các trường selector sau trên Android và iOS. Bạn viết selector trong flow YAML.

Hỗ trợ trong một bảng ​

SelectorAndroidiOSGhi chú
textCóCóKhớp theo regex, phải khớp toàn bộ chuỗi.
idCóCóKhớp theo regex.
indexCóCóĐánh số từ 0.
pointCóCóTọa độ, dùng cho tapOn và các command tương tự.
above, below, leftOf, rightOfCóCóVị trí so với một phần tử mốc.
childOf, containsChild, containsDescendantsCóCóQuan hệ trong cây phân cấp.
enabled, selected, focusedCóCóTrạng thái boolean.
checkedCóKhôngBị bỏ qua trên iOS kèm warning.
width, height, toleranceCóCóKích thước theo pixel do accessibility tree báo cáo.
traitsKhôngKhôngBị bỏ qua. Xem Không hỗ trợ.
cssKhôngKhôngChỉ dành cho web. Astra Scout không chạy flow web.

Nếu flow dùng một trường mà nền tảng hiện tại không hỗ trợ, Astra Scout bỏ qua trường đó và ghi warning vào log của run, ví dụ "checked" is not supported on ios. Step vẫn chạy với các trường còn lại, nên có thể chọn nhầm phần tử.

Core selectors ​

Regex

text và id được hiểu là regex (biểu thức chính quy): một mẫu mô tả chuỗi chữ, ví dụ .* là "bất kỳ ký tự nào, bất kỳ số lần nào". Dùng regex để khớp chữ thay đổi, như Welcome back, .*. Nếu chữ cần tìm có ký tự đặc biệt như $, [ hoặc (, đặt dấu gạch chéo ngược (\) trước nó, ví dụ \$99.

Đặc thù theo nền tảng

  • Flutter: dùng text hiển thị hoặc Semantics Label cho text, Semantics Identifier cho id. Astra Scout không hỗ trợ Key của Flutter.
  • Android Compose: thêm Modifier.semantics { testTagsAsResourceId = true } để test tag dùng được như id.

text ​

Selector text tìm phần tử theo chữ hiển thị trên màn hình. Trên Android, chữ này gồm cả contentDescription; trên iOS gồm cả accessibilityLabel (nhãn mô tả mà developer gắn cho phần tử).

  • Luôn là regex: mọi text đều được hiểu là regex và phải khớp toàn bộ chữ của phần tử.
  • Viết tắt: bỏ key text và truyền thẳng chuỗi cho các command như tapOn hoặc assertVisible.
yaml
- tapOn: Login              # Viết tắt (khớp đúng chữ "Login")
- tapOn:
    text: ".*Continue.*"    # Regex, khớp phần tử có chữ chứa "Continue"
- assertVisible: Submit     # Viết tắt để kiểm tra hiển thị

id ​

Selector id nhắm tới mã định danh mà developer gắn cho một view. Nên dùng cho nội dung thay đổi, icon không có chữ, và app đa ngôn ngữ (chữ hiển thị đổi theo ngôn ngữ).

  • Android: là resource ID.
  • iOS: là accessibilityIdentifier.
yaml
- tapOn:
    id: login_button
- assertVisible:
    id: header_icon

index ​

Khi nhiều phần tử khớp cùng tiêu chí (ví dụ ba nút Add to Cart trên một màn hình), index chọn một trong số đó. Index đánh số từ 0.

yaml
# Chạm vào phần tử thứ ba có ID "buy_button"
- tapOn:
    id: buy_button
    index: 2

point ​

Selector point nhắm tới một tọa độ trên màn hình. Dùng cho phần tử không có trong accessibility tree, hoặc để chạm một vùng cụ thể của view lớn.

  • Vị trí tương đối: phần trăm, ví dụ "50%, 50%" cho tâm màn hình.
  • Tọa độ tuyệt đối: pixel chính xác, ví dụ "100, 200".
yaml
- tapOn:
    point: "50%, 50%"   # Chạm vào tâm màn hình
- tapOn:
    point: "100, 250"   # Chạm cách mép trái 100 pixel, cách mép trên 250

Relational selectors ​

Relational selector tìm một view theo vị trí hoặc quan hệ với view khác. Dùng khi nhiều phần tử có tên giống nhau (như nhiều nút "Buy"), hoặc phần tử không có text hay id ổn định nhưng luôn nằm gần một phần tử mốc đã biết.

SelectorMô tả
aboveKhớp view nằm phía trên phần tử mốc theo chiều dọc.
belowKhớp view nằm phía dưới phần tử mốc theo chiều dọc.
leftOfKhớp view nằm bên trái phần tử mốc.
rightOfKhớp view nằm bên phải phần tử mốc.
containsChildKhớp phần tử cha có một phần tử con trực tiếp khớp tiêu chí đã cho.
childOfKhớp phần tử là con trực tiếp của phần tử cha đã cho.
containsDescendantsKhớp view chứa tất cả các phần tử con, cháu đã cho, ở mọi độ sâu.

Mẹo sử dụng

  • Kết hợp nhiều trường: các selector vị trí (above, below, leftOf, rightOf) so sánh theo tọa độ trên màn hình. leftOf chỉ có nghĩa là "nằm bên trái", không nhất thiết sát cạnh hay thẳng hàng với phần tử mốc. Kết hợp với id, text, enabled... để chọn chính xác hơn: tapOn: { id: "icon", rightOf: "Settings", enabled: true }.
  • Chọn mốc ổn định: dùng phần tử ít thay đổi nhất làm mốc, thường là chữ cố định hoặc ID duy nhất.

Alignment selectors ​

above và below khớp các view nằm phía trên hoặc phía dưới một phần tử tham chiếu:

yaml
# Chạm vào view nằm dưới nhãn "Email"
- tapOn:
    below: Email

# Chạm vào view nằm trên tiêu đề "Checkout"
- tapOn:
    above: Checkout

leftOf và rightOf khớp các view nằm cạnh nhau, ví dụ icon bên cạnh nhãn:

yaml
# Chạm vào view bên phải một ô nhập liệu
- tapOn:
    rightOf:
      id: input_text

# Chạm vào view bên trái một cụm từ cụ thể
- tapOn:
    leftOf: I agree to the terms

Bạn có thể lồng above hoặc below để kiểm tra thứ tự theo chiều dọc:

yaml
- assertVisible:
    text: Top Thing
    above:
      text: Middle Thing
      above:
        text: Bottom Thing

Quan hệ cha - con ​

Các selector này dựa vào quan hệ cha - con trong accessibility tree, không dựa vào vị trí trên màn hình.

containsChild (chỉ con trực tiếp) ​

Khớp phần tử cha có một phần tử con trực tiếp khớp selector đã cho.

yaml
# Chạm vào container chứa trực tiếp text "Order 12345"
- tapOn:
    containsChild:
      text: Order 12345

childOf (chỉ cha trực tiếp) ​

Khớp phần tử là con trực tiếp của một phần tử cha cụ thể. Hữu ích khi cùng một phần tử con xuất hiện trong nhiều container.

yaml
# Chạm vào nút Delete bên trong Basket
- tapOn:
    text: Delete
    childOf:
      id: basket_container

containsDescendants ​

Khớp view chứa tất cả các phần tử con, cháu đã chỉ định ở mọi độ sâu, không chỉ con trực tiếp. Dùng cho card, hàng danh sách và các nhóm có nhiều phần tử lồng bên trong.

yaml
# Tìm một mục trong danh sách chứa cả tên sản phẩm và giá
- assertVisible:
    id: list_item
    containsDescendants:
      - text: Wireless Headphones
      - text: $99.99

State selectors ​

State selector lọc phần tử theo trạng thái hiện tại. Dùng để kiểm tra phần tử đã sẵn sàng, thao tác trước đã làm nó đổi trạng thái, hoặc chọn một phần tử trong nhiều phần tử giống nhau (ví dụ tab đang được chọn). Giá trị luôn là true hoặc false.

SelectorAndroidiOSMô tả
enabledCóCóPhần tử bấm được, hay đang bị làm mờ.
selectedCóCóPhần tử đang được chọn (tab, segmented control).
focusedCóCóPhần tử đang nhận bàn phím.
checkedCóKhôngTrạng thái bật/tắt của checkbox, radio button và switch.

Mẹo sử dụng

State selector hoạt động tốt nhất khi kết hợp với core selector, ví dụ tapOn: { text: "Next", enabled: true }.

yaml
# Kiểm tra nút đăng nhập ban đầu đang bị vô hiệu hóa
- assertVisible:
    id: login_button
    enabled: false

# Chạm vào nút khi nó đã active
- tapOn:
    id: login_button
    enabled: true

# Xác nhận ô tìm kiếm đang có focus
- assertVisible:
    id: search_input
    focused: true

# Chỉ tìm tab Profile nếu nó đang được chọn
- tapOn:
    text: Profile
    selected: true

Trên Android, checked hoạt động với checkbox, radio button và switch:

yaml
- assertVisible:
    id: remember_me_checkbox
    checked: true

Lưu ý

checked không hỗ trợ trên iOS. Trường này bị bỏ qua kèm warning, nên step khớp dù đang bật hay tắt. Trên iOS, kiểm tra chữ hoặc giá trị hiển thị của phần tử.

Dimension matchers ​

Dimension selector khớp phần tử theo kích thước trên màn hình, tính bằng pixel.

SelectorMô tả
widthKhớp phần tử có chiều rộng cụ thể theo pixel.
heightKhớp phần tử có chiều cao cụ thể theo pixel.
toleranceCho phép chênh lệch nhỏ do render hoặc làm tròn khi khớp kích thước.

Mẹo sử dụng

Kích thước pixel cố định dễ sai khi flow chạy trên device có độ phân giải khác nhau. Kết hợp width, height với selector khác và đặt tolerance đủ rộng.

width và height khớp theo kích thước (pixel) mà accessibility tree báo về:

yaml
# Chạm vào nút rộng đúng 200px
- tapOn:
    id: action_button
    width: 200

# Kiểm tra header hồ sơ cao 350px
- assertVisible:
    id: profile_header
    height: 350

tolerance cho phép sai lệch một chút, vì nút 100px có thể báo 99px hoặc 101px tùy tỷ lệ scale của màn hình. Với tolerance: 5, phần tử có kích thước lệch không quá 5 pixel so với giá trị bạn ghi đều khớp.

yaml
# Khớp icon vuông 48px, chừa 2px sai lệch
- assertVisible:
    id: settings_icon
    width: 48
    height: 48
    tolerance: 2

Không hỗ trợ ​

Hai trường selector sau không dùng được trong Astra Scout:

  • traits (text, long-text, square): Astra Scout bỏ qua trường này, nên step chạy như thể không có nó. Dùng text, id, width/height kèm tolerance, hoặc relational selector.
  • css: chỉ dành cho web. Astra Scout chạy flow Android và iOS.

Danh sách command nhận selector nằm ở tham chiếu command.