Testing
A four-layer testing strategy — Vitest unit tests, Storybook visual regression, MSW-backed integration tests, and Playwright smoke / full e2e.
The repo's automated test surface splits into four layers, ordered from fastest to slowest:
| Layer | Tool | Where | What it catches |
|---|---|---|---|
| Unit | Vitest 4 | Co-located *.test.ts(x) next to the code | Pure logic, hooks, reducers, route slug parsing |
| Integration | Vitest + Testing Library + MSW | apps/web/src/...test.tsx | Component-level behavior with mocked network |
| Visual regression | Playwright + Storybook | apps/web/src/**/*.visual.spec.ts via playwright.config.ts | Pixel diff against committed snapshots |
| End-to-end (smoke) | Playwright | apps/web/e2e/smoke/ | Unauthenticated + authenticated landing pages on real preview |
| End-to-end (full) | Playwright | apps/web/e2e/full/ | Business flows (login, onboarding, chat) on real preview |
Each layer is documented in its own page:
- Playwright tiers — smoke / full / visual / preview / local configs
- Storybook topology — five Storybook installs across the repo
- MSW handlers and fixtures — how the mock layer is structured
Vitest unit tests
Unit tests live next to the code under test:
src/lib/foo.ts
src/lib/foo.test.tsVitest 4 (catalog) with happy-dom or jsdom as the default environment depending
on the package. apps/web uses happy-dom; design-system/ui uses jsdom for
features happy-dom doesn't implement (e.g. specific MediaQueryList behavior).
Run via:
pnpm test # all projects, via Moon
pnpm --filter @todayai-labs/web test # one project
pnpm --filter @todayai-labs/web test --watch # interactiveCI's Unit Tests check runs moon run :test and currently completes in ~30s
across 200 test files / 2,095 tests.
Coverage thresholds
Currently not enforced. Tracked as a tier-2 improvement in TODO.md:
Add
coverage.thresholdstoapps/web/vitest.config.tsanddesign-system/*/vitest.config.tsso regressions show up in CI rather than only in local reports.
Coverage reports are still generated on demand (pnpm --filter @todayai-labs/web test --coverage), they just don't fail the build.
What this repo does not test
- Type-level invariants beyond what TypeScript catches — no
tsd/expect-typesuites. We rely ontsgo --buildfor type safety and don't write tests asserting type shape. - Mutation testing — no Stryker. Test quality is judged by reviewers.
- Cross-browser smoke — Playwright runs Chromium only. Firefox + WebKit for smoke are queued as a tier-2 improvement.
Each absence is deliberate and revisitable; check TODO.md for the current
prioritization.