3.6 KiB
testing/conformance — runSecretsConformance harness
(no submodules)
Purpose
runSecretsConformance is the reusable Vitest suite every concrete SecretsLike implementation in the api-secrets family MUST pass. Stage-4 adapters (api-secrets-env, api-secrets-vault) and The api-secrets-bun adapter all import it, hand it a factory that returns a fresh fixture per scenario, and inherit the cross-package shape guarantees — get returns the value, get returns undefined on miss, require returns the value, require throws SECRETS.SECRET_NOT_FOUND on miss, and list() enumerates seeded names. Centralising the suite means an adapter cannot accidentally drift its semantics from peer adapters without a test failure showing up in its own CI.
The harness is intentionally factory-based so sources that own real resources (testcontainers-backed vault, OS keystore) can seed and tear down per scenario rather than reusing a single instance across the suite.
Features
- Five canonical scenarios covering the four documented behaviours plus
list()enumeration. - Per-scenario fixture factory with optional teardown hook.
- Customisable
isNotFoundpredicate so sources representing missing names differently (network adapter wrapping a transport error) can still pass. - All
it(...)calls carry{ timeout: 5000 }.
Usage: Basic
import { runSecretsConformance } from "@suaveplan/api-secrets/testing";
import { createEnvSecrets } from "./env-secrets.js";
runSecretsConformance({
label: "env-secrets",
factory: (seed) => {
const restore = applyEnv(seed);
const secrets = createEnvSecrets({ allowList: Object.keys(seed) });
return { secrets, teardown: () => restore() };
},
});
Usage: Advanced
Adapt the harness to a source whose missing-name representation differs from the canonical code:
import { runSecretsConformance } from "@suaveplan/api-secrets/testing";
import { VaultTransportError } from "./vault-transport.js";
runSecretsConformance({
label: "vault-secrets",
factory: async (seed) => {
const container = await startVaultContainer({ seed });
return {
secrets: container.secrets,
teardown: () => container.stop(),
};
},
// vault wraps "not found" in a transport-level 404 — recognise it as
// the canonical SECRET_NOT_FOUND for the purposes of the suite.
isNotFound: (err) =>
err instanceof VaultTransportError && err.status === 404,
});
API Reference
function runSecretsConformance(options: RunSecretsConformanceOptions): void— registers a Vitestdescribeblock; call once at module top level.interface RunSecretsConformanceOptions—{ label, factory, isNotFound? }.interface SecretsConformanceFixture—{ secrets, teardown? }.
Implementation Notes
The harness deliberately uses describe/it from @suaveplan/testing/runner rather than importing directly from vitest — that runner wrapper routes to bun:test under Bun's runner condition, so a package whose runtime is browser-tier can still drive its conformance check from a bun test invocation. The default isNotFound matches on the canonical SECRETS.SECRET_NOT_FOUND code string; adapters not extending SecretsError directly must supply their own predicate. Note the harness does not check dispose() — that's intentional, because the canonical api-types SecretsLike shape does not require dispose; adapters that DO own resources should pair the conformance run with their own teardown suite.