mcpField
P
playwright-expert

playwright-expert

github.com/cin12211Testing & quality22658 installsUpdated 4d ago
Repository

About playwright-expert

playwright-expert is a skill for Playwright end-to-end and browser testing. It helps developers set up tests, handle common testing problems, and review test code.

Key features

  1. 01Playwright setup guidance
  2. 02End-to-end test examples
  3. 03Page Object Model guidance
  4. 04Network interception and mocking
  5. 05Visual regression checks
  6. 06Flaky test handling

Use cases

  1. 01Starting Playwright tests in a project
  2. 02Testing login and other user flows
  3. 03Mocking API responses during browser tests
  4. 04Reviewing tests for reliability issues

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/cin12211/orca-q --skill playwright-expert

After installing, type/playwright-expertin Claude Code to confirm it loaded.

Details

From the project README

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"]', '[email protected]');
    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"]', '[email protected]');
    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('[email protected]', '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

  1. Hardcoded waits - Use proper assertions
  2. Fragile selectors - Use data-testid
  3. Shared state between tests - Isolate tests
  4. No retries in CI - Add retry for flakiness
  5. Testing implementation details - Test user behavior

Comments

Markdown supported