# `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 full `AdminDatabaseLike` implementation including `prepare`, `transaction`, and a synthetic `SELECT-CURSOR *` that returns an `AsyncIterable` for cursor streaming tests. - `createDbProxyHarness(opts)` — bundles adapter + ports + server + client into one disposable handle. - Tiny command DSL (`INSERT `, `DELETE `, `SELECT *`, `SELECT-CURSOR *`, `COUNT`, `SELECT-SCALAR`, `THROW`) chosen so every code path in the proxy can be exercised without parsing real SQL. ## Usage: Basic ```ts 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: ```ts 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` — `AdminDatabaseLike` plus `rows: ReadonlyMap` and `closed(): boolean` for 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.