first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
# `testing/conformance` — `runSecretsConformance` harness
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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 `isNotFound` predicate so sources representing missing names differently (network adapter wrapping a transport error) can still pass.
- All `it(...)` calls carry `{ timeout: 5000 }`.
## Usage: Basic
```ts
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:
```ts
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 Vitest `describe` block; 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.