Session Recording¶
Convert AI-assisted exploration into deterministic test scripts.
Overview¶
Session recording captures MCP tool calls and exports them as JSON scripts that can be replayed without an LLM.
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Markdown Test │ │ LLM + MCP │ │ JSON Script │
│ Plan (English) │ ──▶ │ (exploration) │ ──▶ │ (deterministic) │
└──────────────────┘ └──────────────────┘ └──────────────────┘
Workflow¶
1. Write Test Plan (Markdown)¶
# Login Test
1. Navigate to the login page
2. Enter email: test@example.com
3. Enter password: secret123
4. Click the login button
5. Verify we reach the dashboard
2. Execute with LLM¶
Ask Claude to execute your test plan while recording:
"Start recording, then follow my test plan: [paste plan]. When done, export the script."
Claude will:
- Call
start_recording - Execute each step using MCP tools
- Handle selectors, waits, and edge cases
- Call
export_scriptwhen done
3. Get JSON Script¶
The exported script:
{
"name": "Login Test",
"version": 1,
"steps": [
{"action": "navigate", "url": "https://example.com/login"},
{"action": "fill", "selector": "#email", "value": "test@example.com"},
{"action": "fill", "selector": "#password", "value": "secret123"},
{"action": "click", "selector": "button[type='submit']"},
{"action": "waitForUrl", "pattern": "/dashboard"}
]
}
4. Run Deterministically¶
MCP Recording Tools¶
start_recording¶
Begin recording actions.
Parameters:
| Name | Type | Description |
|---|---|---|
name |
string | Script name |
description |
string | What the script tests |
baseUrl |
string | Base URL for relative paths |
Example:
{
"name": "start_recording",
"arguments": {
"name": "Login Test",
"description": "Verify user can log in"
}
}
stop_recording¶
Stop recording actions.
Returns:
| Field | Type | Description |
|---|---|---|
message |
string | Status message |
stepCount |
int | Number of steps recorded |
export_script¶
Export recorded actions as JSON.
Parameters:
| Name | Type | Description |
|---|---|---|
format |
string | json or yaml (default: json) |
Returns:
| Field | Type | Description |
|---|---|---|
script |
string | The script content |
stepCount |
int | Number of steps |
format |
string | Output format |
recording_status¶
Check if recording is active.
Returns:
| Field | Type | Description |
|---|---|---|
recording |
bool | Is recording active |
stepCount |
int | Steps recorded so far |
clear_recording¶
Clear recorded steps without stopping.
Recorded Actions¶
The following MCP tools are recorded:
| Category | Actions |
|---|---|
| Navigation | navigate |
| Clicks | click, dblclick |
| Input | type, fill, clear, press |
| Forms | check, uncheck, select_option |
| Element | hover, focus, scroll_into_view |
| Capture | screenshot, evaluate |
Best Practices¶
Let the LLM Find Selectors¶
Don't specify exact selectors in your test plan:
The LLM will find the appropriate selector and it will be captured.
Include Assertions¶
Ask the LLM to verify outcomes:
Handle Dynamic Content¶
The LLM can add appropriate waits:
Review Before Committing¶
Always review exported scripts:
- Check selectors are stable (prefer IDs, data-testid)
- Verify waits are sufficient
- Add
continueOnErrorwhere appropriate
Example Session¶
User: Start recording a test called "Search Test", then: navigate to Google, search for "w3pilot", and verify results appear.
Claude: I'll start recording and execute your test.
[start_recording: name="Search Test"]
[browser_launch]
[navigate: url="https://google.com"]
[fill: selector="input[name='q']", value="w3pilot"]
[press: selector="input[name='q']", key="Enter"]
[wait_until: selector="#search", state="visible"]
[export_script]
Here's your recorded script:
{
"name": "Search Test",
"steps": [
{"action": "navigate", "url": "https://google.com"},
{"action": "fill", "selector": "input[name='q']", "value": "w3pilot"},
{"action": "press", "selector": "input[name='q']", "key": "Enter"},
{"action": "waitForSelector", "selector": "#search", "state": "visible"}
]
}
You can run this with w3pilot run search-test.json.