Recording Browser Flow as Playwright Test
Use the browser MCP as a recorder: every navigation, click, fill, and keypress becomes a row in a script. The agent then translates that trace into a Playwright test file in the repo (or a snippet to paste into an existing spec).
This is Cursor-native because it combines browser_snapshot (refs + roles + names) with structured actions — not a separate recorder extension.
Prerequisites
- Target app reachable (e.g. dev server running); use
finding-dev-server-urlif needed. - Repo has or will have Playwright installed (
@playwright/test). If not, add it withadding-e2e-testsor the project’s standard setup.
Recording workflow
1. Define the flow
One sentence scope, e.g. “Log in, open Settings, toggle dark mode, save.”
2. For each step, in order
browser_snapshot— get the accessibility tree and element refs.- Choose the smallest interaction:
- browser_click with ref from snapshot (not coordinate clicks unless required). - browser_fill or browser_type for inputs. - browser_select_option for selects. - browser_navigate for full URL changes.
- Log the step in a structured list the main agent keeps:
- Step number - Action verb (navigate, click, fill, press, select) - Locator strategy for Playwright — prefer: - getByRole('button', {name: '...'}) - getByLabel('...') - getByPlaceholder('...') - getByTestId('...') if the app uses test IDs - Value (for fills), URL (for navigates) - Optional: short assertion (“expect URL to contain /settings”)
- After actions that change the DOM or navigate, take a new
browser_snapshotbefore the next interaction. - If the flow must wait for async content, use
browser_wait_foror short incremental waits percursor-ide-browserguidance — then snapshot again.
3. Add assertions
From the final snapshot and URL, add at least:
expect(page).toHaveURL(...)or URL fragment check- One visible outcome: text, role, or test id
4. Generate Playwright output
Emit a test file, e.g. tests/recorded/<flow-name>.spec.ts, containing:
test.describeandtest('...', async ({page}) => {...})- Steps as
await page.goto(...),await page.getByRole(...).click(), etc. - No raw snapshot refs in the final file — they are session-specific.
5. Run and harden
npx playwright test tests/recorded/<flow-name>.spec.tsFix flakiness: prefer expect(locator).toBeVisible() before clicks, use toPass() retries for async lists, avoid arbitrary waitForTimeout except as last resort.
Tips
- Stable selectors: roles and accessible names beat CSS from devtools. Add
data-testidin app code if names are ambiguous. - Auth: if the flow needs login, use env vars for test credentials or Playwright
storageState— never commit secrets. - Parallel runs: ensure test data does not collide with other tests.
When not to use
- Flows that require manual 2FA, captchas, or email links — stop and ask the user for a test bypass or mock.