Skip to content

testing: migrate http.test.ts response-handling → stub HttpClient (comms-e5vm.8) - #16

Merged
GraemeF merged 1 commit into
mainfrom
comms-e5vm.8
Jun 13, 2026
Merged

GraemeF merged 1 commit into
mainfrom
comms-e5vm.8

Conversation

@GraemeF

@GraemeF GraemeF commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Tier-2 migration (comms-e5vm.8), following the event-pump proof (#12, comms-e5vm.2).

Moves ZulipHttp request-shape and response-handling off the shared Bun.serve fixture onto the owned-fake stub HttpClient + effectTest, so status/error/parsing/response-shape handling and the 429 retry policy run deterministically with no socket.

What moved

  • Request-shape (URL build, Basic auth, query string, form-encode, host override, trailing-slash normalisation, bare DELETE) now reads the stub's captured HttpClientRequest.
  • Response-handling (error envelopes, non-JSON non-2xx, schema-mismatch ParseError, downloadRaw/uploadRaw shape + errors) drives canned responses keyed by (method, path).
  • 429-retry end-to-end runs on stub + TestClock via a deterministic settle loop — no real socket off the test clock, so the racy runUnderTestClock adjust-against-the-wire is gone (the multi-retry budget case still advances the clock per retry because each sleep only registers once its 429 lands).

What was deleted

Two happy-path cases that merely duplicated the contract-against-real run (contract.live.test.ts): GET-parses-success-envelope and POST-returns-success-body.

What deliberately stays off the stub

  • Pure-unit tests (rate-limit policy replay, RealmUrl/BotEmail/ApiKey brand validators, decodeUserUploadPath, the ZulipApiError tag) — never touch HTTP, keep their plain Effect.runPromise shape.
  • One irreducible real-socket case — a transport failure from a refused connection producing a genuine platform RequestError (status 0). The in-memory stub can't fabricate a real RequestError without lowering fidelity, so this keeps a real FetchHttpClient against a claimed-then-released port (orchestrator ruling).

The brief referenced an AbortSignal→TCP-teardown long-poll test in this file; that was a conflation — http.test.ts has no long-poll test. That residue belongs to the event-pump (comms-4lz5), not here.

Out of scope (untouched): adapter.test.ts (e5vm.3), bot-dm-guard.test.ts (e5vm.7), the stateful-fake deletion (e5vm.6).

…mms-e5vm.8)

Move ZulipHttp request-shape and response-handling off the shared Bun.serve
fixture onto the owned-fake stub HttpClient + effectTest (the comms-e5vm.2
pattern), so status/error/parsing/response-shape and the 429 retry policy run
deterministically with no socket.

- request-shape (URL build, Basic auth, query string, form-encode, host
  override, trailing-slash, bare DELETE) reads the stub's captured request
- response-handling (error envelopes, non-JSON non-2xx, schema-mismatch
  ParseError, download/upload shape+errors) drives canned responses
- 429-retry end-to-end runs on stub + TestClock via a deterministic settle
  loop (no real socket off the test clock, unlike the old runUnderTestClock)
- delete two happy-path cases that merely duplicated the live contract
  (GET-parses-success-envelope, POST-returns-success-body)

Two tests deliberately stay off the stub: the pure-unit cases (rate-limit
policy replay, brand validators, decodeUserUploadPath, the ZulipApiError tag)
that never touch HTTP, and the one irreducible real-socket case — a transport
failure from a refused connection producing a genuine platform RequestError,
which the in-memory stub cannot fabricate without lowering fidelity. The
brief's reference to an AbortSignal/long-poll teardown test in this file was a
conflation: that residue is the event-pump's (comms-4lz5), not here.
@GraemeF
GraemeF merged commit e70bfbf into main Jun 13, 2026
2 checks passed
@GraemeF
GraemeF deleted the comms-e5vm.8 branch June 13, 2026 11:09
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