Skip to content

Step actions reference

Each English line you write becomes one action in this list. The parser maps natural language to one of these action keys; the executor (Playwright, under the hood) runs them. This page is the complete inventory.

Every step is a single key-value pair. The key is the action; the value is either a string (target text) or an object with a target and other fields:

- click: "Sign in button"
- type:
target: "email field"
text: "user@example.com"
- verifyVisible: "Welcome back"

Some actions accept aliases so multiple natural phrasings map to the same behavior — click and tapOn, type and inputText, verifyVisible and assertVisible. Use whichever reads more naturally.

Any action can take optional: true. If no visible element matches the target, the step is marked skipped instead of failed and the run continues. An element that is there but fails the step’s check (the wrong text, unchecked, another value) fails the step, optional or not, and so does a step that is not about an element at all, such as verifyUrl:

- click:
target: "Cookie banner accept"
optional: true

This is most useful for cookie banners, A/B-tested elements, and anything that may or may not be there.

Go to a URL. Waits for the page to finish loading.

- navigate: "https://example.com"

Navigate browser back one entry.

- back: true

Navigate browser forward one entry.

- goForward: true

Reload the current page.

- refresh: true

Open an app by URL. If the value isn’t an http(s):// URL, the step is a no-op (reserved for native-app contexts).

- launchApp: "https://app.example.com"

Click (or tap) an element. If the element is outside the viewport, the executor scrolls to find an in-viewport equivalent before clicking.

When several elements carry the name, the executor picks the one a person would mean: inside an open modal dialog first, then inside the newest open menu, list or popover, then the first visible, enabled control that nothing covers. An element with opacity: 0 (a hover-revealed row action) never counts as visible, and a control the page is still rendering is waited for briefly before the executor settles for plain text.

A click a person could not make fails and says why: the control is disabled, not visible, or covered by another element (a dialog’s backdrop, a cookie banner), which it names. The executor never clicks through a cover, so a green click means the control itself was clicked.

- click: "Sign in button"

Type into a field. With a target, fills the field it names: a field whose label, placeholder or accessible name is exactly the target first, then one whose name reads as the target as whole words — never a button or a heading that shares the words (see Locator resolution). A date field takes the value in its HTML format: YYYY-MM-DD for a date, HH:MM for a time. Without a target, fills the currently focused input — or the first visible input on the page as a fallback.

type fills a field the way a keyboard does: it does not check whether something covers the field (a dialog, an overlay), because a person can often reach such a field with Tab. So a green type does not mean the field could have been clicked; to check that, click the field first.

- type:
target: "email field"
text: "user@example.com"
- type: "user@example.com" # fills focused/first visible input

Clear a field. Same target rules as type.

- clear:
target: "search input"
- clear: true # clears focused/first visible input

Press a single key. Use Playwright key names (Enter, Escape, Tab, ArrowDown, etc.).

- pressKey: "Enter"

Click and hold for one second. Useful for context menus on mobile-style sites.

- longPress: "thumbnail image"

Double-click an element.

- doubleClick: "row item"

Right-click (context-menu click) an element.

- rightClick: "file in tree"

Move the pointer over an element without clicking.

- hover: "user avatar"

Scroll the page. Direction defaults to down.

- scroll: "down"
- scroll:
direction: "up"

Accepted values: down, up, left, right.

Pick an option from a <select> dropdown. With a target, picks from that specific dropdown; without, uses the first visible select on the page.

- selectOption:
target: "country dropdown"
value: "US"
- selectOption: "US"

Check a checkbox. No-op if it’s already checked.

A checkbox a person could not check fails and says why: it is disabled, not visible, or covered by another element (which it names), and nothing is clicked. One the page refuses to change fails as “Clicking the checkbox did not check it.” A styled checkbox whose real input sits under its own label — a toggle, a custom box — is checked the way a person does it, by clicking the label.

- check: "I agree to the terms"

Uncheck a checkbox. No-op if it’s already unchecked. It fails the same way as check when a person could not uncheck the box, or the page refuses.

- uncheck: "Subscribe to newsletter"

All assertions wait up to 10 seconds for the condition to become true before failing. There’s no per-step override flag.

A check needs something to compare. One with no expected URL, title, text or value, with no attribute name, or with a count that is not a whole number fails at once and says what it is missing; so does a check or a waitForElement that names no element. That failure is the test as written, not the site: its origin is configuration.

Assert an element (or text) is visible. A string target is read the way verifyText reads text — whole words and numbers, case and punctuation forgiven.

- verifyVisible: "Welcome back"
- verifyVisible:
target: "Sign out button"

Assert an element is not visible.

- verifyNotVisible: "Loading spinner"

Assert text a person can read. With elementType: "text" (or just a string), the text must be on the page as it is shown: text that exists only in the page source, in a hidden element, or in an option a closed <select> is not showing does not count. What a person reads in a form control does: a visible field’s placeholder or current value, and the option a visible <select> shows.

How the text is matched — the same in the cloud and on the local agent:

  • The phrase as it reads, ignoring case, spacing and punctuation between words. "Total 5 items" reads on a page that says Total: 5 items; "Go to cart" does not read on Go to the cart — a word in between is not punctuation.
  • A word or a number is never matched inside a longer one. "5 items" does not read on 15 items, "1" not on 1,000 or 1.5, "Log" not on Login, "Day 2" not on Day 21. A number’s own separators belong to it: "1,000" and "1 000" read whole.
  • Scripts written without spaces between words — Chinese, Japanese, Thai, Lao, Khmer, Myanmar — have no word edges, so part of a sentence reads: "ログイン" reads on ログインしてください.
  • An accent written as a separate combining mark belongs to its letter: "Cafe" is not Café.
  • Case is the page source’s, not what CSS shows: a heading written You’re on your trip and styled text-transform: uppercase reads as written. Write the text in the source’s case wherever a step compares case.
  • Only text a person can see counts. Not under display: none or visibility: hidden, not inside a box with no size that clips what overflows it (a collapsed panel), not inside a closed <details> (its <summary> does count), not an option a closed <select> is not showing. A dialog drawn over the page does count, wherever its markup sits. aria-hidden text does count: it hides text from screen readers, not from the eye.
  • verifyVisible checks what a sighted person sees. Visually hidden text — the sr-only recipe: a one-pixel clipped box, or a clip that cuts everything away — does not count, though a screen reader reads it. To check that something exists for a screen reader, target it by its accessible name (a click or a verify through the locator ladder) or use verifyAttribute.

For part of a word or a number, use verifyContainsText.

With a target and an elementType other than text, the cloud compares that element’s whole text with expected exactly, case included. (The local agent does not make that distinction yet; it reads the page as above.)

- verifyText:
target: "page heading"
elementType: "heading"
expected: "Dashboard"
- verifyText: "Welcome back"

Assert an element contains the given text — a substring, so part of a word or a number counts ("Log" is in Login, "5" is in 15). On an element the match is case-sensitive. Without an expected of its own, the target is looked for anywhere on the page as it is shown, case-insensitive.

- verifyContainsText:
target: "status message"
expected: "successfully"

Assert the value of an input matches.

- verifyValue:
target: "email input"
expected: "user@example.com"

Assert an HTML attribute equals an expected string.

- verifyAttribute:
target: "submit button"
attribute: "disabled"
expected: "true"

Assert the number of matching elements. With elementType: "checkbox" or "button", counts by ARIA role; otherwise by text match.

- verifyCount:
elementType: "checkbox"
count: 3
- verifyCount:
target: "row item"
count: 5

Assert a checkbox or radio is (or isn’t) checked.

- verifyChecked: "Remember me"
- verifyNotChecked: "Subscribe to newsletter"

Assert an interactive element is (or isn’t) enabled.

- verifyEnabled: "Submit button"
- verifyDisabled: "Submit button"

Assert an element currently has keyboard focus.

- verifyFocused: "search input"

Assert an element has no children or text.

- verifyEmpty: "empty cart message"

Assert the current page URL. A full URL (with https://) must match exactly; anything else — a path, a query parameter — must appear somewhere in the URL, which is what you want after a redirect that carries state you did not choose. A failure names both the expected value and the actual URL.

- verifyUrl: "https://example.com/dashboard" # exact
- verifyUrl: "/dashboard" # contained
- verifyUrl: "next=/new" # a query parameter, contained

Assert the document title matches.

- verifyTitle: "Dashboard — Example"

Pause execution unconditionally. Defaults to 2 seconds if no value given; capped at 600 seconds (10 minutes) — a capped wait is recorded in the step log so the report shows what happened.

- wait: 5
- wait:
seconds: 180 # "wait for 3 minutes" parses to this — always seconds

In plain English, units convert automatically: “wait 3 minutes” becomes wait: 180. Use fixed pauses sparingly — every assertion already auto-waits up to 10 seconds, and for slow backend jobs waitForElement with a budget (below) is faster and clearer.

Wait for the network to go idle (no requests for 500ms). Times out at 15 seconds and continues without failing — the run keeps going either way.

- waitForLoad: true

Wait for an element matching the given text to become visible — the preferred way to handle slow operations. Default timeout 10 seconds, override per-step (also capped at 10 minutes). The step finishes the moment the text appears and fails with a clear reason if it never does.

In plain English: “Click Generate and wait until ‘Report ready’ appears, up to 3 minutes” — the max wait lands in the step’s value as seconds. In the manual editor this is Wait until text appears.

- waitForElement: "Dashboard"
- waitForElement:
target: "Report ready"
timeout: 180000 # milliseconds — 3 minutes

Capture a screenshot and compare it with the test’s baseline — see Visual regression. With a target, captures just that element; without, captures what is in view (the viewport), not the whole scrollable page.

Visual checks run in the cloud only. On the local agent a screenshot step fails with Visual checks run in the cloud only: there is no baseline to compare with, and a check that compares nothing is not a pass.

- screenshot: true # full page
- screenshot:
target: "search input"
elementType: "input" # element-only

When the test runs in visual regression mode with a saved baseline, the screenshot is compared against the baseline using a vision model. See Visual regression for the comparison mechanics.

Screenshot steps respect optional: true — if no visible element matches the target, the step is skipped, not failed.

A few actions accept multiple keys for readability. They’re identical:

CanonicalAlias
clicktapOn
typeinputText
clearclearText
verifyVisibleassertVisible
verifyNotVisibleassertNotVisible
screenshottakeScreenshot
navigateopenLink
scrollswipe