# Visual Regression Testing

## Objective

Catch unintended visual changes before they reach users, not after.

An automated comparison of rendered screenshots against approved baselines, run on every change.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Identify the surfaces where a silent visual change would actually hurt — the shared components, the pricing table, the checkout, the dashboard — and capture those rather than screenshotting every route in the app.
2. Freeze everything that varies between runs before capturing: load fonts and wait for them, fix the clock to a known instant, disable animations and transitions, and render from seeded fixtures rather than live data.
3. Capture each surface in every theme and at every viewport the app claims to support, and label each capture with that combination so a diff says exactly which one moved.
4. Fail the run on a diff and require a human to look at it, but make approving a genuine change a single deliberate action rather than a reason to disable the check.
5. Storage, review, ownership, and expiry of the approved images belong to Screenshot Diff Baselines; this brief owns capture, stabilisation, and comparison. Do not build a second baseline store here.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Unstable input produces diffs that mean nothing — a system font substituting for a web font, a relative timestamp ticking over, a spinner caught mid-rotation, or a random fixture name will all fail a run that should have passed.
- A component that looks right in light mode at desktop width can be broken in dark mode on a phone, so a matrix that captures one theme at one viewport is a matrix that misses most regressions.
- The run must make an intentional redesign distinguishable from flake, or reviewers learn to approve everything without looking and the suite stops protecting anything.
- Granularity has to be chosen deliberately: whole-page shots turn one button change into forty diffs, and component-only shots miss layout collisions that only appear when components sit together.
- Anti-aliasing and sub-pixel text rendering differ between machines, so a comparison with a zero-tolerance threshold will fail on a developer laptop even when nothing changed.
- Content that legitimately varies in height — a truncated description, an error banner, a lazily loaded image — must be settled before capture, or the shot records a mid-load frame.
- A newly added surface has no baseline. Treat the first capture as pending review rather than an automatic pass.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] Fonts, dates, animations, and fixture data are deterministic, and re-running the suite on an unchanged codebase produces no diffs.
- [ ] Every captured surface exists in each supported theme and viewport, and the diff report names the combination that changed.
- [ ] A visual difference fails the run and blocks the merge until a person reviews it.
- [ ] The capture set covers both isolated components and the assembled pages they appear on.
- [ ] Approved images are read from the baseline store defined by Screenshot Diff Baselines rather than a second copy kept here.
- [ ] A surface with no baseline is reported as new and awaiting review, never silently passed.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
