Skip to content

Step Actions Reference

Each step in a QA plan performs one of two action types: http_request or browser. The AI agent selects and configures these actions when building QA plans via MCP tools. This page documents the full configuration schema for both.

The http_request action sends an HTTP request and validates the response.

FieldTypeRequiredDescription
methodstringYesHTTP method: GET, POST, PUT, PATCH, DELETE, etc.
urlstringYesThe request URL. Supports template variables (e.g., {{base_url}}/api/users).
headersRecord<string, string>NoRequest headers as key-value pairs. Values support template variables.
bodyanyNoThe request body. Objects are serialized as JSON. Supports template variables in string values.
timeoutnumberNoRequest timeout in milliseconds.
pollPollConfigNoPoll the endpoint until a condition is met.

Some API endpoints require polling — repeating a request until a condition is met. When poll is specified, the request is repeated at a fixed interval until the until condition is satisfied or the timeout is reached.

FieldTypeRequiredDescription
untilobjectYesThe condition to check. Must specify one of the sub-fields below.
until.status_codenumberNoPoll until the response status code matches this value.
until.json_pathobjectNoPoll until a JSON path in the response body matches. Contains path (string) and expected (any).
interval_msnumberYesMilliseconds to wait between each poll request.
timeout_msnumberYesMaximum total time in milliseconds before the poll is considered failed.

Polling example — wait for an async job to complete:

{
"action": "http_request",
"config": {
"method": "GET",
"url": "{{api_base_url}}/jobs/{{job_id}}"
},
"poll": {
"until": {
"json_path": "$.status",
"equals": "completed"
},
"interval_ms": 2000,
"timeout_ms": 60000
}
}

The extract field captures values from the HTTP response for use in subsequent steps. Each extraction uses a JSONPath expression to locate the value in the response body. Extracted values become template variables accessible via {{variable_name}}.

{
"extract": {
"user_id": "$.data.id",
"user_name": "$.data.name"
}
}

After this step executes, {{user_id}} and {{user_name}} are available in all subsequent steps.

The following example creates a user, extracts the returned ID, and then retrieves the user to verify it was created correctly.

Step 1 — Create user:

{
"step_key": "create_user",
"action": "http_request",
"config": {
"method": "POST",
"url": "{{api_base_url}}/users",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer {{auth_token}}"
},
"body": "{\"name\": \"Test User\", \"email\": \"test@example.com\"}"
},
"assertions": [
{ "type": "status_code", "expected": 201 },
{ "type": "json_path", "expression": "$.data.name", "equals": "Test User" }
],
"extract": {
"created_user_id": "$.data.id"
}
}

Step 2 — Retrieve user:

{
"step_key": "get_user",
"action": "http_request",
"depends_on": ["create_user"],
"config": {
"method": "GET",
"url": "{{api_base_url}}/users/{{created_user_id}}",
"headers": {
"Authorization": "Bearer {{auth_token}}"
}
},
"assertions": [
{ "type": "status_code", "expected": 200 },
{ "type": "json_path", "expression": "$.data.email", "equals": "test@example.com" }
]
}

The condition field on a step controls whether the step executes based on a variable’s value. If the condition is not met, the step is skipped (same behavior as depends_on or requires skips).

Condition checks are evaluated after depends_on checks. The variables referenced in conditions typically come from extract in earlier steps.

FieldTypeRequiredDescription
typestringYesThe condition type: "variable_equals" or "variable_not_equals".
variablestringYesThe name of the variable to check.
valuestringYesThe value to compare against.

Execute the step only if the variable equals the specified value. If the variable is undefined, the condition is not met and the step is skipped.

{
"condition": {
"type": "variable_equals",
"variable": "user_role",
"value": "admin"
}
}

Execute the step only if the variable does NOT equal the specified value. If the variable is undefined, the condition is met and the step runs.

{
"condition": {
"type": "variable_not_equals",
"variable": "payment_method",
"value": "free"
}
}

The browser action drives a headless browser using Playwright.

FieldTypeRequiredDescription
stepsBrowserStep[]YesAn ordered array of browser actions to execute.
timeout_msnumberNoMaximum time in milliseconds for the entire browser action sequence.

Each entry in the steps array is an object with a type field and type-specific parameters.

TypeParameterDescription
gotostring (URL)Navigate to a URL. Supports template variables.
TypeParameterDescription
clickstring (CSS selector)Click an element.
double_clickstring (CSS selector)Double-click an element.
hoverstring (CSS selector)Hover over an element.
TypeParameterDescription
type{ selector: string, text: string }Type text into an input field. Both fields support template variables.
select_option{ selector: string, value: string }Select an option in a <select> element by value.
checkstring (CSS selector)Check a checkbox.
uncheckstring (CSS selector)Uncheck a checkbox.
press{ selector: string, key: string }Press a keyboard key while focused on an element (e.g., Enter, Tab).
focusstring (CSS selector)Focus an element.
upload_file{ selector: string, path: string }Upload a file to a file input element.
TypeParameterDescription
wait_for_selectorstring (CSS selector)Wait until an element matching the selector appears in the DOM.
wait_for_urlstring (URL substring)Wait until the page URL contains the given substring.
TypeParameterDescription
screenshotstring (name)Take a screenshot and save it with the given name.
TypeParameterDescription
set_headerRecord<string, string>Set custom HTTP headers for subsequent browser requests.
TypeParameterDescription
switch_to_framestring (CSS selector)Switch the execution context to an iframe identified by the selector.
switch_to_main_frametrueSwitch back to the main frame.

The browser context is shared across all steps within a single scenario. This means:

  • Login sessions persist across steps.
  • Cookies and localStorage are preserved.
  • Navigation history is maintained.

The browser’s storageState (cookies and localStorage) is carried over from one scenario to the next. This allows you to perform a login in an early scenario and have that session available in all subsequent scenarios without repeating the authentication flow.

The following example tests a login flow and verifies the user lands on the dashboard.

Step 1 — Login:

{
"step_key": "login",
"action": "browser",
"config": {
"steps": [
{ "type": "goto", "url": "{{web_base_url}}/login" },
{ "type": "type", "selector": "#email", "text": "{{test_email}}" },
{ "type": "type", "selector": "#password", "text": "{{test_password}}" },
{ "type": "click", "selector": "button[type='submit']" },
{ "type": "wait_for_url", "url": "/dashboard" }
],
"timeout_ms": 15000
},
"assertions": [
{ "type": "url_contains", "expected": "/dashboard" },
{ "type": "element_visible", "selector": "[data-testid='welcome-message']" }
]
}

Step 2 — Verify dashboard content:

{
"step_key": "verify_dashboard",
"action": "browser",
"depends_on": ["login"],
"config": {
"steps": [
{ "action": "wait_for_selector", "selector": "[data-testid='user-name']" }
]
},
"assertions": [
{ "type": "element_text", "selector": "[data-testid='user-name']", "expected": "Test User" },
{ "type": "element_visible", "selector": "[data-testid='recent-activity']" }
]
}