| name | web-test |
| description | Use to debug a live web page and convert findings into Playwright regression tests — investigate UI bugs, fix flaky tests, generate E2E tests from exploration. Orchestrates the debug-to-test workflow. Not for writing standalone tests with no exploration (use playwright). |
Web Test: Debug-to-Test Workflow
Overview
This skill orchestrates a four-phase workflow: explore a web page with agent-browser to identify issues, diagnose problems, map element references to Playwright locators, and generate test scripts that capture findings as regression tests.
Prerequisites: agent-browser CLI installed (npm install -g agent-browser && agent-browser install) and @playwright/test installed in the project (npm install -D @playwright/test && npx playwright install).
The four phases:
Explore (agent-browser) → Diagnose → Map refs to locators → Generate Playwright test
Phase 1: Explore with agent-browser
Navigate to the target page and systematically inspect its state:
agent-browser open <url>
agent-browser snapshot -i
Investigation checklist:
- Visual scan —
screenshot to observe layout, visual state, and obvious defects.
- Interactive inventory —
snapshot -i to list all interactive elements with refs.
- Section focus —
snapshot -s ".section" to isolate specific areas of interest.
- Interaction test — Click buttons, fill forms, navigate links. Re-snapshot after each action to verify state changes.
- Scroll exploration —
scroll down N then re-snapshot to find below-fold content.
- Annotated verification —
screenshot --annotate to visually confirm ref-to-element mapping.
Record every interaction step — these become the basis for test cases in Phase 4.
Exploration is complete when all visible sections have been inspected, all interactive elements have been tested, and all observed defects have been recorded.
Phase 2: Diagnose Issues
Categorize findings from exploration:
| Category | Detection Method | Example |
|---|
| Missing element | Expected ref absent from snapshot | Button in spec but not in DOM |
| Wrong text | Snapshot shows incorrect label/content | "Save" button labeled "Svae" |
| Broken interaction | Action produces no or wrong state change | Submit button doesn't navigate |
| Visual defect | Screenshot shows layout/style issues | Overlapping elements, clipped text |
| Accessibility gap | Snapshot shows missing roles/labels | Input without associated label |
Fallback to Playwright for Advanced Diagnostics
When agent-browser cannot diagnose the root cause (console errors, network failures, JavaScript state, iframes, shadow DOM), switch to Playwright library mode. Use page.on('console') for console errors, page.on('response') for network failures, and page.evaluate() for JavaScript state inspection.
For diagnostic code templates and the full fallback scenario reference, consult references/playwright-diagnostics.md.
Phase 3: Map Refs to Playwright Locators
Convert agent-browser snapshot information to Playwright locators. Apply the locator precision order from the playwright skill (getByTestId > getByRole > getByLabel > getByPlaceholder > getByText > data attributes > CSS).
Snapshot-to-Locator Mapping
agent-browser reports element roles from the accessibility tree. Map them directly to Playwright locators:
data-testid attribute → getByTestId() (always preferred)
- Role + accessible name (e.g.,
button "Submit") → getByRole('button', { name: 'Submit' })
- Input with label (e.g.,
textbox "Email") → getByLabel('Email')
- Always pass
{ exact: true } to text-based locators
- If ambiguous, narrow with
.filter({ hasText: 'unique' }) or scope to parent
Snapshot-to-Locator Examples
Snapshot output: Playwright locator:
─────────────────────────────────────────────────────────────
@e1: button "Submit" → getByRole('button', { name: 'Submit' })
@e2: textbox "Email" → getByLabel('Email')
@e3: link "Learn more" → getByRole('link', { name: 'Learn more' })
@e4: heading "Dashboard" [level=1] → getByRole('heading', { name: 'Dashboard', level: 1 })
@e5: checkbox "Remember me" → getByLabel('Remember me')
@e6: combobox "Country" → getByLabel('Country')
Phase 4: Generate Playwright Test
Transform exploration steps and diagnosed issues into a structured test file:
import { test, expect } from '@playwright/test';
test.describe('<Feature or Page Name>', () => {
test.beforeEach(async ({ page }) => {
await page.goto('<url>');
});
test('should <expected behavior description>', async ({ page }) => {
const emailField = page.getByLabel('Email');
const submitButton = page.getByRole('button', { name: 'Submit' });
await emailField.fill('test@example.com');
await submitButton.click();
await expect(page.getByText('Success', { exact: true })).toBeVisible();
});
test('should not show error when <fixed scenario>', async ({ page }) => {
const deleteButton = page.getByRole('button', { name: 'Delete' });
await deleteButton.click();
await expect(page.getByText('Item deleted', { exact: true })).toBeVisible();
await expect(page.getByRole('alert')).not.toBeVisible();
});
});
Test Generation Rules
- One test per behavior — Each test verifies one specific interaction flow or state.
- Regression tests for bugs — For each diagnosed issue, create a test that fails if the bug reappears.
- AAA pattern — Arrange (locate elements), Act (interact), Assert (verify outcome).
- Descriptive test names — Describe the expected behavior:
'should navigate to dashboard after login', not 'test login'.
- Minimal interactions — Include only steps necessary to reach the assertion. Remove exploration noise.
- Use web assertions — Always
await expect(locator).toBeVisible(), never expect(await locator.isVisible()).toBe(true).
Including Fallback Diagnostics in Tests
When console or network issues were diagnosed during Phase 2, convert them into test assertions. For diagnostic test patterns (console error detection, network health, JavaScript error tests), consult references/playwright-diagnostics.md.
Complete Workflow Example
1. agent-browser open https://app.example.com/login
2. agent-browser snapshot -i
→ @e1: textbox "Email"
→ @e2: textbox "Password"
→ @e3: button "Sign In"
3. agent-browser fill @e1 "test@example.com"
4. agent-browser fill @e2 "password123"
5. agent-browser click @e3
6. agent-browser snapshot -i
→ @e4: heading "Dashboard"
→ @e5: button "Logout"
7. agent-browser screenshot
→ Dashboard loaded correctly
Generated test:
test('should login and reach dashboard', async ({ page }) => {
await page.goto('https://app.example.com/login');
await page.getByLabel('Email').fill('test@example.com');
await page.getByLabel('Password').fill('password123');
await page.getByRole('button', { name: 'Sign In' }).click();
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible();
await expect(page.getByRole('button', { name: 'Logout' })).toBeVisible();
});