playwright

Playwright Core Knowledge

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "playwright" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-playwright

Playwright Core Knowledge

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: playwright for comprehensive documentation.

When NOT to Use This Skill

  • Unit Testing - Use vitest or jest for isolated function/module tests

  • Component Testing - Use testing-library for React/Vue component tests

  • API-Only Tests - Use framework-specific HTTP clients or REST clients

  • Performance Testing - Use dedicated tools like k6 or Lighthouse

  • Mobile App Testing - Use Appium or Detox for native mobile apps

Basic Test

import { test, expect } from '@playwright/test';

test('user can login', async ({ page }) => { await page.goto('/login'); await page.fill('[name="email"]', 'user@example.com'); await page.fill('[name="password"]', 'password123'); await page.click('button[type="submit"]');

await expect(page).toHaveURL('/dashboard'); await expect(page.locator('h1')).toContainText('Welcome'); });

Locators

// By role (preferred) page.getByRole('button', { name: 'Submit' }); page.getByRole('link', { name: 'Home' }); page.getByLabel('Email'); page.getByPlaceholder('Enter email'); page.getByText('Welcome');

// By test id page.getByTestId('submit-button');

// CSS/XPath (fallback) page.locator('.submit-btn'); page.locator('#user-form');

Assertions

// Visibility await expect(locator).toBeVisible(); await expect(locator).toBeHidden();

// Text await expect(locator).toHaveText('Hello'); await expect(locator).toContainText('Hello');

// Attributes await expect(locator).toHaveAttribute('href', '/home'); await expect(locator).toHaveClass(/active/);

// Input await expect(locator).toHaveValue('test@example.com');

// Page await expect(page).toHaveURL(/dashboard/); await expect(page).toHaveTitle('Dashboard');

Actions

await page.click('button'); await page.fill('input', 'text'); await page.check('input[type="checkbox"]'); await page.selectOption('select', 'option1'); await page.hover('.menu-item'); await page.keyboard.press('Enter');

Page Objects

class LoginPage { constructor(private page: Page) {}

async login(email: string, password: string) { await this.page.fill('[name="email"]', email); await this.page.fill('[name="password"]', password); await this.page.click('button[type="submit"]'); } }

Config

// playwright.config.ts export default defineConfig({ testDir: './e2e', use: { baseURL: 'http://localhost:3000' }, projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } } ] });

Production Readiness

Test Configuration

// playwright.config.ts import { defineConfig, devices } from '@playwright/test';

export default defineConfig({ testDir: './e2e', fullyParallel: true, forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: process.env.CI ? 1 : undefined, reporter: [ ['html'], ['junit', { outputFile: 'test-results/junit.xml' }], ],

use: { baseURL: process.env.BASE_URL || 'http://localhost:3000', trace: 'on-first-retry', screenshot: 'only-on-failure', video: 'on-first-retry', },

projects: [ { name: 'chromium', use: { ...devices['Desktop Chrome'] } }, { name: 'firefox', use: { ...devices['Desktop Firefox'] } }, { name: 'webkit', use: { ...devices['Desktop Safari'] } }, { name: 'mobile', use: { ...devices['iPhone 13'] } }, ],

webServer: { command: 'npm run start', url: 'http://localhost:3000', reuseExistingServer: !process.env.CI, timeout: 120000, }, });

Authentication State

// Save auth state for reuse // auth.setup.ts import { test as setup } from '@playwright/test';

setup('authenticate', async ({ page }) => { await page.goto('/login'); await page.fill('[name="email"]', process.env.TEST_USER_EMAIL!); await page.fill('[name="password"]', process.env.TEST_USER_PASSWORD!); await page.click('button[type="submit"]'); await page.waitForURL('/dashboard');

// Save storage state await page.context().storageState({ path: '.auth/user.json' }); });

// Use in tests import { test } from '@playwright/test';

test.use({ storageState: '.auth/user.json' });

test('authenticated test', async ({ page }) => { await page.goto('/dashboard'); // Already logged in });

API Testing

test('API test', async ({ request }) => { const response = await request.post('/api/users', { data: { name: 'John', email: 'john@example.com' }, headers: { Authorization: Bearer ${token} }, });

expect(response.ok()).toBeTruthy(); const user = await response.json(); expect(user.name).toBe('John'); });

// Mock API responses test('with mocked API', async ({ page }) => { await page.route('/api/users', async route => { await route.fulfill({ status: 200, body: JSON.stringify([{ id: 1, name: 'Mock User' }]), }); });

await page.goto('/users'); await expect(page.getByText('Mock User')).toBeVisible(); });

Visual Regression

test('visual regression', async ({ page }) => { await page.goto('/dashboard'); await expect(page).toHaveScreenshot('dashboard.png', { maxDiffPixels: 100, threshold: 0.2, }); });

// Update snapshots: npx playwright test --update-snapshots

CI Configuration

GitHub Actions

  • name: Install Playwright run: npx playwright install --with-deps

  • name: Run E2E tests run: npx playwright test env: BASE_URL: ${{ secrets.STAGING_URL }}

  • name: Upload report uses: actions/upload-artifact@v3 if: always() with: name: playwright-report path: playwright-report/

Monitoring Metrics

Metric Target

E2E test pass rate

99%

Test execution time < 10min

Flaky test rate < 1%

Visual diff failures Review all

Checklist

  • Multi-browser testing configured

  • Mobile viewport testing

  • Authentication state reused

  • Retry on failure (CI only)

  • Screenshots on failure

  • Trace collection enabled

  • API mocking for isolation

  • Visual regression tests

  • CI/CD integration

  • Test parallelization

  • Page Object pattern used

Anti-Patterns

Anti-Pattern Why It's Bad Solution

Testing via CSS selectors Brittle, breaks on style changes Use getByRole, getByLabel, getByTestId

Not waiting for elements Flaky tests Use auto-waiting locators, avoid waitForTimeout

Hardcoded waits (page.waitForTimeout) Slow, unreliable Use page.waitForSelector or auto-waiting

No Page Object Model Duplicated code, hard to maintain Extract common actions into Page Objects

Testing too much in one test Hard to debug failures One user flow per test

Not reusing auth state Slow login for every test Save storageState, reuse across tests

Ignoring flaky tests False confidence Fix flaky tests, use retries sparingly

Quick Troubleshooting

Problem Likely Cause Solution

"Timeout waiting for selector" Element not rendered or wrong selector Check selector, ensure element exists

Flaky test (passes/fails randomly) Race condition, slow network Use auto-waiting, avoid waitForTimeout

"Element is not visible" Element hidden or not in viewport Scroll into view, check CSS display

"Execution context destroyed" Navigation happened during action Wait for navigation to complete

Screenshot mismatch Font rendering, animation Disable animations, use fixed viewport

Test hangs forever Missing await Ensure all async calls are awaited

Reference Documentation

  • Locators

  • Page Objects

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

Virtual Desktop — Universal Browser Execution

Full Computer Use for OpenClaw via kasmweb/chrome Docker sidecar. Navigate any website, click, type, fill forms, extract data, upload files, screenshot on an...

Registry SourceRecently Updated
1061Profile unavailable
Coding

OpenClaw CLI Bridge

Bridge local AI CLIs + web browser sessions (Grok, Gemini, Claude.ai, ChatGPT) into OpenClaw as model providers. Includes /cli-* slash commands for instant m...

Registry SourceRecently Updated
4290Profile unavailable
Coding

Handsfree Windows Control

Guide skill for controlling native Windows apps (UIA) and web browsers (Playwright) via the handsfree-windows CLI. Use when you need to automate or test desk...

Registry SourceRecently Updated
4000Profile unavailable
Coding

Playwright CLI Automation

官方Microsoft Playwright CLI网页自动化工具,支持所有主流浏览器的无头/有头自动化操作,包括页面导航、元素交互、截图、录制、测试等功能。当用户提到网页自动化、浏览器操作、爬虫、截图、录制用户操作、E2E测试时触发。

Registry SourceRecently Updated
2252Profile unavailable