TestMesh
YAML ReferenceActions

browser

Automate web browsers using Chromium — navigate, click, type, extract content, and take screenshots.

The browser action drives a headless Chromium browser via the Chrome DevTools Protocol. Use it to test web UIs, scrape content, or automate interactions that require JavaScript execution.

- id: open_page
  action: browser
  config:
    action: navigate
    url: "https://app.example.com/login"
    timeout: "30s"
    headless: true

Configuration

FieldTypeRequiredDescription
actionstringyesBrowser sub-action (see below)
urlstringcontextTarget URL (required for navigate)
selectorstringcontextCSS selector for the target element
textstringcontextText to type or check
valuestringcontextValue to set
attributestringnoHTML attribute to read
scriptstringcontextJavaScript to evaluate
timeoutstringnoPer-action timeout (default: 30s)
headlessboolnoRun headless (default: true)
screenshotboolnoTake a screenshot after the action
full_pageboolnoFull-page screenshot (default: false)
wait_forstringnoCSS selector to wait for after the action
cookiesarraynoCookies to set before navigation
headersobjectnoExtra request headers
viewportobjectno{ width, height } in pixels

Sub-actions

All browser actions share the same action type (browser) and differ by the action field.

Navigate to a URL and wait for page load:

- id: go_to_login
  action: browser
  config:
    action: navigate
    url: "https://app.example.com/login"
    wait_for: "#login-form"
  output:
    title: "$.title"
    url: "$.url"

click

Click an element identified by a CSS selector:

- id: submit_form
  action: browser
  config:
    action: click
    selector: "button[type=submit]"
    wait_for: ".success-message"

type

Clear an input field and type text:

- id: enter_email
  action: browser
  config:
    action: type
    selector: "#email"
    text: "user@example.com"

get_text

Extract the text content of an element:

- id: read_message
  action: browser
  config:
    action: get_text
    selector: ".notification-banner"
  output:
    message: "$.text"

get_attribute

Read an HTML attribute from an element:

- id: get_href
  action: browser
  config:
    action: get_attribute
    selector: "a.download-link"
    attribute: "href"
  output:
    download_url: "$.attribute"

get_html

Get the outer HTML of an element:

- id: capture_table
  action: browser
  config:
    action: get_html
    selector: "#results-table"
  output:
    table_html: "$.html"

screenshot

Take a screenshot of the current page:

- id: capture_screen
  action: browser
  config:
    action: screenshot
    full_page: true
    screenshot: true
  output:
    image_base64: "$.screenshot"

The screenshot is returned as a base64-encoded PNG string.

evaluate

Execute arbitrary JavaScript in the page context:

- id: get_user_data
  action: browser
  config:
    action: evaluate
    script: "return window.__USER_DATA__"
  output:
    user: "$.eval_result"

The script return value must be JSON-serializable.

wait_for_selector

Wait until an element appears on the page (useful after navigation or AJAX):

- id: wait_for_results
  action: browser
  config:
    action: wait_for_selector
    selector: ".search-results"
    timeout: "10s"

select

Choose an option in a <select> dropdown:

- id: choose_country
  action: browser
  config:
    action: select
    selector: "#country"
    value: "US"

hover

Hover over an element (triggers hover states and tooltips):

- id: hover_menu
  action: browser
  config:
    action: hover
    selector: "#nav-menu"

Output Data

FieldTypeDescription
successboolWhether the action succeeded
actionstringThe sub-action that was executed
urlstringCurrent page URL
titlestringCurrent page title
textstringExtracted text content
valuestringExtracted value
attributestringExtracted attribute value
htmlstringExtracted HTML content
screenshotstringBase64-encoded PNG screenshot
eval_resultanyJavaScript evaluation result
cookiesarrayCurrent page cookies
duration_msintExecution time in milliseconds

Full Example: Login Flow

login-and-verify.yaml
flow:
  name: "Test Login Flow"

  steps:
    - id: navigate_to_login
      action: browser
      config:
        action: navigate
        url: "https://app.example.com/login"
        wait_for: "#login-form"
        viewport:
          width: 1440
          height: 900

    - id: enter_credentials
      action: browser
      config:
        action: type
        selector: "#email"
        text: "admin@example.com"

    - id: enter_password
      action: browser
      config:
        action: type
        selector: "#password"
        text: "secret123"

    - id: click_login
      action: browser
      config:
        action: click
        selector: "button[type=submit]"
        wait_for: ".dashboard"

    - id: verify_dashboard
      action: browser
      config:
        action: get_text
        selector: ".welcome-message"
      output:
        welcome_text: "$.text"

    - id: screenshot_dashboard
      action: browser
      config:
        action: screenshot
        full_page: false

  assert:
    - '"Welcome" in welcome_text'

Authentication with Cookies

Set cookies before navigating to skip a login form:

- id: authenticated_page
  action: browser
  config:
    action: navigate
    url: "https://app.example.com/dashboard"
    cookies:
      - name: "session"
        value: "${auth_cookie}"
        domain: "app.example.com"
        path: "/"

Custom Headers

Send extra HTTP headers on navigation requests:

- id: navigate_with_auth
  action: browser
  config:
    action: navigate
    url: "https://app.example.com/admin"
    headers:
      X-Internal-Token: "${internal_token}"
      Accept-Language: "en-US"

The browser action requires Chromium to be installed on the system running the TestMesh API. In Docker deployments, use the testmesh/api-with-chrome image which includes Chromium.


What's Next

On this page