TestMesh
YAML ReferenceActions

Utility Actions

delay, log, wait_for, and db_poll — actions for timing, output, and polling.

Utility actions handle timing control, logging, and polling patterns that don't fit a specific protocol.


delay

Pauses execution for a fixed duration. Useful for introducing wait time between steps when polling isn't appropriate, or simulating think time.

- id: wait_for_processing
  action: delay
  config:
    duration: "2s"

Configuration

FieldTypeRequiredDescription
durationstringyesHow long to wait. Accepts Go duration format: 100ms, 2s, 1m, 1h30m

Output

FieldTypeDescription
durationstringThe duration string that was used
duration_msintEquivalent in milliseconds
completedboolAlways true

Example

flow:
  name: "Wait for async job"
  steps:
    - id: trigger_job
      action: http_request
      config:
        method: POST
        url: "${BASE_URL}/jobs"
        body:
          type: "report_generation"
      output:
        job_id: "$.body.id"

    - id: wait_for_job
      action: delay
      config:
        duration: "5s"

    - id: check_job_status
      action: http_request
      config:
        method: GET
        url: "${BASE_URL}/jobs/${trigger_job.job_id}"
      assert:
        - 'body.status == "completed"'

Prefer wait_for over delay when you have a condition to check — it polls until the condition is met rather than waiting a fixed amount of time.


log

Writes a message to the execution log. Useful for annotating test output, recording intermediate values, and making long flows easier to follow.

- id: log_user_id
  action: log
  config:
    message: "Created user with ID: ${create_user.body.id}"
    level: "info"

Configuration

FieldTypeRequiredDescription
messagestringyesThe message to log. Supports ${variable} interpolation.
levelstringnoLog level: debug, info, warn, error (default: info)

Example

steps:
  - id: note_phase
    action: log
    config:
      message: "--- Phase 2: Verifying order fulfillment ---"

  - id: warn_on_retry
    action: log
    config:
      message: "Retrying after rate limit: attempt ${retry_count}"
      level: "warn"

Log messages appear in the execution log visible in the dashboard and CLI output.


wait_for

Polls a condition repeatedly until it is satisfied or the timeout is reached. More efficient and reliable than a fixed delay when waiting for a service to become ready or an async operation to complete.

- id: wait_for_service
  action: wait_for
  config:
    type: http
    url: "http://my-service/health"
    status_code: 200
    timeout: "30s"
    interval: "1s"

Configuration

FieldTypeRequiredDescription
typestringyesWhat to poll: http or tcp
timeoutstringnoMax total wait time (default: 30s)
intervalstringnoTime between attempts (default: 1s)
max_attemptsintnoMax number of attempts (overrides timeout)

HTTP-specific fields

FieldTypeDescription
urlstringURL to poll
methodstringHTTP method (default: GET)
headersobjectRequest headers
status_codeintExpected HTTP status code
body_containsstringString that must appear in the response body
json_pathstringJSONPath expression to evaluate
json_valueanyExpected value at the JSONPath

TCP-specific fields

FieldTypeDescription
hoststringHostname or IP
portintTCP port number

Examples

Wait for a service to become healthy:

- id: wait_for_api
  action: wait_for
  config:
    type: http
    url: "http://user-service:5001/health"
    status_code: 200
    timeout: "60s"
    interval: "2s"

Wait for a specific JSON value:

- id: wait_for_job_complete
  action: wait_for
  config:
    type: http
    url: "${BASE_URL}/jobs/${job_id}"
    json_path: "$.status"
    json_value: "completed"
    timeout: "2m"
    interval: "5s"

Wait for a TCP port to open:

- id: wait_for_postgres
  action: wait_for
  config:
    type: tcp
    host: "postgres"
    port: 5432
    timeout: "30s"
    interval: "500ms"

Combining with docker_run to start a dependency:

steps:
  - id: start_db
    action: docker_run
    config:
      image: "postgres:15"
      env:
        POSTGRES_PASSWORD: "test"
      ports:
        - "5432:5432"
    output:
      container_id: "$.container_id"

  - id: wait_for_db
    action: wait_for
    config:
      type: tcp
      host: "localhost"
      port: 5432
      timeout: "30s"

db_poll

Like wait_for, but polls a database query instead of an HTTP endpoint. Retries until the query returns the expected result or the timeout is reached.

- id: wait_for_record
  action: db_poll
  config:
    connection_string: "postgres://user:pass@localhost/testdb"
    query: "SELECT status FROM orders WHERE id = $1"
    params:
      - "${order_id}"
    expected_value: "shipped"
    column: "status"
    timeout: "60s"
    interval: "2s"

Configuration

FieldTypeRequiredDescription
connection_stringstringyesPostgreSQL connection string
querystringyesSQL query to execute
paramsarraynoQuery parameters (avoid SQL injection)
expected_valueanyyesValue to wait for
columnstringnoColumn to check (default: first column)
timeoutstringnoMax total wait time (default: 30s)
intervalstringnoTime between retries (default: 1s)
max_attemptsintnoMax retry count

Example: Waiting for Kafka-driven processing

flow:
  name: "Order Processing via Kafka"

  steps:
    - id: publish_order
      action: kafka_producer
      config:
        brokers: ["kafka:9092"]
        topic: "orders"
        value:
          id: "order-123"
          amount: 99.99

    - id: wait_for_order_record
      action: db_poll
      config:
        connection_string: "${DB_URL}"
        query: "SELECT status FROM orders WHERE external_id = $1"
        params: ["order-123"]
        expected_value: "processed"
        column: "status"
        timeout: "30s"
        interval: "2s"

    - id: verify_status
      action: database_query
      config:
        connection_string: "${DB_URL}"
        query: "SELECT * FROM orders WHERE external_id = $1"
        params: ["order-123"]
      assert:
        - 'rows[0].status == "processed"'
        - 'rows[0].amount == 99.99'

What's Next

On this page