Skip to content

test(api): blackbox behavior spec for health endpoints (Step 1b)#143

Open
guidefari wants to merge 1 commit into
migration/1a-api-health-contractfrom
migration/1b-health-blackbox-tests
Open

test(api): blackbox behavior spec for health endpoints (Step 1b)#143
guidefari wants to merge 1 commit into
migration/1a-api-health-contractfrom
migration/1b-health-blackbox-tests

Conversation

@guidefari

Copy link
Copy Markdown
Owner

Step 1b, stacked on #142 (merge that first). This is the behavior-preservation approach discussed on the migration doc: a blackbox suite that asserts only the wire contract, so the exact same assertions can run unchanged once health moves to HttpApiBuilder in step 3a.

What

  • decodeResponseBody (packages/api/src/testing.ts): decodes a Response body against a response schema with no decoding-service requirements (Schema.Codec<unknown, unknown, never>). Generic over any schema an endpoint declares for success or error -- reusable regardless of which server implementation produced the response.
  • health.blackbox.test.ts (apps/vps): request/response assertions against the live Hono app (app.request(path), same pattern as the existing music.integration.test.ts). Asserts status codes and body shape via the shared @gbfm/api schemas -- zero knowledge of Hono or Effect internals.

Why blackbox, not implementation tests

The migration's actual risk is behavior drift while internals get swapped (Hono→Effect router, Zod→Schema, handlers rewritten). A suite that only asserts the new implementation's internals proves nothing about whether it still behaves like the old one. This suite is the spec: written once against current behavior, later pointed at the ported handler unchanged. If it still passes, behavior was preserved; if not, that's a real regression.

Deliberately not covered here

  • The readiness-failure/500 path and exact cache call-count -- both need a seam in app.ts (e.g. injectable DB check) that this contract-only step doesn't touch. Revisit once step 3a's handler port gives us that seam.

Verification

  • bun --filter='@gbfm/api' typecheck / bun --filter='@gbfm/vps' typecheck -- clean
  • bun run lint / bun run format:check -- clean
  • apps/vps test: 5/5 passing against a real Hono app + real Postgres (testcontainers)

Next

Step 2a: add HttpRouter.toWebHandler as a second, unused export next to the existing Bun.serve entry point, with HonoFallback routing 100% of traffic through unchanged. No route behavior change.

Step 1b of the Hono -> Effect HttpApi migration
(docs/migration-effect-http-api.md).

- decodeResponseBody (packages/api/src/testing.ts): decodes an HTTP
  Response body against a response schema with no decoding-service
  requirements. Reusable across any server implementation serving
  the same contract.
- health.blackbox.test.ts (apps/vps): request/response assertions
  against the live Hono app (status codes, body shape via the shared
  @gbfm/api schemas). No knowledge of Hono or Effect internals -- the
  same assertions will run unchanged once health is ported to
  HttpApiBuilder in step 3a, proving behavior was preserved.

Deliberately not testing the readiness-failure/500 path or the 5s
cache's internal call count here: forcing a DB failure or observing
call counts needs a seam in app.ts this contract-only step doesn't
touch. Revisit once step 3a gives us handler-level injection.
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