Files
familysync/docs/TESTING.md
T

5.0 KiB

Testing

Test framework and setup

Both apps use Vitest (^4.1.8).

App Environment Setup file
apps/api node apps/api/test/setup.ts
apps/pwa jsdom apps/pwa/src/test-setup.ts

apps/api setup (test/setup.ts) registers a global afterEach that truncates list_items, list_shares, push_subscriptions, and lists in FK-safe order after every test. This keeps DB-backed integration tests isolated without requiring a full DB reset between runs. Parallel file execution is disabled (fileParallelism: false) to prevent FK violations when multiple test files share the same MariaDB.

apps/pwa setup (src/test-setup.ts) imports @testing-library/jest-dom for extended matchers and polyfills window.matchMedia for jsdom (required because Zustand's calendarStore calls window.matchMedia at module initialisation time). The timezone is pinned to UTC via env: { TZ: 'UTC' } so date-extraction assertions are deterministic across developer machines and CI.

No additional install step is needed beyond the normal pnpm install at the repo root.

Running tests

All API tests (from repo root):

pnpm --filter @familysync/api test

This is also the command run by pnpm test at the root.

All PWA tests:

pnpm --filter @familysync/pwa test

Watch mode (API):

pnpm --filter @familysync/api test:watch

Single test file:

pnpm --filter @familysync/api exec vitest run tests/routes/lists.test.ts

Type checking (separate from tests — required):

Vitest uses esbuild, which strips TypeScript types at runtime. A test run can pass while tsc reports errors. Always run type checks separately:

pnpm typecheck          # runs tsc --noEmit across both apps
pnpm --filter @familysync/api typecheck
pnpm --filter @familysync/pwa typecheck

Integration tests requiring a real database

Several API tests in apps/api/tests/lib/ and apps/api/tests/routes/ connect to the real dev MariaDB rather than mocking the DB layer. These tests require the dev Docker stack to be running with port 3306 exposed.

Start the dev stack:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d mariadb

Set environment variables, then run:

set -a; . ./.env; set +a
export DB_HOST=127.0.0.1 DB_PORT=3306
pnpm --filter @familysync/api test

DB-backed tests that require this setup include:

  • apps/api/tests/lib/listAccess.test.tsgetAccessibleListIds access-scope queries
  • apps/api/tests/lib/listChangeDispatcher.test.ts — list change dispatcher with real DB rows
  • apps/api/tests/routes/lists.test.ts — full lists API router (creates/deletes real rows)

Pure-logic tests (e.g. apps/api/tests/broker/expand.test.ts, apps/api/tests/lib/rank.test.ts) do not require DB — the afterEach cleanup is a no-op when tables are empty or no DB connection is available.

Writing new tests

File naming and location

App Convention Example
apps/api apps/api/tests/{category}/*.test.ts apps/api/tests/routes/push.test.ts
apps/pwa co-located *.test.ts / *.test.tsx src/components/AppNav.test.tsx

Test categories for apps/api:

  • apps/api/tests/auth/ — authentication middleware and session handling
  • apps/api/tests/broker/ — CalDAV sync, outbox worker, event expansion, push dispatch
  • apps/api/tests/lib/ — pure library functions and service logic
  • apps/api/tests/routes/ — HTTP route integration tests
  • apps/api/tests/health.test.ts — health check endpoint
  • apps/api/tests/fixtures/ — shared .ics fixture files and DB fixture helpers

Test helpers

  • apps/api/tests/helpers/db.tscreateMockDb() returns a Vitest mock of the Drizzle db singleton; also exports sample VEVENT strings (SAMPLE_VEVENT_TIMED, SAMPLE_VEVENT_ALLDAY, SAMPLE_VEVENT_RECURRING_TIMED, SAMPLE_VEVENT_RECURRING_ALLDAY) for broker tests.
  • apps/api/tests/fixtures/*.ics — Raw iCalendar fixture files for broker parsing tests (allday-birthday.ics, exdate-series.ics, single-duration.ics, weekly-count3.ics, weekly-dst.ics).
  • apps/api/tests/fixtures/vapid.ts — VAPID key fixture for push tests.
  • apps/pwa/src/test-setup.ts — Provides matchMedia polyfill and jest-dom matchers for all PWA tests automatically via setupFiles.

For PWA component tests, use @testing-library/react (^16.3.0) render helpers. Import from vitest for assertions — @testing-library/jest-dom matchers are available globally via the setup file.

Coverage requirements

No coverage thresholds are configured in either vitest.config.ts. There is no minimum coverage enforcement in CI.

CI integration

No CI pipeline is configured in this repository. Tests are run manually by developers before opening pull requests against the self-hosted Gitea remote.

The recommended pre-PR gate is:

pnpm test && pnpm typecheck