Files
skills/docs/api-stack/api/api-worker-rpc/src/testing/conformance.md
2026-05-29 08:20:56 +01:00

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 RawWorkerRpcClient so streaming tests can attach a StreamDispatcher via the client's onStreamFrame option.

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's dispatch method wired into onStreamFrame, then use the harness's ports directly. This keeps the non-streaming path one-line.
  • The client field is a RawWorkerRpcClient, 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-test afterEach can call it unconditionally.