Skip to content

feat(test): bootstrap unit tests for auth helpers + geocoder classifier#4

Merged
yorickdewid merged 3 commits into
mainfrom
feat/bootstrap-tests
May 13, 2026
Merged

feat(test): bootstrap unit tests for auth helpers + geocoder classifier#4
yorickdewid merged 3 commits into
mainfrom
feat/bootstrap-tests

Conversation

@yorickdewid

Copy link
Copy Markdown
Contributor

Summary

First tests in the repo. Targets the three pure functions where a regression would silently corrupt behaviour — drift in the hash format means every authed request 401s; drift in the classifier means a BU01234567 might silently join on the wrong column and return wrong building data on a billable call.

Bun's built-in test runner — zero new dependencies, no jest/vitest setup.

Coverage

Function Cases What it pins
extractKey 7 Bearer-only policy (explicit assertions that X-API-Key and AuthKey are NOT recognized), case-insensitivity, whitespace tolerance, empty-token rejection
sha256Hex 3 FIPS 180-4 vector for "abc"; output shape (64 lowercase-hex chars)
sha256Base64Url 3 Same hash bytes encoded per @better-auth/api-key's defaultKeyHasher (43 chars, no padding, base64url alphabet — guards against encoder drift to standard base64)
detectFormat 18 Every supported format + every deliberately-unsupported format (CBS WK/GM, malformed BU codes, empty string, random strings)

32 tests / 37 assertions, run in 48ms.

Scope deliberately limited to pure functions

DB-touching tests (resolveKey, resolveBuildingExternalId, resolveNeighborhoodId) are out of scope for this PR. They need fixture setup and a separate decision on test-DB strategy (transactional rollback vs ephemeral schema vs mocked sql). Landing the unit-test foundation first so the next contributor doesn't bounce off "where do I even start" — they can either add more pure-function tests in the same shape, or pick up the DB-fixture problem as a separate effort.

Test exports

To make the helpers testable without forcing them through authMiddleware / resolveBuildingExternalId, four internal functions are now exported: extractKey, sha256Hex, sha256Base64Url, detectFormat. Also exported the IdFormat type so the test table can be typed. No runtime behaviour change.

Wiring

  • package.json now has bun test and bun run typecheck scripts so CI can call them by name without baking the bun incantation into the workflow.
  • CLAUDE.md Common Commands section updated to list both.

Test plan

  • bun test → 32 pass, 0 fail
  • bun run --bun tsc --noEmit clean
  • Service still boots: fundermaps-webservice.service restarts cleanly post-rebuild

🤖 Generated with Claude Code

First tests in the repo. Targets the three pure functions where a
regression would silently corrupt behaviour:

- extractKey (7 cases) — pulls fmsk.… out of `Authorization: Bearer …`.
  Pins the policy that Bearer is the only accepted shape; explicitly
  asserts X-API-Key and AuthKey are NOT recognized (matches the
  9485134 + 257d98e header removals).

- sha256Hex (3 cases) — pinned to the FIPS 180-4 test vector for "abc".
  Asserts exactly 64 lowercase-hex chars. Drift here would break legacy
  application.auth_key validation silently.

- sha256Base64Url (3 cases) — pinned to the same SHA-256 bytes encoded
  per @better-auth/api-key's defaultKeyHasher (base64url no-padding,
  43 chars). Asserts the output uses the base64url alphabet (- and _),
  not standard base64 — guards against encoder drift that would silently
  break BA-issued key validation.

- detectFormat (18 cases) — table-driven over every supported and
  unsupported ID format. Includes the deliberately-unsupported CBS
  WK/GM codes returning "unknown" (matches the recent classifier
  cleanup), and the case/whitespace normalization branches.

DB-touching tests (resolveKey, resolveBuildingExternalId,
resolveNeighborhoodId) are out of scope for this PR — they need
fixture setup and a separate decision on test-DB strategy (transactional
rollback vs ephemeral schema). Leaving as a follow-up so the unit test
foundation can land first.

Wires `bun test` and `bun run typecheck` into package.json scripts so
both are runnable from CI without remembering the exact bun incantation.
Wires the bun test + typecheck scripts (just added in the previous
commit) into CI. Runs on every PR and on push to main.

oven-sh/setup-bun@v2 is the official Bun setup action.
--frozen-lockfile keeps bun.lock authoritative; a stray dependency
change without a lockfile bump fails the install step rather than
silently picking a newer version on CI.
@yorickdewid yorickdewid merged commit e9f8e6c into main May 13, 2026
1 check passed
@yorickdewid yorickdewid deleted the feat/bootstrap-tests branch May 13, 2026 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant