test(driver): branch coverage >=80% on src/driver/{http2,undici}#121
Conversation
Drives the previously-uncovered branches in `src/driver/http2.ts` and
`src/driver/undici.ts` so each file lands at >=80% branch coverage and
the `src/driver` aggregate clears the same bar.
http2.ts: 60.37% -> 81.13% branches.
undici.ts: 70% -> 80% branches.
src/driver overall: 64.38% -> 80.82% branches.
http2 scenarios added:
- host header stripped before sending (server sees only :authority)
- multi-value response headers append (set-cookie array path)
- server-initiated RST_STREAM rejects via the `error` listener
- pre-aborted signal rejects synchronously (queueMicrotask path)
- cached session reuse across sequential requests (bumpIdle on hit)
- recovery when the cached session was destroyed between calls
- idle-timer expiry closes the session, next call opens a fresh one
- dispose() is idempotent and a no-op before any request
undici scenarios added:
- POST forwards body bytes and sets `duplex: 'half'`
- bodyless GET omits both `body` and `duplex`
- request.signal forwards through to the dispatcher
- dispatcher object identity preserved (same reference, not cloned)
- POST/PUT/DELETE method propagation
- request.redirect propagation
- ensureFetch caches the import across concurrent requests
- real-undici end-to-end POST (covers dynamic-import branch)
- real-undici non-2xx surfaces as HTTPError
- error path when undici exposes no `fetch` (line 81 throw)
Server-side `stream.on('error', ...)` swallows the expected
RST_STREAM / abort errors during teardown so they don't surface as
unhandled exceptions on the http2 server.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bench results
Local Node HTTP server, Apple-class GitHub runner. Numbers fluctuate ±2-3% from runner heat alone — only sustained >5% deltas are signal. |
The test referenced `followRedirects: false`, which is not a valid MisinaOptions key — typecheck failed. Use `redirect: "follow"` to get the same effect (driver receives the original redirect field instead of misina intercepting it). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Driver test coverage looks solid: real http2 server (with proper socket cleanup destroying every accepted socket on teardown — necessary because Http2Server.close lacks closeAllConnections), real http listener for undici. Branch coverage hits the targets (http2 81.13%, undici 80%, driver/ 80.82%). Tests exercise real async paths: RST_STREAM via stream.close(0x02), abort via DOMException AbortError, ensureFetch concurrent-import branch, dispatcher identity propagation, multi-value set-cookie via Headers.append. Disposal is tested for idempotency and pre-request no-op. Caught and fixed one issue: a test referenced followRedirects (not a real MisinaOptions field) — replaced with redirect: 'follow'. Full suite 932/932 green after fix. |
* test(driver): cover undici pool / http2 socket / abort branches
Drives the previously-uncovered branches in `src/driver/http2.ts` and
`src/driver/undici.ts` so each file lands at >=80% branch coverage and
the `src/driver` aggregate clears the same bar.
http2.ts: 60.37% -> 81.13% branches.
undici.ts: 70% -> 80% branches.
src/driver overall: 64.38% -> 80.82% branches.
http2 scenarios added:
- host header stripped before sending (server sees only :authority)
- multi-value response headers append (set-cookie array path)
- server-initiated RST_STREAM rejects via the `error` listener
- pre-aborted signal rejects synchronously (queueMicrotask path)
- cached session reuse across sequential requests (bumpIdle on hit)
- recovery when the cached session was destroyed between calls
- idle-timer expiry closes the session, next call opens a fresh one
- dispose() is idempotent and a no-op before any request
undici scenarios added:
- POST forwards body bytes and sets `duplex: 'half'`
- bodyless GET omits both `body` and `duplex`
- request.signal forwards through to the dispatcher
- dispatcher object identity preserved (same reference, not cloned)
- POST/PUT/DELETE method propagation
- request.redirect propagation
- ensureFetch caches the import across concurrent requests
- real-undici end-to-end POST (covers dynamic-import branch)
- real-undici non-2xx surfaces as HTTPError
- error path when undici exposes no `fetch` (line 81 throw)
Server-side `stream.on('error', ...)` swallows the expected
RST_STREAM / abort errors during teardown so they don't surface as
unhandled exceptions on the http2 server.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(review): replace nonexistent followRedirects with redirect: follow
The test referenced `followRedirects: false`, which is not a valid
MisinaOptions key — typecheck failed. Use `redirect: "follow"` to get
the same effect (driver receives the original redirect field instead of
misina intercepting it).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Drives previously-uncovered branches in
src/driver/http2.tsandsrc/driver/undici.tsso each file lands at >=80% branch coverage and thesrc/driveraggregate clears the same bar. No source changes — tests only.Coverage (before -> after, branches)
src/driver/http2.tssrc/driver/undici.tssrc/driver/overallMeasured via
pnpm vitest run --coverage --coverage.include='src/driver/**'.Scenarios added
http2.ts::authority)errorlistenerdispose()is idempotent and a no-op before any requestundici.ts:duplex: 'half'bodyandduplexrequest.signalforwards through to the dispatcherrequest.redirectpropagationensureFetchcaches the import across concurrent requestsHTTPErrorfetchTest plan
pnpm vitest run test/driver-undici.test.ts test/driver-http2.test.ts— 30/30 passpnpm vitest run— full suite 932/932 pass (twice in a row)pnpm lint— no new errors introducedpnpm fmt— formatted clean1ba17a7pattern)🤖 Generated with Claude Code