Repository navigation
test(strategy): stand up the testing trophy and rework the interface - #18
Merged
Merged
Conversation
- vitest.config.ts: two projects, unit (node, src/domain/**) and integration (jsdom, src/ui/** and src/app/**), replacing the vite.config.ts that never had a test block - coverage thresholds (v8 provider): 90% on src/domain, 70% on src/ui, enforced in CI - integration tests for the flows that matter: list products, add to cart, change quantity, remove an item, the free-shipping banner and the "Free" badge, the welcome survey's auto-open/save/close cycle - add the ZustandWelcomeSurveyRepository spec it never had, the third storage implementation now has the same coverage as the other two - Playwright, 2 smoke specs against a built vite preview: home to shop, and add to cart through to the checkout modal. Runs as its own CI job with the report uploaded on failure - CONTRIBUTING.md documents TDD (with two real examples from this repo's own history) and the trophy shape Found and fixed along the way, surfaced by writing real tests against real components: - every umami?.track(...) call site threw ReferenceError whenever the global umami script hadn't loaded (blocked, offline, or simply not present, which is exactly what jsdom is). Switched to window.umami?.track(...), and typed it as a Window property instead of a bare ambient global - tsconfig.json (the app build) was type-checking spec files with none of the vitest/ jest-dom types available, and tsconfig.vitest.json was missing globals.d.ts and vite-env.d.ts, so window and import.meta.env typings weren't visible to it either - every real catalog product costs far more than COMMERCE_CONFIG.freeShippingThreshold, so the "add X more to earn free shipping" banner can never appear against real data. Covered with a mocked, deliberately cheap catalog instead of leaving it untested Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BcGPRc3sgUJYKihGRXh5g
Correctness: - gate TanStackRouterDevtools behind import.meta.env.DEV and lazy-load it, it was shipping to production unconditionally - reportWebVitals() was called with no callback, so its own guard clause made it a no-op forever. Wired it to actually forward Core Web Vitals to Umami - moved the lore video iframe out of ModalDescription (a <p>, invalid HTML for an iframe, and it made the dialog's accessible description empty), gave it a real description, and dropped ?autoplay=1 (WCAG 1.4.2) - AnimatePresence wrapped a single stable-keyed container instead of the cart items themselves, so item exit animations never fired Accessibility: - --ring was too light to pass 3:1 non-text contrast in either theme, darkened both - the modal close button had a ~16px hit area, now 44px with a visible hover state - "Read Lore" was a button that called window.open(), now a real link - the mobile cart toggle gets aria-expanded/aria-controls, the cart is a landmark (<aside aria-labelledby>), the product grid and cart items are real lists - cart items promoted from h4 to h3 (Your Inventory was h2 straight to h4), and their images and the product images go alt="" since the adjacent text already names them - the cart total is aria-live, the free-shipping Free badge got real color contrast Design and layout: - a working light/dark/system theme toggle, using tokens that already existed in styles.css but nothing ever applied - replaced the CRA-era hardcoded hex colors on the header and home page with the site's own tokens - fixed the product grid's premature 3-column squeeze between 1024 and 1280px (xl: instead of lg:), gave the sticky cart a max-height with its own scroll region instead of growing past the viewport, dropped the mt-14 alignment hack - extracted CartSummaryRow, removing ~80 lines of duplicated subtotal/shipping/tax markup from ShoppingCart.tsx - added a footer landmark, first one in the app - deleted dead files: styles/index.css (unimported Vite scaffolding that would have broken the layout if anyone ever did import it), sheet.tsx, input.tsx, react.svg, vite.svg - fixed public/manifest.json, still named "TanStack App", and linked it from index.html Performance: - the first 3 product cards load eagerly with fetchpriority high instead of lazy, they're the ones competing for LCP - preconnect to the image host and to Umami Coverage-worthy new code got its own tests: theme.ts and ThemeToggle. Not done here, called out for later: full i18n extraction (next PR), and the OG image / canonical / hreflang pass (the SEO PR after that). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BcGPRc3sgUJYKihGRXh5g
This was referenced Sep 2, 2026
This was referenced Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #7.
Summary
toggle (light/dark/system, persisted), proper
<main>/<footer>landmarks, a cartsheet on mobile with a sticky summary on desktop, 44px touch targets
focus trap in the welcome modal, lazy images with explicit dimensions to kill layout
shift, reduced motion respected everywhere,
reportWebVitalsactually wired upintegration (UI, jsdom) projects, coverage thresholds enforced in CI, two Playwright
smoke specs against a built preview,
CONTRIBUTING.mddocumenting the shape and theTDD workflow
Test plan
pnpm typecheckpnpm checkpnpm lint:mdpnpm test:coverage, thresholds passpnpm buildpnpm test:e2e🤖 Generated with Claude Code
https://claude.ai/code/session_014BcGPRc3sgUJYKihGRXh5g