This documentation is available as Markdown. For the complete index, see llms.txt. Skip to content

Worked example — authoring over MCP

For the complete documentation index, see llms.txt

This is the orchestration an agent runs to author a test end-to-end — the literal tool-call trace, plus the exact input schema for the recording tools.

The loop

explore_start → goto → get_page_snapshot → explore_step×N (with refs)
→ save_exploration_as_test → run_test → (step / resume / inspect_runtime on pause)

Trace: record a sign-in

// 1. Start a recording session.
explore_start({
scenario_name: "auth/login",
title: "Sign in",
description: "Demo user signs in"
})
// → { explorationId, availableVariables, availableFlows }
// If availableFlows already has "signin", DON'T re-record it — call explore_run_flow.
// 2. Navigate. goto needs no element ref.
explore_step({
explorationId, action: "goto", url: "/login",
section: "Sign in", description: "Open the login page"
})
// 3. Snapshot to get element ref handles ([ref=eN]).
get_page_snapshot()
// → outline containing [ref=e3] email input, [ref=e5] password input, [ref=e8] submit button
// 4. Record actions, addressing elements by ref.
explore_step({
explorationId, action: "fill",
locator: { kind: "locator", steps: [{ kind: "ref", ref: "e3" }] },
value: "demo@example.com",
section: "Sign in", description: "Type the email"
})
explore_step({
explorationId, action: "fill",
locator: { kind: "locator", steps: [{ kind: "ref", ref: "e5" }] },
value: "hunter2",
section: "Sign in", description: "Type the password"
})
explore_step({
explorationId, action: "click",
locator: { kind: "locator", steps: [{ kind: "ref", ref: "e8" }] },
section: "Sign in", description: "Submit the form"
})
// 5. Save to disk. flow:-marked steps are extracted into _helpers/<flow>.js.
save_exploration_as_test({ explorationId, scenarioName: "auth/login" })
// → writes unotest/e2e/auth/login.js
// 6. Verify it runs green.
run_test({ scenario: "auth/login" })
// → { runtimeId }. If it pauses (breakpoint/failure): inspect_runtime → patch → resume.

explore_step / explore_record — input schema

explore_step runs one action. With an explorationId it records the step; without one it executes ad-hoc (no recording). explore_record is the same envelope but section + description are required and locators must be ref-form.

FieldTypeNotes
actionstringrequired — one of the actions below
explorationIdstringpresent → record · absent → ad-hoc run
locatorref locatorelement to act on (see below)
urlstringfor goto
patternstringfor wait_for_url (substring match)
valuestring | string[]for fill, select_option
keystringfor press (e.g. "Enter")
textstringfor wait_for_text
optionsobjectaction options (e.g. { force: true }, nav options)
sectionstringgroup label · required when recording
descriptionstringstep intent · required when recording
flowstringmark step as part of a reusable flow_<name>
allowNoRefbooleanallow a non-ref locator (last resort)

Actions and their fields

ActionFields
gotourl
reload, go_back, go_forward
click, double_click, hover, check, uncheck, scroll_into_view, wait_forlocator
filllocator, value (string)
presslocator, key
select_optionlocator, value (string | string[])
wait_for_texttext
wait_for_urlpattern
enter_framelocator
exit_frame, set_pagetab/frame switch — see the live tool description

Ref locators

While recording, address elements by the [ref=eN] handles from get_page_snapshot (or get_aria_snapshot):

{ "kind": "locator", "steps": [{ "kind": "ref", "ref": "e8" }] }

Recording rejects non-ref locators (so saved tests get stable getByRole/getByTestId selectors, not brittle ones). Pass allowNoRef: true only as a last resort for a hand-written locator. On save, refs are resolved to the stable selector form per the selector priority.

After saving

The generated unotest/e2e/auth/login.js is plain .js with step("…") blocks. Add assertions, run run_test, then npx @unotest/web lint. On failure, read the failure bundle and propose a diff — the human approves it (self-healing is never silent).