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

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 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

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 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.