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.
http_request
Section titled “http_request”The http_request action sends an HTTP request and validates the response.
HttpRequestConfig
Section titled “HttpRequestConfig”| Field | Type | Required | Description |
|---|---|---|---|
method | string | Yes | HTTP method: GET, POST, PUT, PATCH, DELETE, etc. |
url | string | Yes | The request URL. Supports template variables (e.g., {{base_url}}/api/users). |
headers | Record<string, string> | No | Request headers as key-value pairs. Values support template variables. |
body | any | No | The request body. Objects are serialized as JSON. Supports template variables in string values. |
timeout | number | No | Request timeout in milliseconds. |
poll | PollConfig | No | Poll the endpoint until a condition is met. |
PollConfig
Section titled “PollConfig”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.
| Field | Type | Required | Description |
|---|---|---|---|
until | object | Yes | The condition to check. Must specify one of the sub-fields below. |
until.status_code | number | No | Poll until the response status code matches this value. |
until.json_path | object | No | Poll until a JSON path in the response body matches. Contains path (string) and expected (any). |
interval_ms | number | Yes | Milliseconds to wait between each poll request. |
timeout_ms | number | Yes | Maximum 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 }}Extract
Section titled “Extract”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.
Example
Section titled “Example”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" } ]}Step Condition
Section titled “Step Condition”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.
ConditionConfig
Section titled “ConditionConfig”| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | The condition type: "variable_equals" or "variable_not_equals". |
variable | string | Yes | The name of the variable to check. |
value | string | Yes | The value to compare against. |
variable_equals
Section titled “variable_equals”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" }}variable_not_equals
Section titled “variable_not_equals”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" }}browser
Section titled “browser”The browser action drives a headless browser using Playwright.
BrowserConfig
Section titled “BrowserConfig”| Field | Type | Required | Description |
|---|---|---|---|
steps | BrowserStep[] | Yes | An ordered array of browser actions to execute. |
timeout_ms | number | No | Maximum time in milliseconds for the entire browser action sequence. |
Browser Step Types
Section titled “Browser Step Types”Each entry in the steps array is an object with a type field and type-specific parameters.
Navigation
Section titled “Navigation”| Type | Parameter | Description |
|---|---|---|
goto | string (URL) | Navigate to a URL. Supports template variables. |
Mouse Actions
Section titled “Mouse Actions”| Type | Parameter | Description |
|---|---|---|
click | string (CSS selector) | Click an element. |
double_click | string (CSS selector) | Double-click an element. |
hover | string (CSS selector) | Hover over an element. |
Form Input
Section titled “Form Input”| Type | Parameter | Description |
|---|---|---|
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. |
check | string (CSS selector) | Check a checkbox. |
uncheck | string (CSS selector) | Uncheck a checkbox. |
press | { selector: string, key: string } | Press a keyboard key while focused on an element (e.g., Enter, Tab). |
focus | string (CSS selector) | Focus an element. |
upload_file | { selector: string, path: string } | Upload a file to a file input element. |
Waiting
Section titled “Waiting”| Type | Parameter | Description |
|---|---|---|
wait_for_selector | string (CSS selector) | Wait until an element matching the selector appears in the DOM. |
wait_for_url | string (URL substring) | Wait until the page URL contains the given substring. |
Capture
Section titled “Capture”| Type | Parameter | Description |
|---|---|---|
screenshot | string (name) | Take a screenshot and save it with the given name. |
Headers
Section titled “Headers”| Type | Parameter | Description |
|---|---|---|
set_header | Record<string, string> | Set custom HTTP headers for subsequent browser requests. |
Frames
Section titled “Frames”| Type | Parameter | Description |
|---|---|---|
switch_to_frame | string (CSS selector) | Switch the execution context to an iframe identified by the selector. |
switch_to_main_frame | true | Switch back to the main frame. |
Browser Context and State
Section titled “Browser Context and State”Within a Scenario
Section titled “Within a Scenario”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.
Across Scenarios
Section titled “Across Scenarios”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.
Example
Section titled “Example”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']" } ]}