Dev notes
640+ tests (623 unit + 17 e2e) — Vitest, Testing Library, MSW, and Playwright. Pure functions first, then hooks with fetch mocking, with a specific technique for proving that optimistic updates actually fire before the server responds.
One principle that should be followed and be non-negotiable is Test-Driven Development (TDD). This codebase, before the change, had zero test files. The goal was to close that gap by targeting the parts of the codebase that are actually worth testing: the rate limiter, the calendar layout algorithm, the vitals formatting, and the hooks with their optimistic update behavior.
renderHook and waitFor — both are needed for anything that touches React QueryonUnhandledRequest: "error" so any fetch without a registered handler fails the test immediately instead of silently passingnext/server and Auth0 and require a Next.js runtimeThe first attempt at testing optimistic updates used a fetchCount variable to make the GET handler return different data on first vs subsequent calls. It worked, but it was testing the wrong thing — it verified the end state after a completed mutation cycle, not whether the cache updated before the server responded.
The fix is delay() from MSW. Add a 300ms pause to the POST/PUT/DELETE handler, then fire the mutation without awaiting it. The mutation is still in-flight when the assertion runs, so the test is checking the actual optimistic state — what the user sees before the server has responded.
The calendar's layoutDayEvents function takes a list of same-day timed events and assigns each one a column index and a total column count, so they can be absolutely positioned side by side in the time grid. The tests cover: a single event gets column 0 of 1, two non-overlapping events share column 0, two overlapping events get separate columns, three simultaneous events get three columns each reporting totalColumns: 3, and pixel positions derived from the row height constant. This is the kind of logic that looks simple but has enough edge cases to be worth specifying in tests.
Tests only matter if they run automatically. A GitHub Actions workflow runs typecheck and the full unit suite on every push to main and develop, and on every PR targeting main. A second job runs after the first passes: it installs Chromium, boots the dev server, and runs the public Playwright suite — which includes axe-core accessibility scans on the landing page, TCG browser, and card detail page. A WCAG 2.1 AA violation blocks the merge just like a failing unit test. Vercel deploys are gated on both checks passing.
Every test uses factory functions instead of shared fixtures. makeEvent(), makeCountdown(), and makePage() accept optional overrides and return fresh objects with randomized IDs. No let declarations, no beforeEach mutations. Each test constructs exactly what it needs and nothing is shared between tests.