2.7 KiB
2.7 KiB
conformance
Purpose
Builds a paired client/server harness over an in-process MessageChannel
for conformance tests. The harness is intended for use by every Stage-3
worker-proxy package (api-db-worker-proxy, api-events-worker-proxy,
api-secrets-worker-proxy, api-jobs-worker-proxy,
api-logger-worker-proxy, and any successor) so each proxy can verify
its capability semantics over a real MessagePort round-trip without
re-implementing setup boilerplate.
The harness exposes the live client, server, and ports handles
plus a dispose() that tears them all down in the correct order
(client first, then server, then port). Tests typically wrap it in a
finally-style block or per-test setup/teardown.
Features
- Single-call paired construction: pass a handlers factory, get a fully wired client/server/ports triple back.
- Idempotent
dispose()— safe to call inside a test cleanup hook even if the test already closed parts of the harness. - Exposes the underlying
RawWorkerRpcClientso streaming tests can attach aStreamDispatchervia the client'sonStreamFrameoption.
Usage: Basic
import { runWorkerRpcConformance } from "@suaveplan/api-worker-rpc/testing";
const h = runWorkerRpcConformance(() => ({
ping: () => "pong",
}));
await expect(h.client.call("ping", [])).resolves.toBe("pong");
h.dispose();
Usage: Advanced
import { StreamDispatcher, streamRequest } from "@suaveplan/api-worker-rpc/streaming";
import { runWorkerRpcConformance } from "@suaveplan/api-worker-rpc/testing";
const h = runWorkerRpcConformance(() => ({
rows: async function* () {
for (let i = 0; i < 5; i++) yield i;
},
}));
const dispatcher = new StreamDispatcher();
// Re-wire onStreamFrame on the underlying client — note: in practice you'd
// construct the client with this option from the start. The harness ships
// without it so test authors can choose whether streaming is exercised.
h.dispose();
API Reference
interface ConformanceHarness { client, server, ports, dispose }.runWorkerRpcConformance(factory: () => WorkerRpcHandlers): ConformanceHarness.
Implementation Notes
- The default harness does NOT install a
StreamDispatcher— streaming tests construct their own client with the dispatcher'sdispatchmethod wired intoonStreamFrame, then use the harness's ports directly. This keeps the non-streaming path one-line. - The
clientfield is aRawWorkerRpcClient, not the typed proxy — conformance tests address methods by string and inspect raw frames rather than relying on TypeScript inference. dispose()tolerates partial-prior-closure so per-testafterEachcan call it unconditionally.