| name | testing-end-to-end |
| description | Validate runtime behavior with real end-to-end evidence. Use when a change affects an app, browser surface, API, CLI, workflow, integration, dev server, runtime orchestration, or any user-visible behavior that tests and typechecks alone cannot prove. |
Testing End To End
The rule is evidence over confidence. Typecheck and lint verify code correctness, not feature correctness. They can pass while a page throws at runtime, a query is not deployed, a form never writes back, or a dev command starts on the wrong port.
When a change touches runtime behavior, exercise that behavior end to end before calling the work done.
What Counts As Runtime Surface
Runtime surfaces include browser routes, pages, components, shared UI, forms, navigation, auth-gated flows, loading/empty/error states, APIs, CLI commands, workers, provider integrations, generated artifacts, dev servers, build-system changes, runtime upgrades, local proxies, port routing, process lifecycle, and orchestration scripts.
Unit tests, static screenshots, typecheck, lint, and API calls do not replace runtime proof for a browser-testable workflow. They can complement it.
End-To-End Bar
Before reporting success, prove the changed path in the real surface:
- Define the proof target. Identify the route, command, endpoint, workflow, integration, generated artifact, or local dev command that represents the change. Completion criterion: you know what state a reviewer or user must see to believe the change works.
- Boot the real surface. Use the project's documented local, preview, or dev-stack command. Do not hand-roll a substitute when the project has a canonical runner.
- Use representative state. Prefer the same account, permissions, data shape, route, environment, and workflow the user or reviewer cares about. If the changed state is missing, seed or create it rather than verifying the wrong state.
- Exercise the changed path. Drive the actual workflow, not a fixture or isolated component. Include the interaction that could fail: submit, save, mutate, navigate, toggle, edit a dependent field, upload, approve, revoke, or exercise the loading/empty/error state that changed.
- Check runtime errors. Inspect browser console output, server logs, network failures, command exits, and backend errors after the interaction. Do not eyeball this when tooling can read it.
- Capture evidence. Save screenshots, clips, logs, command output, traces, or generated artifacts that show the intended state. If the change is too small, hidden, or ambiguous, crop, zoom, scroll, seed data, or interact until the evidence is legible.
Browser-Testable Changes
If a user can reach the changed behavior in a browser, run the app and drive it in a real browser.
At minimum, cover:
- One form submission, mutation, or write-back action when the surface writes data. "Page loaded" and "static text rendered" are smoke tests, not an e2e pass.
- One reactive state change when the surface has state: toggle a select, change a date, switch tabs, edit a dependent field, filter, sort, or otherwise prove the dependent UI updates.
- One console/runtime-error check after the interaction.
- At least one screenshot or clip showing the verified state when the change is visual or reviewable through UI evidence.
The capture must visibly include the UI change or interaction state being verified, and it must come from the actual mounted product UI for the relevant route, account, data, and state. Fake, unmounted, unauthenticated, fixture-rendered, mocked, reference, Storybook, or component-only screenshots do not satisfy product evidence unless the task is explicitly about that isolated surface.
For existing UI, capture comparable before/after evidence when practical. For new UI, capture the new state. For motion, transitions, drag-and-drop, optimistic updates, or sequenced state, capture a short clip.
Backend, API, CLI, And Integration Changes
For backend/API/CLI work, call the real endpoint or command path that exercises the change. For writes, cross-check with a read after the write. For permission or runtime boundaries, exercise both allowed and denied paths when that is the changed behavior.
If a browser consumes the changed backend shape, run the backend/API check and a representative browser flow. New unit tests for the backend code do not prove the browser path still works under real interaction.
Dev Tooling And Runtime Orchestration
Dev-tooling, build-system, package-manager, runtime, local proxy, port-routing, and process-lifecycle changes also need an end-to-end smoke. Start the changed command, wait for readiness or capture the exact blocker, exercise the primary local endpoint if it boots, terminate intentionally, and verify no owned processes or listeners remain where applicable.
Recover Before Declaring Blocked
A browser navigation failure, auth bounce, server refusal, missing seed data, provider config gap, stale backend binding, or local port issue is a symptom to diagnose, not a completed blocker.
Before calling verification blocked, try the project's documented recovery path: restore the app/server, confirm the selected URL and port, recover auth if safe credentials or documented flows exist, refresh provider/backend state, seed the needed data, and try an allowed fallback browser/tool path. Only stop when the blocker is genuinely outside the agent's control.
Reporting
Finish with the route/command/API exercised, the actions performed, where the evidence lives, the console/log/error result, and what could not be completed. Do not claim end-to-end verification passed if only tests, typecheck, lint, or a static render ran.