Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Browser-based UI verification using Playwright. Page Object Model, selector best practices, visual regression, network interception, and MCP integration. Trigger: When writing E2E tests, verifying UI changes, or setting up Playwright.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-20 | ✗→✓ | ▲ Improved | -15% | 0% |
| case-10 | ✓→✓ | = Same ✓ | -12% | 0% |
| case-01 | ✓→✓ | = Same ✓ | -20% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 91% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 24% | 0% |
Patterns for browser-based UI verification using Playwright. Reliable, maintainable, fast E2E tests.
| Priority | Selector | Example | Why | |----------|----------|---------|-----| | 1 | Role | getByRole('button', { name: 'Submit' }) | Accessible, semantic | | 2 | Label | getByLabel('Email') | Accessible, user-facing | | 3 | Test ID | getByTestId('submit-btn') | Stable, explicit | | 4 | Text | getByText('Sign in') | Readable but fragile | | 5 | CSS | page.locator('.btn-primary') | Last resort |
NEVER: XPath, auto-generated IDs, DOM structure selectors.
typescriptexport class LoginPage { constructor(private page: Page) {} get emailInput() { return this.page.getByLabel('Email'); } get passwordInput() { return this.page.getByLabel('Password'); } get submitButton() { return this.page.getByRole('button', { name: 'Sign in' }); } async login(email: string, password: string) { await this.emailInput.fill(email); await this.passwordInput.fill(password); await this.submitButton.click(); } }
typescripttest('dashboard renders correctly', async ({ page }) => { await page.goto('/dashboard'); await page.waitForLoadState('networkidle'); await expect(page).toHaveScreenshot('dashboard.png', { maxDiffPixelRatio: 0.01 }); });
typescripttest('handles API errors', async ({ page }) => { await page.route('**/api/users', route => route.fulfill({ status: 500, body: 'Server Error' }) ); await page.goto('/users'); await expect(page.getByText('Something went wrong')).toBeVisible(); });
page.waitForTimeout()expect(locator).toBeVisible() auto-retriesretries: 2 in configpage.waitForTimeout() — wait for specific conditionsmaxDiffPixelRatio--trace on-first-retry in CIOther measured skills in the registry, with their headline benchmark lift.