test(client): unit coverage for the off-origin URL rewriter + middleware contract #233
Labels
No labels
area:auth
area:ci
area:db
area:infra
area:native
area:pwa
area:service
epic
feature
foundation
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
james/carol#233
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Context
PR #232 fixed four separate bugs in
apps/client/lib/apiClient.ts's off-origin URL rewriter that surfaced when running the universal client on a real Android device via Expo Go:new URL(originalUrl)threw on relative paths — RN's whatwg-fetch keeps relative inputs literal, so the rewriter silently no-op'd and the request went to whatever bundle origin RN happened to resolve. Manifested as 404s on login.new Request(next, request)didn't transfer the body stream via RN's polyfill — server saw empty body, parsed it as invalid JSON. Manifested as"invalid_body"on every POST.onRequest/onResponsemiddleware tripped openapi-fetch'sinstanceof Request/instanceof Responsecheck on RN's polyfill class identity. Manifested as"onResponse: must return new Response() when modifying the response".headers: request.headerspassed aHeadersinstance to RN's Request constructor — RN's polyfill doesn't iterate that correctly, the Authorization header set by authMiddleware disappeared, every authenticated GET returned 401. Manifested as the post-login bounce-back.All four are unit-testable in pure JS — the rewriter is a pure function and the middleware contract is observable from the outside. They'd have been caught by tests against RN's whatwg-fetch polyfill before reaching a device.
Source
Follow-up from the PR #232 debugging cycle.
Scope
rewriteRequestUrlfromapps/client/lib/apiClient.tsfor testing (or extract it to a sibling module — your call; the existing file already exportsapiClientso a sibling keeps the boundary clean).apps/client/tests/apiClient.test.tscovering:rewriteRequestUrlwith an absolute URL → splice the configured base over the path.rewriteRequestUrlwith a relative URL starting with/→ splice the configured base directly (the RN path).rewriteRequestUrlwith a foreign absolute URL → pass through.rewriteRequestUrlwith no configured base → pass through.apps/client/tests/orpackages/api-client/tests/. Construct acreateApiClientinstance with a fixturefetchstub, install the rewriter + auth middlewares, fire a request, and assert:Authorizationheader is the onegetAuthHeaderreturned.CarolApiError.The test environment needs to spec the same Request / Response / Headers shape RN ships. Vitest's
happy-domorjsdomboth satisfy that surface; pick whichever matches whatapps/client's test suite already uses.Acceptance criteria
pnpm -F @carol/client teststays green.Out of scope
packages/api-client's test surface.Composes with
Part of
#176