Claude Skills Guide

Claude Code Playwright E2E Testing Guide

End-to-end testing with Playwright combined with Claude Code creates a powerful workflow for automating browser-based tests. This guide shows you how to use Claude Code’s capabilities to speed up Playwright test creation, handle complex test scenarios, and maintain robust E2E test suites.

Setting Up Playwright with Claude Code

First, ensure Playwright is installed in your project. Claude Code can assist with the entire setup process, from installation to configuration.

Initialize Playwright in your project:

npm init -y
npm install --save-dev @playwright/test
npx playwright install --with-deps chromium

Create a basic Playwright configuration file that Claude Code can work with:

// playwright.config.js
const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
  testDir: './e2e',
  timeout: 30000,
  retries: 2,
  use: {
    baseURL: 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
  },
  projects: [
    { name: 'chromium', use: { browserName: 'chromium' } },
  ],
});

When setting up this configuration, you can ask Claude Code to explain each option and suggest modifications based on your specific testing needs. For projects that also require accessibility testing, consider combining Playwright with the axe accessibility testing skill to catch WCAG violations during your E2E runs.

Writing E2E Tests with Claude Code Assistance

Claude Code excels at generating Playwright test code quickly. Here’s how to request effective test creation:

“Write a Playwright test that logs in with email user@example.com and password Test123!, verifies the dashboard loads, checks that the user profile section displays the correct username, and logs out.”

Claude Code generates clean, maintainable test code:

// e2e/login.spec.js
const { test, expect } = require('@playwright/test');

test('user can login and view dashboard', async ({ page }) => {
  await page.goto('/login');
  
  await page.fill('[data-testid="email-input"]', 'user@example.com');
  await page.fill('[data-testid="password-input"]', 'Test123!');
  await page.click('[data-testid="login-button"]');
  
  await expect(page).toHaveURL('/dashboard');
  await expect(page.locator('[data-testid="username"]')).toHaveText('user@example.com');
  
  await page.click('[data-testid="logout-button"]');
  await expect(page).toHaveURL('/login');
});

The key to getting high-quality test code from Claude Code is providing clear selectors and describing the exact user flow you want to test. Always use stable selectors like data-testid attributes rather than relying on fragile CSS selectors.

Handling Complex Test Scenarios

Real-world E2E tests often involve complex workflows, authentication handling, and state management. Claude Code can help you implement patterns for these scenarios.

Authentication and Session Management

For tests requiring authenticated sessions, use Playwright’s storageState to maintain login state across tests:

// e2e/utils/auth.js
const { chromium } = require('@playwright/test');
const fs = require('fs');

async function createAuthenticatedSession() {
  const browser = await chromium.launch();
  const context = await browser.newContext();
  const page = await context.newPage();
  
  await page.goto('http://localhost:3000/login');
  await page.fill('[data-testid="email-input"]', 'test@example.com');
  await page.fill('[data-testid="password-input"]', 'TestPassword123');
  await page.click('[data-testid="login-button"]');
  await page.waitForURL('/dashboard');
  
  await context.storageState({ path: 'e2e/.auth/user.json' });
  await browser.close();
}

module.exports = { createAuthenticatedSession };

Claude Code can also help you set up API mocking using tools like MSW (Mock Service Worker) for tests that need to verify API interactions without hitting real endpoints. This approach reduces test flakiness and improves execution speed.

Testing Form Submissions

Form testing is a common E2E scenario. Here’s a pattern for comprehensive form testing:

// e2e/forms/contact.spec.js
const { test, expect } = require('@playwright/test');

test.describe('Contact Form', () => {
  test('validates required fields', async ({ page }) => {
    await page.goto('/contact');
    await page.click('[data-testid="submit-button"]');
    
    await expect(page.locator('[data-testid="email-error"]'))
      .toContainText('Email is required');
  });
  
  test('submits successfully with valid data', async ({ page }) => {
    await page.goto('/contact');
    
    await page.fill('[data-testid="name-input"]', 'John Doe');
    await page.fill('[data-testid="email-input"]', 'john@example.com');
    await page.fill('[data-testid="message-input"]', 'Hello world');
    
    await page.click('[data-testid="submit-button"]');
    
    await expect(page.locator('[data-testid="success-message"]'))
      .toBeVisible();
  });
});

Debugging Failed E2E Tests

When tests fail, Claude Code helps you diagnose issues quickly. Share the error output and ask for analysis:

“This Playwright test is failing with ‘Timeout waiting for element visible’. The element exists but might be behind a loading state. How can I modify the test to wait properly?”

Claude Code suggests improvements like explicit waits or retry logic:

// Improved wait pattern
await page.waitForSelector('[data-testid="dashboard-content"]', { 
  state: 'visible', 
  timeout: 10000 
});

For debugging, enable Playwright’s trace viewer which captures detailed execution information. Configure trace collection on failure:

// In playwright.config.js
use: {
  trace: 'on-first-retry',
  video: 'on-first-retry',
}

After a failure, run npx playwright show-trace to analyze the recorded execution. You can paste the trace analysis to Claude Code for further interpretation.

Running Tests in CI/CD Pipelines

Integrating Playwright tests with CI requires proper browser installation and configuration. Claude Code can generate GitHub Actions workflows:

# .github/workflows/e2e.yml
name: E2E Tests
on: [push, pull_request]
jobs:
  test:
    timeout-minutes: 15
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npx playwright install --with-deps
      - run: npm run build
      - run: npm test

For teams using containerized environments, the docker skill can help set up Playwright in Docker containers for consistent test execution across environments.

Best Practices for AI-Assisted E2E Testing

Follow these guidelines to get the most out of Claude Code with Playwright:

Use descriptive test names that explain what the test verifies. Claude Code generates better code when tests have clear names like “displays error message for invalid login” rather than generic names.

Implement the test pyramid: rely on unit tests for logic verification, use integration tests for API interactions, and reserve E2E tests for critical user flows. Claude Code can help you balance test coverage across these layers.

Maintain test data independently. Create dedicated test accounts and use database seeding for consistent test states. The database test fixtures skill provides patterns for managing test data.

Clean up after tests. Ensure logout flows work and test isolation prevents state leakage between tests.

Complementary Testing Skills

Claude Code’s testing capabilities extend beyond Playwright. For comprehensive test suites, consider these skills:

Combine these tools based on your project’s specific needs. Playwright handles browser automation while these complementary skills address other testing scenarios.

Built by theluckystrike — More at zovo.one