Record user interactions on any website and generate ready-to-run Playwright tests instantly — directly from a Chrome extension popup. No iframe, no proxy, no limitations.
chrome://extensionsBug-Reproduction-Tool folderPin it for quick access: click the puzzle icon → pin BRT
R)| Action | Generated code |
|—|—|
| Navigate | page.goto('https://...') |
| Click | page.locator(selector).click() |
| Fill input | page.locator(selector).fill('value') |
| Check/Uncheck | .check() / .uncheck() |
| Select dropdown | .selectOption('value') |
| Hover (press H while hovering) | .hover() |
| Keyboard (Enter/Tab on input, Escape) | .press('Enter') |
| File upload | .setInputFiles('filename') |
| Screenshot | page.screenshot({ path: '...' }) |
| Type | Output |
|—|—|
| Has Text | expect(locator).toHaveText('...') |
| Has URL | expect(page).toHaveURL('...') |
| Is Visible | expect(locator).toBeVisible() |
| Has Value | expect(locator).toHaveValue('...') |
| Has Attr | expect(locator).toHaveAttribute('attr', 'value') |
| Count | expect(locator).toHaveCount(n) |
Use ◎ Pick in the assertion dialog to click an element on the page instead of typing a selector manually.
[data-testid] → [name] → [aria-label] → #id → role → [placeholder] → CSS path
Best-practice Playwright selectors, automatically chosen. Selectors are color-coded:
| ● green = stable | ⚠ amber = fragile (may break if layout changes) |
// comment that appears in generated code.brt.jsonimport (TypeScript) and require (JavaScript) syntaxawait page.waitForLoadState('networkidle') after every gototest('...') label and download filename| Key | Action |
|—|—|
| R | Toggle recording |
| Esc | Stop recording |
| S | Add screenshot step |
| H | Record hover on currently highlighted element |
| Ctrl+Z | Undo last step |
manifest.json — Extension config (Manifest V3)
content.js — Injected into every page:
• Intercepts click / change / input / keydown / navigation
• Renders hover highlight + selector tooltip
• Pick mode for element selector picker
• Sends BRT_STEP / BRT_PICK_RESULT messages
background.js — Service worker:
• Receives steps, persists to session storage
• Deduplicates consecutive fill / goto steps
• Forwards step list to popup via BRT_STEP_UPDATE
popup/
popup.html — Extension popup UI
popup.css — Dark developer aesthetic (IBM Plex Sans + JetBrains Mono)
popup.js — Recording control, step list, drag-reorder, undo,
code generator (TS/JS), modals, export/import
tests/
recorded-test.spec.js — Example exported test
playwright.config.js — Ready-to-use Playwright config (headless: false, video on failure)
icons/ — Extension icons (16, 48, 128px)
User interacts with page
→ content.js captures event
→ chrome.runtime.sendMessage({ type: 'BRT_STEP', step })
→ background.js persists + deduplicates
→ chrome.runtime.sendMessage({ type: 'BRT_STEP_UPDATE', steps })
→ popup.js re-renders step list + code
Element picker:
popup.js → BRT_PICK_START → content.js enters pick mode
content.js → BRT_PICK_RESULT (selectorData) → popup.js fills selector field
The repo includes a ready-to-use Playwright config. Just install the dependency and run:
npm install @playwright/test
npx playwright test
Or if starting from scratch in a new project:
npm init playwright@latest
# paste your .spec.ts / .spec.js into tests/
npx playwright test
chrome.storage.session for step persistence across navigationschrome.scripting for dynamic content script injection