Files
suaveplan/openspec/changes/enterprise-testing-fixtures-expansion/design.md
2026-05-27 23:29:53 +01:00

4.4 KiB

Selection rationale — why these five first

The 2026-04-25 audit (/mnt/s/web/genesis/docs/superpowers/specs/2026-04-25-test-suite-audit.md, §1) lists ten missing fixtures. This wave picks the five with direct existing-package consumers in the genesis tree (per the CLAUDE.md package list) so each new fixture immediately unblocks integration testing for shipped code:

Plugin Direct consumer on genesis Audit severity
testing-integration-oidc @suaveplan/oauth-client (Authorization Code + PKCE, Client Credentials, OIDC discovery) Critical
testing-integration-mongodb data-tier parity with @suaveplan/db-sqlite; future db-mongodb Critical
testing-integration-mysql data-tier parity with @suaveplan/db-sqlite; future db-mysql Critical
testing-integration-minio AWS-S3 surface parity vs testing-integration-garage-s3 quirks High
testing-integration-nats @suaveplan/events; future stream-processing High

Deferred (next waves)

  • OpenTelemetry collector — required to verify exported spans/metrics end-to-end across every package. Held back because it needs a co-designed assertion helper (assertSpanExported(name, attributes)) that does not yet exist; spec lands with the OTel-collector change.
  • Elasticsearch / OpenSearch — Typesense covers our search surface today; no shipped consumer.
  • Vault — no shipped secrets consumer; @suaveplan/env and @suaveplan/config cover env/file layers.
  • LocalStack — overlaps with MinIO + future SQS/SNS work; revisit once an AWS-API consumer ships.
  • Caddy / nginx reverse-proxy — useful for routing tests once apps/testbed formalises a reverse-proxy contract.
  • Kafka / RabbitMQ — NATS goes first as the lightest broker; Kafka follows when a Kafka-specific consumer is on deck.

dependsOn interaction

Audit §3 flags that ServiceFixture lacks declared inter-fixture dependencies. The testing-integration core package is expected to gain a dependsOn?: string[] field on ServiceFixture and topo-sort start order in TestEnvironment. That field is specified by testing-integration itself — out of scope for this change — but every plugin in this wave MUST tolerate its presence:

  • testing-integration-oidc is the canonical upstream: an app fixture that authenticates against the issuer would declare dependsOn: ['oidc']. The OIDC fixture itself declares no dependencies.
  • testing-integration-mongodb / mysql / minio / nats likewise declare no dependencies; downstream app fixtures depend on them.

Plugins MUST NOT introspect the dependsOn field; resolution is TestEnvironment's responsibility.

Image-pinning policy

Mirroring the existing six-plugin precedent: each plugin pins a minor tag (mongo:7.0, mysql:8.4, nats:2.10-alpine, quay.io/keycloak/keycloak:26.0) AND records a # TODO: replace with sha256:<digest> comment in the constants file. Digest substitution happens during the implementation chunk, not in the spec — the spec only requires that a digest placeholder exists.

Env-bridge contract (uniform across all five)

When all documented env vars for a plugin are present and non-empty, the fixture's start() MUST skip container creation entirely and return a ServiceFixtureHandle whose config points at the live service. This is the same contract the existing six plugins implement. Each plugin spec below enumerates its env-var set explicitly.

Injectable fakes — coverage strategy

Each fixture exposes a constructor option object with at least:

  • containerFactory?: () => GenericContainer — swap in a fake container for unit tests.
  • One of: fetchFn?: typeof fetch (HTTP-driven seeding — OIDC, MinIO), execFn?: (cmd: string[]) => Promise<{ stdout, stderr, exitCode }> (in-container CLI seeding — MongoDB, MySQL, NATS), tcpPingFn?: (host, port) => Promise<boolean> (TCP healthchecks — NATS).

This pattern is exactly what testing-integration-redis (tcp ping), testing-integration-postgres (exec), and testing-integration-garage-s3 (fetch + exec) already use; consistency lets the same Vitest fake helpers be re-used across plugins.

Error-code namespacing

Each plugin reserves a top-level prefix under INTEGRATION.*: INTEGRATION.OIDC.*, INTEGRATION.MONGODB.*, INTEGRATION.MYSQL.*, INTEGRATION.MINIO.*, INTEGRATION.NATS.*. Codes match ^INTEGRATION\.[A-Z0-9_]+\.[A-Z_]+$ (same regex the existing plugins use).