Files
2026-01-20 15:31:41 -05:00

2.1 KiB

E2E CLAUDE.md

Playwright end-to-end tests.

Commands

npm test              # Headless
npm run test:headed   # Visible browser
npm run test:ui       # Interactive UI
npx playwright test tests/basic.spec.ts  # Specific file
npx playwright test -g "test name"       # By name

Test Ports

Service Dev Port E2E Port
Backend 3000 3001
Frontend 5173 5174
Database spiceflow.db test-e2e.db

Directory Structure

e2e/
├── tests/                # Test files
├── global-setup.ts       # Starts servers
├── global-teardown.ts    # Stops servers
├── server-utils.ts       # Server utilities
└── playwright.config.ts  # Configuration

Test Pattern

import { test, expect } from '@playwright/test';
import { E2E_BACKEND_URL } from '../playwright.config';

test('example', async ({ page, request }) => {
  // API setup
  const res = await request.post(`${E2E_BACKEND_URL}/api/sessions`, {
    data: { provider: 'claude' }
  });
  const session = await res.json();

  // Browser interaction
  await page.goto(`/session/${session.id}`);
  await page.fill('textarea', 'Hello');
  await page.click('button:has-text("Send")');

  // Assertions
  await expect(page.locator('.assistant-message')).toBeVisible({ timeout: 30000 });

  // Cleanup
  await request.delete(`${E2E_BACKEND_URL}/api/sessions/${session.id}`);
});

Selectors

page.locator('[data-testid="x"]')     // By test ID
page.getByRole('button', { name: 'Send' })
page.locator('text=Hello')
page.locator('.class')

Waits

await expect(locator).toBeVisible();
await expect(locator).toBeVisible({ timeout: 30000 });
await expect(locator).toHaveText('Expected');
await expect(locator).not.toBeVisible();

Test Files

File Tests
basic.spec.ts Health, loading
workflow-claude.spec.ts Claude session flow
permissions-claude.spec.ts Permission handling
autoaccept-claude.spec.ts Auto-accept edits
tmux-terminal.spec.ts Tmux sessions