Targets and waits
How a step finds its element, how to wait for a result, and how to list the targets a page offers instead of guessing them.
Targets#
A target is the element a step acts on. Prefer what a user sees:
| Form | Finds |
|---|---|
New project | the element whose visible text is "New project" |
{ role: button, name: Create } | an element by ARIA role and accessible name |
{ label: Owner email } | a form field by its label (or aria-label, or placeholder) |
{ testid: save } | data-testid="save" |
{ css: "#project-30 a" } | a CSS selector: the escape hatch |
Every target finds its first match. When the same text appears many times (thirty "Open" links in a list), name the one you mean another way, such as a CSS selector from an element with an id.
title: Open a project
browser:
url: http://localhost:5173
viewport: 1280x800
speed: auto
script:
- goto: /
- scroll: { to: { css: "#project-30" } }
- click: { css: "#project-30 a" } # the "Open" link of project 30
id: open
- wait: { text: Project details }
pause: 1Waits#
| Step | Waits until |
|---|---|
wait: { text: Saved } | the text is on the page |
wait: { css: ".toast" } | an element matches |
wait: { text: Loading…, gone: true } | it is gone |
wait: { js: "window.app.ready" } | a JavaScript expression is true (it may use await) |
wait: 2 | two seconds, only when nothing better exists |
Long waits are fine: speed: auto compresses them in the video, with a "⏩ 4×" badge.
The targets command#
Capture records, after each step, the elements on screen and the targets that find them. Each was
checked in the page with the same lookups the capture uses. targets lists them:
browser-clip targets open-project.yaml --after 2after step 2 (scroll) · 1.862 s · 30 elements
text span "Project 29" Project 29 · { css: "#project-29 span" }
control a "Open" { css: "#project-29 a" }
text span "Project 30" Project 30 · { css: "#project-30 span" }
control a "Open" { css: "#project-30 a" }
…Each line is an element, then its targets, best first: "Open" is in every row, so for the links only a CSS selector finds the one you mean.
The best target comes first. --json prints everything, boxes included; agents use it to write the
next step. In the studio, the picker does the same with a click on the
preview.
When a step fails#
The take stops at the first step that fails, and the message says why:
target not actionable (covered): something lies over the element (a dialog, a cookie banner);target not actionable (moving): it was still animating;wait timed out after 10 s: the text never showed, or showed differently;cannot load http://…: the server is not running.
Raise timeout on the step, or fix the wait before it.
Source: docs-src/pages/tutorial/02-targets.md · browser-clip 0.1.0