Record from clicks
The blank page is the hardest part of authoring tests. Record-from-clicks removes it: record yourself clicking through a flow, and Tripwire turns that recorded trace into a plain-English Tripwire suite you can run, edit, and check into the suite repo.
The idea
A recorder — Playwright codegen, a browser extension, or a devtools hook — emits an ordered list of low-level actions. Tripwire's record engine humanizes them into a Tripwire suite: each interaction becomes a natural-language step, and each recorded assertion becomes an expect entry.
[
{ "type": "goto", "url": "/login" },
{ "type": "fill", "selector": "#email", "value": "a@b.test" },
{ "type": "fill", "selector": "#password", "value": "hunter2" },
{ "type": "click", "selector": "button[type=submit]" },
{ "type": "assert", "text": "Welcome back" },
{ "type": "assert", "url": "/account" }
]becomes:
suite: "Recorded flow"
id: recorded-flow
base_url: https://app.example.com
cases:
- id: recorded-flow
title: "Recorded flow"
tags: [recorded]
steps:
- { id: s1, do: "Go to /login" }
- { id: s2, do: "Type 'a@b.test' into the email field" }
- { id: s3, do: "Type 'hunter2' into the password field" }
- { id: s4, do: "Click the submit button" }
expect:
- { id: a1, assert: "the text 'Welcome back' is visible",
check: { kind: visible_text, contains: "Welcome back" } }
- { id: a2, assert: "the URL path is /account",
check: { kind: url, path_is: "/account" } }How the conversion works
- Step types —
goto,fill,click,select,press,check,upload— become plain-English steps. Tripwire derives a human label for each target from its selector (#email→ "the email field",button[type=submit]→ "the submit button"). assertactions become expectations: anassertwithurl→ aurlcheck, anassertwithtext→ avisible_textcheck. Recorded flows therefore arrive with deterministic checks already wired up.- Humanizing the language is optional and additive: with an Anthropic client, Claude rewrites the literal steps into natural tester language (same count, same order, concrete values preserved). Without a client — or if the call fails — a deterministic fallback maps each action to English directly. The structure and expectations are always deterministic.
The result is canonical Tripwire YAML (via the same serializer the generator uses), so a recorded suite drops straight into the suite repo and runs like any other.
One-click recorder
The dashboard's Record tab is a true recorder: click it, a real browser opens at your app, you click and type through the flow you care about, then hit Stop — Tripwire captures every action and converts it to a plain-English suite. No JSON, no Playwright knowledge.
Under the hood (backend/app/engine/recorder.py) a session owns a headed Chromium, injects a recorder script that reports each click / input / select / navigation, and on stop hands the trace to the same pure converter below. Endpoints: /record/start → /record/sessions/{id} → /record/stop.
Convert a trace you already have
The conversion core is a pure, unit-tested engine capability (backend/app/engine/record.py — actions_to_suite, action_to_step, action_to_expect; no browser, no model required) exposed at POST /record/convert. Feed it a recorded action trace (e.g. adapted from Playwright codegen) and get back ready-to-run YAML.
Record vs. generate
| URL → generate | Record from clicks | |
|---|---|---|
| Input | A URL | A recorded interaction trace |
| Coverage | The flows it can infer from the page | Exactly the flow you performed |
| Best for | "I have an app, zero tests" | "I know the exact journey I care about" |
Use generate for breadth, record for the precise flow you just clicked through. Both emit the same Tripwire YAML.
Related: URL → test generation · Writing Tests