# E2E Runner Agent

> **Purpose:** Create and execute end-to-end tests using Playwright with Page Object Model patterns.

---

## When to Use

This agent is automatically invoked when:
- New user-facing features are implemented
- Critical user flows are modified
- The `/e2e` command is used

You can also invoke it manually with `/e2e [test-name]`.

---

## Capabilities

### 1. Test Generation
Creates E2E tests following best practices:

```typescript
// tests/e2e/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from './pages/login.page';
import { DashboardPage } from './pages/dashboard.page';

test.describe('Login Flow', () => {
  test('user can login with valid credentials', async ({ page }) => {
    const loginPage = new LoginPage(page);
    const dashboardPage = new DashboardPage(page);

    await loginPage.goto();
    await loginPage.login('user@example.com', 'password');

    await expect(dashboardPage.welcomeMessage).toBeVisible();
    await expect(dashboardPage.welcomeMessage).toContainText('Welcome');
  });
});
```

### 2. Page Object Model
Generates maintainable page objects:

```typescript
// tests/e2e/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;
  readonly errorMessage: Locator;

  constructor(page: Page) {
    this.page = page;
    this.emailInput = page.getByLabel('Email');
    this.passwordInput = page.getByLabel('Password');
    this.submitButton = page.getByRole('button', { name: 'Sign in' });
    this.errorMessage = page.getByTestId('error-message');
  }

  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();
  }
}
```

### 3. Flaky Test Detection
Identifies and quarantines flaky tests:

```typescript
// Flaky test detection
test.describe('Potentially Flaky Tests', () => {
  test.fixme('animation-dependent test', async ({ page }) => {
    // TODO: Add explicit wait for animation
  });
});
```

### 4. Test Execution
Runs tests with smart defaults:

```bash
# Run all E2E tests
npx playwright test

# Run specific test file
npx playwright test tests/e2e/login.spec.ts

# Run with UI mode for debugging
npx playwright test --ui

# Run with trace for debugging failures
npx playwright test --trace on
```

---

## Python Support

For Python projects using Playwright:

```python
# tests/e2e/test_login.py
import pytest
from playwright.sync_api import Page, expect
from .pages.login_page import LoginPage
from .pages.dashboard_page import DashboardPage

class TestLogin:
    def test_user_can_login(self, page: Page):
        login_page = LoginPage(page)
        dashboard_page = DashboardPage(page)

        login_page.goto()
        login_page.login("user@example.com", "password")

        expect(dashboard_page.welcome_message).to_be_visible()
```

---

## Test Categories

### Critical Path Tests
User journeys that must always work:
- Login/logout
- Signup/onboarding
- Core feature access
- Payment flows

### Regression Tests
Tests for previously fixed bugs:
```typescript
test('regression: login button should be disabled while loading', async ({ page }) => {
  // Reproduces issue #123
  ...
});
```

### Visual Regression Tests
Screenshot comparison:
```typescript
test('homepage matches snapshot', async ({ page }) => {
  await page.goto('/');
  await expect(page).toHaveScreenshot('homepage.png');
});
```

---

## Flaky Test Management

### Quarantine Strategy
```typescript
// tests/e2e/quarantine.spec.ts
import { test } from '@playwright/test';

// Tests here are known flaky and excluded from CI
test.describe.configure({ mode: 'skip' });

test.describe('Quarantined Tests', () => {
  test('flaky timing-dependent test', async ({ page }) => {
    // Issue: Depends on animation timing
    // TODO: Add explicit waits
  });
});
```

### Retry Configuration
```typescript
// playwright.config.ts
export default defineConfig({
  retries: process.env.CI ? 2 : 0,
  reporter: [
    ['html'],
    ['json', { outputFile: 'test-results/results.json' }],
  ],
});
```

---

## Best Practices

### Locator Strategies (Priority Order)
1. `getByRole()` - Semantic, accessible
2. `getByLabel()` - Form elements
3. `getByText()` - Content-based
4. `getByTestId()` - Last resort

### Test Isolation
- Each test should be independent
- Use fixtures for shared setup
- Clean up after tests

### Wait Strategies
```typescript
// ❌ Bad: Fixed timeout
await page.waitForTimeout(3000);

// ✅ Good: Wait for specific condition
await expect(page.getByTestId('loading')).toBeHidden();
await expect(page.getByTestId('data')).toBeVisible();
```

---

## Integration with Other Agents

- **TDD Guide:** Ensures E2E tests are written first
- **Code Reviewer:** Reviews test quality
- **Build Error Resolver:** Fixes failing tests

---

## Commands

| Command | Description |
|---------|-------------|
| `/e2e` | Generate E2E test for current feature |
| `/e2e run` | Execute all E2E tests |
| `/e2e debug [file]` | Run test in debug mode |
| `/e2e update-snapshots` | Update visual regression snapshots |
