Skip to main content

Playwright E2E Testing

End-to-end tests validate the client PWA and admin dashboard using Playwright, with fixtures for Anvil fork interaction and mock-based critical path testing.

How To Approach Tests

Playwright E2E tests verify complete user journeys through the browser — from page navigation to blockchain interaction. The philosophy is to keep E2E tests focused on critical paths, using mock-based CI variants for speed and Anvil fork variants for fidelity.

Test Directory Structure

Tests live in the tests/ directory at the monorepo root:

tests/
fixtures/ # Anvil fork, contract helpers, config
helpers/ # Shared test utilities
mocks/ # Pimlico bundler/paymaster mocks
specs/ # Test specifications
global-setup.ts # Pre-test environment bootstrap
global-teardown.ts

Test Projects

The config defines several Playwright projects for different testing scopes:

ProjectMatchesPurpose
client-ciclient.smoke.spec.ts, client.*.ci.spec.tsClient lane smoke and critical client specs
admin-ciadmin.smoke.spec.ts, admin.production-flows.ci.spec.tsAdmin lane smoke and production-flow specs
chromiumadmin*.spec.tsManual admin dashboard tests
chromium-clientclient.smoke.spec.tsManual client smoke tests
critical-path*.ci.spec.tsManual mock-based critical UI flows
performanceperformance.spec.tsLoad time and resource checks
anvil-fork*.fork.spec.tsTests with local Anvil fork (60s timeout)
passkey-mock*.passkey.spec.tsPasskey E2E with mocked Pimlico
client-fullclient*.spec.tsFull client suite (optional)

Mobile projects (mobile-chrome, mobile-safari) exist in the config, but the normal repo entry points use the explicit root scripts below rather than relying on those projects implicitly.

Web Server Configuration

Playwright config (playwright.config.ts) always starts the Envio indexer on port 8080 unless SKIP_WEBSERVER=true is set. App servers are selected with PLAYWRIGHT_APP: PLAYWRIGHT_APP=client starts the client on 3001, PLAYWRIGHT_APP=admin starts the admin on 3002, and an unset value starts both apps for broader local runs.

Completing Test Coverage

Spec Conventions

Spec files follow the naming pattern {package}.{feature}.spec.ts:

  • client.navigation.spec.ts -- Client routing and page transitions
  • client.work-submission.spec.ts -- Full work submission flow
  • admin.auth.spec.ts -- Admin authentication and role checks
  • client.offline-sync.spec.ts -- Offline-first behavior and sync

CI-specific variants (*.ci.spec.ts) use lightweight mocks instead of real infrastructure, enabling faster and more reliable CI runs.

Test Fixtures

Anvil Fork Fixture

The anvil-fork.ts fixture spawns a local Anvil process forking from Sepolia, providing:

  • testClient -- Anvil manipulation (mine blocks, set balances, impersonate)
  • publicClient -- Read operations against forked state
  • walletClient -- Write operations with test accounts
const context = await startAnvilFork();
try {
await context.testClient.setBalance({
address: TEST_ACCOUNTS.gardener1.address,
value: parseEther('100'),
});
// ... test blockchain interactions
} finally {
await context.cleanup();
}

Contract Helpers

The contract-helpers.ts fixture provides deployment artifact types and utility functions for interacting with deployed contracts during E2E tests. It reads addresses from packages/contracts/deployments/{chainId}-latest.json.

Running Tests

# Standard local wrapper
bun run test:e2e

# Smoke suite
bun run test:e2e:smoke

# Fork / passkey / testnet variants
bun run test:e2e:fork
bun run test:e2e:passkey
bun run test:e2e:testnet

# Direct Playwright usage when you want a specific project or file
npx playwright test --project=client-ci
npx playwright test --project=admin-ci
npx playwright test tests/specs/client.navigation.spec.ts
npx playwright test --ui

The bun run test:e2e wrapper starts bun run dev, waits for the client and admin surfaces to become reachable, then runs npx playwright test with SKIP_WEBSERVER=true and SKIP_HEALTH_CHECK=true.

Configuration Details

Key settings from playwright.config.ts:

  • Retries: 1 locally, 2 in CI
  • Workers: 4 locally, 2 in CI
  • Traces: Captured on first retry
  • Video: Retained on failure (local only)
  • Screenshots: Only on failure
  • Timeouts: 30s navigation, 15s actions; fork tests get 60s, testnet gets 120s

The global setup (global-setup.ts) bootstraps the test environment, and global-teardown.ts handles cleanup. Both use ESM-compatible imports.

Resources

Next page

Next: Vitest Unit Testing

Learn how to write unit and integration tests for TypeScript packages with Vitest.

Vitest Unit Testing