2.1 KiB
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 |