# How to Set Up Playwright E2E Tests Using the e2e-runner Agent in Claude Code

> Automate Playwright E2E tests with the e2e-runner agent in Claude Code. Learn to orchestrate Agent Browser, generate Page-Object Model tests, and manage flaky tests for smoother testing.

- Repository: [Affaan Mustafa/everything-claude-code](https://github.com/affaan-m/everything-claude-code)
- Tags: how-to-guide
- Published: 2026-03-20

---

**The e2e-runner agent in Claude Code automates Playwright E2E testing by orchestrating the Agent Browser (an AI-augmented Playwright driver) alongside fallback Playwright execution, generating Page-Object Model tests, and managing flaky test quarantine.**

The **e2e-runner** agent serves as the built-in end-to-end testing specialist for the Everything-Claude-Code (ECC) platform. It drives UI verification by preferring the **Agent Browser**—a Playwright-based, AI-augmented driver—and falling back to raw Playwright when the browser agent is unavailable. This guide walks you through configuring the e2e-runner agent to create, execute, and maintain reliable Playwright E2E tests.

## Understanding the e2e-runner Agent Architecture

The e2e-runner agent operates through a dual-mode execution model defined in [`agents/e2e-runner.md`](https://github.com/affaan-m/everything-claude-code/blob/main/agents/e2e-runner.md). 

**Agent Browser (Preferred Mode):** An AI-augmented wrapper around Playwright that understands natural language instructions and can generate selectors interactively.

**Raw Playwright (Fallback Mode):** Standard Playwright execution when the Agent Browser is not installed or explicitly bypassed.

When invoked, the agent plans critical user journeys, creates test files using the **Page-Object Model (POM)** pattern from the [`skills/e2e-testing/SKILL.md`](https://github.com/affaan-m/everything-claude-code/blob/main/skills/e2e-testing/SKILL.md), executes tests with full artifact capture (screenshots, videos, traces), and automatically quarantines flaky tests using `test.fixme()` or `test.skip()`.

## Prerequisites and Installation

### Install the Agent Browser

The e2e-runner prefers the Agent Browser for AI-augmented test generation. Install it globally:

```bash
npm install -g agent-browser && agent-browser install

```

This provides the interactive `agent-browser` CLI used for generating selectors and driving tests with natural language.

### Install Playwright Dependencies

Install the core Playwright test runner and system dependencies as the fallback mechanism:

```bash
npm i -D @playwright/test
npx playwright install --with-deps

```

The `--with-deps` flag ensures OS-level browser dependencies (Chromium, Firefox, WebKit) are installed.

## Configuring Playwright for the e2e-runner

The e2e-runner expects a [`playwright.config.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/playwright.config.ts) at the repository root. This configuration, referenced in the agent's execution plan, enables parallel execution, multiple reporters, and automatic trace capture:

```typescript
import { defineConfig, devices } from '@playwright/test'

export default defineConfig({
  testDir: './tests/e2e',
  fullyParallel: true,
  forbidOnly: !!process.env.CI,
  retries: process.env.CI ? 2 : 0,
  workers: process.env.CI ? 1 : undefined,
  reporter: [
    ['html', { outputFolder: 'playwright-report' }],
    ['junit', { outputFile: 'playwright-results.xml' }],
    ['json', { outputFile: 'playwright-results.json' }],
  ],
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    trace: 'on-first-retry',
    screenshot: 'only-on-failure',
    video: 'retain-on-failure',
    actionTimeout: 10000,
    navigationTimeout: 30000,
  },
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
    { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
  ],
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
    timeout: 120000,
  },
})

```

**Key configuration aspects for the e2e-runner:**
- **testDir**: Points to `./tests/e2e` where the agent generates specs
- **trace**: Captures detailed execution traces on first retry for AI analysis
- **webServer**: Automatically starts the dev server before test execution
- **reporter**: Outputs HTML, JUnit XML, and JSON formats for comprehensive reporting

## Writing Tests with the Page-Object Model

The e2e-runner agent generates tests following the **Page-Object Model (POM)** pattern defined in [`skills/e2e-testing/SKILL.md`](https://github.com/affaan-m/everything-claude-code/blob/main/skills/e2e-testing/SKILL.md). This separates page structure from test logic.

### Page Object Example ([`tests/pages/ItemsPage.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/tests/pages/ItemsPage.ts))

```typescript
import { Page, Locator } from '@playwright/test'

export class ItemsPage {
  readonly page: Page
  readonly searchInput: Locator
  readonly itemCards: Locator
  readonly createButton: Locator

  constructor(page: Page) {
    this.page = page
    this.searchInput = page.locator('[data-testid="search-input"]')
    this.itemCards = page.locator('[data-testid="item-card"]')
    this.createButton = page.locator('[data-testid="create-btn"]')
  }

  async goto() {
    await this.page.goto('/items')
    await this.page.waitForLoadState('networkidle')
  }

  async search(query: string) {
    await this.searchInput.fill(query)
    await this.page.waitForResponse(r => r.url().includes('/api/search'))
    await this.page.waitForLoadState('networkidle')
  }

  async getItemCount() {
    return await this.itemCards.count()
  }
}

```

### Test Specification ([`tests/e2e/features/search.spec.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/tests/e2e/features/search.spec.ts))

```typescript
import { test, expect } from '@playwright/test'
import { ItemsPage } from '../../pages/ItemsPage'

test.describe('Item Search', () => {
  let itemsPage: ItemsPage

  test.beforeEach(async ({ page }) => {
    itemsPage = new ItemsPage(page)
    await itemsPage.goto()
  })

  test('should return results for a valid query', async ({ page }) => {
    await itemsPage.search('test')
    const count = await itemsPage.getItemCount()
    expect(count).toBeGreaterThan(0)
    await expect(itemsPage.itemCards.first()).toContainText(/test/i)
    await page.screenshot({ path: 'artifacts/search-results.png' })
  })

  test('should handle no‑result queries', async ({ page }) => {
    await itemsPage.search('nonexistent‑123')
    await expect(page.locator('[data-testid="no-results"]')).toBeVisible()
    expect(await itemsPage.getItemCount()).toBe(0)
  })
})

```

## Executing Tests Locally

The e2e-runner agent can suggest execution commands based on your environment. You have two execution paths:

**Agent Browser Workflow (Preferred):**

```bash

# Open interactive browser for AI-assisted selector generation

agent-browser open http://localhost:3000

# Capture page snapshots for test generation

agent-browser snapshot -i

# Execute tests if agent-browser provides a wrapper

agent-browser test

```

**Standard Playwright Fallback:**

```bash

# Run all E2E tests

npx playwright test

# Run specific test file with headed browser for debugging

npx playwright test tests/e2e/features/search.spec.ts --headed

# View HTML report

npx playwright show-report

```

## CI/CD Integration

The e2e-runner agent generates GitHub Actions workflows based on the pattern in [`.github/workflows/e2e.yml`](https://github.com/affaan-m/everything-claude-code/blob/main/.github/workflows/e2e.yml). This configuration installs dependencies, starts the dev server, executes tests, and uploads artifacts:

```yaml
name: E2E Tests
on: [push, pull_request]

jobs:
  test:
    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: npx playwright test
        env:
          BASE_URL: ${{ vars.STAGING_URL }}
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

```

The workflow captures screenshots, videos, and traces on failure, storing them as artifacts for 30 days.

## Handling Flaky Tests

The e2e-runner agent automatically identifies and quarantines unstable tests. When a test exhibits inconsistent behavior, the agent suggests marking it with `test.fixme()` or `test.skip()`:

```typescript
test('flaky: complex search', async ({ page }) => {
  test.fixme(true, 'Flaky - Issue #123')
  // Test implementation...
})

```

This prevents flaky tests from blocking CI pipelines while preserving the test code for future stabilization.

## Summary

- **The e2e-runner agent** in Claude Code orchestrates Playwright E2E testing through the AI-augmented Agent Browser with fallback to standard Playwright.
- **Configuration** centers on [`playwright.config.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/playwright.config.ts) with parallel execution, multi-reporter output, and automatic dev server management.
- **Test architecture** follows the Page-Object Model pattern defined in [`skills/e2e-testing/SKILL.md`](https://github.com/affaan-m/everything-claude-code/blob/main/skills/e2e-testing/SKILL.md), separating page selectors from test logic.
- **Execution** supports both interactive Agent Browser workflows (`agent-browser open`) and standard CLI commands (`npx playwright test`).
- **CI integration** uses the GitHub Actions template in [`.github/workflows/e2e.yml`](https://github.com/affaan-m/everything-claude-code/blob/main/.github/workflows/e2e.yml) to install dependencies, run tests against staging URLs, and upload artifact reports.
- **Flaky test management** utilizes `test.fixme()` quarantine patterns to maintain pipeline stability.

## Frequently Asked Questions

### What is the difference between the Agent Browser and standard Playwright?

The **Agent Browser** is an AI-augmented wrapper around Playwright that understands natural language instructions and can interactively generate selectors by observing user interactions. According to the source code in [`agents/e2e-runner.md`](https://github.com/affaan-m/everything-claude-code/blob/main/agents/e2e-runner.md), the e2e-runner prefers this mode for intelligent test generation but falls back to raw Playwright when the Agent Browser is unavailable or when running in standard CI environments.

### Where does the e2e-runner agent store its configuration patterns?

The e2e-runner agent references canonical patterns from [`skills/e2e-testing/SKILL.md`](https://github.com/affaan-m/everything-claude-code/blob/main/skills/e2e-testing/SKILL.md), which defines the Page-Object Model structure, recommended directory layout (`tests/e2e/` for specs, `tests/pages/` for POMs), and configuration standards. The actual Playwright configuration resides in [`playwright.config.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/playwright.config.ts) at the repository root, while CI workflows are templated in [`.github/workflows/e2e.yml`](https://github.com/affaan-m/everything-claude-code/blob/main/.github/workflows/e2e.yml).

### How does the e2e-runner handle test failures in CI?

When tests fail in CI, the e2e-runner leverages Playwright's configured reporters to generate HTML, JUnit XML, and JSON output files. The GitHub Actions workflow in [`.github/workflows/e2e.yml`](https://github.com/affaan-m/everything-claude-code/blob/main/.github/workflows/e2e.yml) automatically uploads the `playwright-report/` directory as an artifact with a 30-day retention period. Additionally, the configuration captures screenshots, videos, and traces on failure, providing comprehensive debugging material for AI analysis or manual review.

### Can I use the e2e-runner without installing the Agent Browser?

Yes, the e2e-runner explicitly supports fallback to standard Playwright when the Agent Browser is not installed. As documented in [`agents/e2e-runner.md`](https://github.com/affaan-m/everything-claude-code/blob/main/agents/e2e-runner.md), the agent will suggest standard Playwright CLI commands (`npx playwright test`) and utilize the [`playwright.config.ts`](https://github.com/affaan-m/everything-claude-code/blob/main/playwright.config.ts) configuration directly. While you lose the AI-augmented selector generation capabilities, all core E2E functionality—including parallel execution, reporting, and flaky test management—remains fully functional through the standard Playwright runtime.