Skip to content

Statement Types

TypeSyntaxDescription
ACTION (action:)- intent: Enter email + action: input_textFast 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 messageAI assertion, optional js: cache
DRAFT- intent: Click the login buttonAI resolves at runtime (~5-10s)
URL- URL: /pathNavigation 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.yamlInline 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):

yaml
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:

yaml
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:

yaml
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.

yaml
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 field

Frames

For elements inside iframes, use frame_path with action: form:

yaml
- intent: Click Hello inside iframe
  action: click
  frame_path:
    - "iframe#main"
  locator: "getByText('Hello')"

Released under the MIT License.