playwright-e2e
World Pulse: When writing or modifying end-to-end tests for the web frontend (or Electron app) in the project's Playwright test suite.
SKILL.md.claude/skills/playwright-e2e/SKILL.md
GitHubPlaywright E2E Test
When to use: When writing or modifying end-to-end tests for the web frontend (or Electron app) in the project's Playwright test suite.
Setup
Run E2E tests with:
npm run test:e2e
Playwright is configured in playwright.config.ts (root). Tests live alongside source or in a dedicated e2e/ directory.
Test Isolation
Each test must be fully independent — no shared state between tests:
import { test, expect } from '@playwright/test';
test('dashboard renders the globe', async ({ page }) => {
await page.goto('/');
await expect(page.locator('canvas')).toBeVisible();
});
Use page.goto('/') at the start of every test that needs a fresh page state.
Selectors
Prefer accessible selectors in order:
getByRole— most resilient to DOM changesgetByText— for visible labelsgetByTestId— adddata-testidattributes sparingly and only for E2E use
Avoid CSS class selectors — Tailwind class names change.
Async Patterns
Always await Playwright actions and assertions. Use expect(locator).toBeVisible() rather than manual wait loops:
// Good
await expect(page.getByText('CONNECTED')).toBeVisible({ timeout: 5000 });
// Bad — polling manually
while (!(await page.getByText('CONNECTED').isVisible())) { ... }
Electron E2E
For Electron-specific tests, use the electron launch helper from @playwright/test:
import { _electron as electron } from 'playwright';
test('Electron window opens', async () => {
const app = await electron.launch({ args: ['dist/main/main.js'] });
const window = await app.firstWindow();
expect(await window.title()).toBe('World Pulse');
await app.close();
});
Build the app before running Electron E2E (npm run build:electron).
CI Integration
E2E tests run separately from unit tests. In CI:
- Unit tests:
npm run test:coverage(Vitest) - E2E tests:
npm run test:e2e(Playwright, requires a running server orwebServerconfig)
Configure webServer in playwright.config.ts to start the dev server automatically:
export default defineConfig({
webServer: {
command: 'npm run dev:renderer',
url: 'http://localhost:5173',
reuseExistingServer: !process.env.CI,
},
});
Anti-Patterns
- Do not use
page.waitForTimeout()— useexpect(locator).toBeVisible()with a timeout. - Do not share browser state across tests via module-level variables.
- Do not write E2E tests for logic that unit tests can cover — E2E is for user-visible behavior.
- Do not hard-code ports — use environment variables or the
webServerconfig.