3.1 KiB
testing
(no submodules)
Purpose
This module provides the in-memory test harness for
@suaveplan/api-db-worker-proxy. It exposes createInMemoryAdminDb
— a deterministic AdminDatabaseLike backed by a Map — and
createDbProxyHarness, which pairs that adapter with a real
MessageChannel, a createDbProxyServer on one port, and a
createDbProxyClient on the other. Tests can drive the full
client-port-server-adapter chain end-to-end without a real DB and
without any mocking framework.
The harness exists in src/testing/ (rather than tests/) so it
can be imported by downstream Stage-4 adapter packages from the
package's "./testing" subpath export.
Features
createInMemoryAdminDb({ engine?, seed?, cursorDelayMs? })— a fullAdminDatabaseLikeimplementation includingprepare,transaction, and a syntheticSELECT-CURSOR *that returns anAsyncIterable<MemoryRow>for cursor streaming tests.createDbProxyHarness(opts)— bundles adapter + ports + server + client into one disposable handle.- Tiny command DSL (
INSERT <id>,DELETE <id>,SELECT *,SELECT-CURSOR *,COUNT,SELECT-SCALAR,THROW) chosen so every code path in the proxy can be exercised without parsing real SQL.
Usage: Basic
import { createDbProxyHarness } from "@suaveplan/api-db-worker-proxy/testing";
const h = createDbProxyHarness({ seed: [["a", { v: 1 }]] });
try {
expect(await h.client.query("SELECT *")).toEqual([{ v: 1 }]);
} finally {
await h.client.close();
h.close();
}
Usage: Advanced
To assert that cursor cancellation propagates, set a per-row delay on the in-memory cursor and abort partway through:
const h = createDbProxyHarness({
seed: Array.from({ length: 100 }, (_, i) => [String(i), { i }]),
cursorDelayMs: 5,
});
try {
const ac = new AbortController();
let n = 0;
for await (const _row of h.client.cursor("SELECT-CURSOR *", undefined, {
signal: ac.signal,
})) {
if (++n >= 3) {
ac.abort();
break;
}
}
expect(n).toBe(3);
} finally {
await h.client.close();
h.close();
}
API Reference
createInMemoryAdminDb(opts?): InMemoryAdminDb—AdminDatabaseLikeplusrows: ReadonlyMap<string, MemoryRow>andclosed(): booleanfor assertions.createDbProxyHarness(opts?): DbProxyHarness—{ db, server, client, ports, close() }.InMemoryAdminDbOptions—{ engine?, seed?, cursorDelayMs? }.
Implementation Notes
The in-memory adapter ignores parameter placeholders for INSERT /
DELETE and instead encodes the row key in the SQL string. This is
intentional — the harness exists to exercise the proxy plumbing, not
to validate a real query language. Concrete adapters (Stage 4) ship
their own conformance suites under their own engine semantics.
The harness's close() does NOT call client.close() so tests can
choose between observing graceful close (await client.close()) and
abrupt disconnect (client.dispose(), then harness.close()). Both
paths are first-class.