playwright-expert
0
总安装量
19
周安装量
安装命令
npx skills add https://github.com/cin12211/orca-q --skill playwright-expert
Agent 安装分布
claude-code
16
opencode
15
gemini-cli
14
cursor
12
antigravity
11
github-copilot
11
Skill 文档
Playwright Expert
Expert in Playwright for E2E testing, browser automation, and cross-browser testing.
When Invoked
Recommend Specialist
- Unit/integration tests: recommend jest-expert or vitest-expert
- React component testing: recommend testing-expert
- API testing only: recommend rest-api-expert
Environment Detection
npx playwright --version 2>/dev/null
ls playwright.config.* 2>/dev/null
find . -name "*.spec.ts" -path "*e2e*" | head -5
Problem Playbooks
Project Setup
# Initialize Playwright
npm init playwright@latest
# Install browsers
npx playwright install
// 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',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{ name: 'chromium', use: { ...devices['Desktop Chrome'] } },
{ name: 'firefox', use: { ...devices['Desktop Firefox'] } },
{ name: 'webkit', use: { ...devices['Desktop Safari'] } },
],
webServer: {
command: 'npm run dev',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
},
});
Writing Tests
import { test, expect } from '@playwright/test';
test.describe('Authentication', () => {
test('should login successfully', async ({ page }) => {
await page.goto('/login');
await page.fill('[data-testid="email"]', 'user@example.com');
await page.fill('[data-testid="password"]', 'password123');
await page.click('[data-testid="submit"]');
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
});
test('should show error for invalid credentials', async ({ page }) => {
await page.goto('/login');
await page.fill('[data-testid="email"]', 'wrong@example.com');
await page.fill('[data-testid="password"]', 'wrong');
await page.click('[data-testid="submit"]');
await expect(page.locator('.error-message')).toBeVisible();
});
});
Page Object Model
// pages/login.page.ts
import { Page, Locator } from '@playwright/test';
export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly submitButton: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.locator('[data-testid="email"]');
this.passwordInput = page.locator('[data-testid="password"]');
this.submitButton = page.locator('[data-testid="submit"]');
}
async goto() {
await this.page.goto('/login');
}
async login(email: string, password: string) {
await this.emailInput.fill(email);
await this.passwordInput.fill(password);
await this.submitButton.click();
}
}
// Usage in test
test('login test', async ({ page }) => {
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.login('user@example.com', 'password');
});
Network Interception
test('mock API response', 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.locator('.user-name')).toContainText('Mock User');
});
Visual Regression
test('visual comparison', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png', {
maxDiffPixelRatio: 0.1,
});
});
Handling Flaky Tests
// Retry flaky tests
test('flaky network test', async ({ page }) => {
test.slow(); // Triple timeout
await page.goto('/');
await page.waitForLoadState('networkidle');
// Use polling assertions
await expect(async () => {
const response = await page.request.get('/api/status');
expect(response.ok()).toBeTruthy();
}).toPass({ timeout: 10000 });
});
Running Tests
# Run all tests
npx playwright test
# Run specific file
npx playwright test login.spec.ts
# Run in headed mode
npx playwright test --headed
# Run in UI mode
npx playwright test --ui
# Debug mode
npx playwright test --debug
# Generate report
npx playwright show-report
Code Review Checklist
- data-testid attributes for selectors
- Page Object Model for complex flows
- Network requests mocked where needed
- Proper wait strategies (no arbitrary waits)
- Screenshots on failure configured
- Parallel execution enabled
Anti-Patterns
- Hardcoded waits – Use proper assertions
- Fragile selectors – Use data-testid
- Shared state between tests – Isolate tests
- No retries in CI – Add retry for flakiness
- Testing implementation details – Test user behavior