Skip to content

Element targets

A step that acts on an element (click, type, assert…) carries a target that says how to find it. A target is not one selector. It is an ordered list of strategies, plus an optional scope and a fingerprint.

"target": {
"scope": { "within": { "role": "row", "key": "{{poNumber}}" } },
"strategies": [
{ "kind": "testId", "value": "save-po" },
{ "kind": "role", "role": "button", "name": "Save" },
{ "kind": "css", "value": "#btn_save_123" }
]
}
Kind Finds the element by Example Durability
testId its data-testid attribute save-po Excellent, if the developers add test ids
role ARIA role + accessible name role button, name Save Very good. Survives redesigns.
label the text of its form label Username Very good for form fields
placeholder placeholder text Search… Good
altText image alt text Company logo Good
title its title attribute Close Good
text its visible text Approved Fair. Text changes with wording and language.
css a CSS selector #btn_save_123 Depends: stable ids are good, generated ones are poor
xpath an XPath //*[@id="po-form"]/div[2]/button Poor. Breaks on layout changes.

role, label and text accept exact (whole-string match). text, css and xpath accept nth (which match to use when several match, 0-based).

Strategy values are matched literally. {{…}} is not substituted in them. To find something by a variable value, use the scope’s row key (below).

  1. Strategies are tried in order.
  2. The first strategy gets the step’s whole timeout to appear, because it is expected to work.
  3. If it finds nothing, each fallback is probed briefly (up to 1.5 seconds).
  4. If the target has a fingerprint, extra strategies derived from it are tried after the authored ones.
  5. The element is looked for in the recorded frame first, then in every other frame on the page, since applications move content between iframes.
  6. When a strategy matches several elements:
    • an explicit nth decides,
    • otherwise, if exactly one of them is visible, that one is used,
    • otherwise the strategy counts as failed and the next one is tried. AutoTestX never silently takes the first match, because that is how a test clicks Delete on the wrong row.
  7. If nothing resolves, the step fails with, for example: No strategy resolved to a usable element in the page or any of its 0 frame(s). Tried: label=“Username” -> 0. Each strategy is listed with how many elements it matched.

A step is primary when the first strategy found the element in its recorded frame. Anything else is degraded: a fallback strategy, or the element found in another frame.

A degraded step still passes, but it is reported as warned, shows Fallback locator in the run report, and the test appears as drifting on the dashboard.

Drift is the early warning that the application changed. Fix it while the test still passes:

  1. Open the run report and see which strategy worked.
  2. Use Pick to refresh the target, or reorder the strategies so the working one is first.

A scope narrows where strategies search.

Scope Meaning
frame Path of frame selectors from the top document, for elements inside iframes. Filled by the recorder and Pick.
within.role + within.key A container with that role (usually row) whose text contains the key. The key is a template: {{poNumber}}, {{data.vendor_name}}.
within.selector A CSS selector for the container
within.testId A container by test id

Find grid rows by business key, never by index. “The row containing PO-102938” survives sorting, paging and new rows. “Row 3” does not. In the editor, use Scope to a container: role row, key {{poNumber}}.

When an element is recorded, picked, or found during a run, AutoTestX stores a fingerprint: role, accessible name, label, placeholder, input type, attributes, tag, own and nearby text, nearest heading, ancestor chain, landmark, an XPath anchored at the nearest unique id, frame path, position and size, and how many elements each strategy matched at the time.

The fingerprint:

  • supplies extra fallback strategies at run time,
  • records when the target was last verified, and by which run,
  • is the “last known good” state that future self-healing will compare against.

It is captured before the action, so a click that navigates away still has one.

  • First choice: testId if the application has test ids, else role + name, else label for form fields.
  • The recorder, by request of teams whose applications have stable ids but little accessible markup, orders them: unique id → unique name → id-anchored XPath → semantic strategies. Reorder them if your application is different.
  • Always keep at least one fallback. A single-strategy target fails outright instead of degrading.
  • Avoid nth and absolute XPaths unless nothing else identifies the element.