Statement Types
| Type | Syntax | Description |
|---|---|---|
ACTION (action:) | - intent: Enter email + action: input_text | Fast replay with AI self-healing fallback |
ACTION (js:) | - intent: Click login + js: "await ..." | Fast replay (Playwright code) with AI self-healing |
| VERIFY | - VERIFY: page shows welcome message | AI assertion, optional js: cache |
| DRAFT | - intent: Click the login button | AI resolves at runtime (~5-10s) |
| URL | - URL: /path | Navigation shorthand |
| Code | - description: ... + js: await request.get(...) | Inline Playwright code (no self-healing) |
| STEP | - STEP: Login + statements: [...] | Group related actions |
| IF/ELSE | - IF: cookie banner is visible + THEN: [...] | Conditional execution |
| WHILE | - WHILE: more items to load + DO: [...] | Repeat until condition |
| Function | - call: "file#export" + args: [...] | Call custom TypeScript function |
| Template | - template: ./path.yaml | Inline reusable statement flow |
IF/ELSE and WHILE are covered in Conditionals & Loops; functions and templates have their own pages.
VERIFY
Asserts a condition using AI. Use the VERIFY: shorthand (unquoted key):
statements:
- VERIFY: The success message is displayed
- VERIFY: The order total is $49.99
js: "await expect(page.getByTestId('order-total')).toHaveText('$49.99')"The js: cache speeds up simple checks. If the js: assertion fails, it automatically falls back to AI verification using the natural language statement.
ACTION
Fast deterministic replay (<1s) with AI self-healing fallback. Use the structured action: form for all supported actions:
statements:
- intent: Type email address
action: input_text
text: "{{USER_EMAIL}}"
locator: "getByLabel('Email')"intent describes what the step should accomplish in natural language; the action:/locator: field is a cache for fast replay. When the cache fails (e.g., a locator becomes stale), Shiplight's agentic layer falls back to the intent to self-heal.
For complex interactions that don't map to a supported action (e.g., drag-and-drop), use the description: + js: code step — but note raw JS does not self-heal:
statements:
- description: Drag the card to the Done column
js: |
const card = page.getByText('My Task');
const target = page.getByTestId('column-done');
await card.dragTo(target);STEP (grouping)
Groups related statements under a label.
statements:
- STEP: Fill in the registration form
statements:
- intent: Type "John" in the first name field
- intent: Type "Doe" in the last name field
- intent: Type "john@example.com" in the email fieldFrames
For elements inside iframes, use frame_path with action: form:
- intent: Click Hello inside iframe
action: click
frame_path:
- "iframe#main"
locator: "getByText('Hello')"