Skip to content

Testing

This page covers running the test suite, the two kinds of test, and the gaps.

Terminal window
pnpm test # every workspace with a test script
pnpm --filter app test # the app only (vitest run)
pnpm --filter app test src/graph # files whose path matches

The root pnpm test runs pnpm -r --if-present test. That covers two workspaces:

Workspace Runner Files
apps/app Vitest (vitest run), using apps/app/vite.config.ts 46
packages/bluesky_to_graph Node’s test runner (tsx --test src/*.test.ts) 2

There is no separate Vitest config. vite.config.ts loads the root .env into process.env, so the integration tests get VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY and SUPABASE_SECRET_KEY without ./scripts/supa. Running them through ./scripts/supa pnpm test also works.

Test files sit next to the code they test, named *.test.ts (or *.test.tsx for one that renders JSX).

39 files in apps/app test pure functions with no database. The main groups:

  • graph algorithms: graph/ (betweenness, communities, weight modes, connection rules, and the progressive reveal’s worked example in modes.test.ts)
  • import and export parsing: server/lib/map-io/ (CSV, GraphML, internal JSON, the /changes payload, the upsert plan)
  • visualiser helpers: components/map-visualiser/lib/ (appearance, including Bridges sizing; force adapter; node painting, including selection emphasis; PNG export; saved-view naming; config; force parameters; the “What you’re looking at” sentences in describe-view.test.ts), and the raw view parameters panel (raw-view-parameters.test.tsx)
  • editor and table helpers: components/map-editor/ (including the editor’s description, describe-canvas.test.ts), components/map-table/lib/
  • the About this map panel: components/map-workspace/about/ (sentence helpers, panel height, and recipe markdown, rendered to a string with renderToStaticMarkup)
  • the recipe: server/lib/map-recipe.test.ts (planRecipeSave, and the split between data and layout event types)
  • shared helpers: lib/ (connection dates, CSV conventions, value formatting, the view parameters schema)
  • public API request parsing and key hashing: server/api/v1/request.test.ts, server/lib/api-key-crypto.test.ts

server/lib/pagination.test.ts uses a real supabase-js client with a stubbed fetch, so it checks the PostgREST requests fetchAllRows sends without a network call.

Nine files named *.integration.test.ts run against the shared dev Supabase project. They create real users with the service-role client, sign them in with the publishable key, and create orgs, maps and data. Each run tags its rows with a runId timestamp and deletes them in afterAll. A run that crashes can leave rows behind.

There is no per-branch database. Two people running the suite at once share the same project, and a migration you haven’t pushed isn’t there (see Development environment).

File Covers
server/lib/authz.integration.test.ts The RLS helpers and app-schema policies: membership, roles, the roster, invitations, public and private maps.
server/functions/manual-editing.integration.test.ts The network RPCs, composite FKs, catalogue rules and map scoping, RLS between orgs, the getGraph and unplaced-node query shapes, change capture, property promotion and connection dates.
server/functions/tag-groups.integration.test.ts Moving tags into and out of groups: a clash is refused, naming the nodes, and changes nothing; a deleted group keeps its tags; group names are unique; tag icons and colours reach the browser and survive a duplicate.
server/lib/map-io/map-io.integration.test.ts Export loading and import for internal JSON, GraphML and CSV bundles, including field mapping, value columns and dates.
server/api/v1/auth.integration.test.ts API key to org resolution: bad keys, cross-org maps, soft-deleted orgs, removed members, key hash access.
server/api/v1/v1.integration.test.ts The public API’s GraphML export and upsert import through the real handlers.
server/api/v1/v1-1.integration.test.ts The public API’s maps, fields, /changes and create_fields endpoints.
server/api/v1/v1-views.integration.test.ts The view endpoints: the CK progressive reveal built from tag names, read back with its descriptions; repeat requests; patch, null and reset; unknown names; a shared name; another map’s view and another org.
server/api/v1/v1-recipe.integration.test.ts The recipe endpoints, and staleness: API writes (including no-ops), value-type changes and editor changes without a session make it stale; layout changes don’t. Also the save conflict check and cross-org access.

The integration tests call library functions that take a Supabase client (readMapFields, ingestGraph and similar) or the v1 handlers with real Request objects. They don’t go through createServerFn.

A createServerFn handler can’t run outside the TanStack Start runtime, because it needs the request context that holds the cookie-bound client. So no test exercises logic that lives only inside a handler. That includes:

  • the guard that stops removeMember or changeMemberRole removing an org’s last org_admin
  • acceptInvitation’s branches: already a member, expired, email mismatch
  • setting map_id and user_id on service-role writes

To make handler logic testable, move it into a function that takes a Supabase client and call that from the handler, as fields.ts and server/lib/map-io/ do.

There are no interactive component tests or end-to-end browser tests.

.github/workflows/ci.yml runs pnpm check, pnpm typecheck and pnpm build on every pull request and push to main. It doesn’t run the tests. Run pnpm test yourself before opening a pull request.