with one click
e2e
End-to-end tests — full stack, multi-service flows, browser testing.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
End-to-end tests — full stack, multi-service flows, browser testing.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
Visual-design discipline for forge frontends — brief the work before building (never invent an aesthetic without user input), declare the design system before coding, lean on the component library, use restrained color/type systems, never hand-draw complex SVGs, and verify visually before declaring done.
Write Next.js frontends — generated hooks, component library, Tailwind v4, visual verification, and Connect RPC clients.
Outbound boundary translators. One adapter per third-party system / queue / storage backend; narrow interface, vendor-neutral callers.
Write Connect RPC handlers — proto-driven codegen, the thin-translation handler pattern (validate, extract auth, convert proto↔internal, call service, wrap errors via `svcerr.Wrap`), middleware, and testing. Business logic lives in `internal/handlers/<svc>/contract.go`, never in handlers.
Forge project conventions and architecture — project structure, generated vs hand-written code, the generate pipeline, proto annotations, contracts, wiring, and naming.
Use-case orchestrators that compose two or more adapters/services. Deps are interfaces only — designed for unit tests with all-mock collaborators.
| name | e2e |
| description | End-to-end tests — full stack, multi-service flows, browser testing. |
E2E tests exercise the full running stack — real services, real database, real network calls between services. They live in the e2e/ directory and validate multi-service flows as a user or client would experience them.
The full stack must be running before you execute e2e tests. Don't hand-roll the stack with kubectl apply or a bespoke compose file — forge up --env=<env> builds every service, brings up the compose-managed infra, and deploys each service to its declared target in one command:
forge up --env=dev # in one terminal — builds + infra + deploys all services
forge test e2e # in another terminal — runs e2e suite
If your services span multiple clusters, you don't script that yourself: each service's deploy block names its own K8sCluster (the cluster field is its kubectl context), and forge up routes each service to its context. A cross-cluster e2e flow is just real Connect clients talking to services that happen to live in different contexts.
forge test e2e # all e2e tests
forge test e2e --service <name> # target a specific service's e2e tests
forge test -V # verbose output for debugging
E2E tests verify cross-service behavior over real Connect RPC calls. A typical test might:
Use real Connect clients pointed at the running stack — mock nothing internal at this level. The only legitimate mock in an e2e test is a third-party boundary you don't own (a payment sandbox, an upstream provider); everything inside your system stays real.
Auth at the e2e tier: most flows can ride the dev-auth bypass (a synthetic dev token) to skip the login dance. But if the flow under test IS the auth path — login, token validation, role/tenant gating — turn the bypass off and drive a real token. An auth e2e test that runs under the bypass tests nothing.
E2E tests are the most flake-prone level. Follow these rules strictly:
time.Sleep() to "wait for it to settle" is always wrong. Poll the real state with a short interval (50–100ms) and a tight overall timeout (a few seconds), and fail with the last observed state. Once the infra is up, e2e tests should be fast — they wait for convergence, not for a wall-clock guess.t.Cleanup() for everything — every resource created must be cleaned upWhen an e2e test fails, the stack is still running. You can attach a debugger:
forge debug start
Inspect logs, database state, and service health while the failure is reproducible.
When the stack spans multiple clusters (a secondary k3d cluster joined to the
primary's docker network) and a workload is stuck Pending / not-ready, or a flow
that passes in single-cluster dev fails here — read the pod's STATUS before the
network layer. The failure is almost always image-pull or node-setup, not app
logic. See the forge/debug/multi-cluster-e2e skill for the pod-status-first
discipline, the hold-on-fail pattern, and the nested-cluster gotchas (registry
mirror not loaded, host-gateway DNS missing on the secondary, path-MTU dropping
TLS handshakes).
For UI-level end-to-end tests:
t.Skip() and link an issue referenceIf a scenario can be fully tested with mocked Connect clients and doesn't need the live stack, write it as an integration test instead. Reserve e2e for flows that genuinely require multiple running services.