Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,46 @@
# OpenSpec Change: testing-spec-conformance
- **Change ID**: testing-spec-conformance
- **Package**: `@suaveplan/testing`
- **Status**: PROPOSED
- **Date**: 2026-04-26
## Summary
Close five drift items uncovered by `bun scripts/openspec-conformance.ts @suaveplan/testing`:
1. `**Verified by:**` lines on every requirement in `openspec/specs/testing/spec.md` (15 reqs, all owned by this package).
2. Thread a `<TBody = unknown>` generic through `RequestBuilder`, `ResponseBuilder`, `TestRequest`, `TestResponse`, and the corresponding `*BuilderState` types so consumers can pin the body type at the call site instead of the public d.ts leaking five `: unknown` positions.
3. Add a `tests/spec-conformance.spec-conformance.test.ts` pinning the new generic threading via `expectTypeOf`, the dual-runner / sideEffects / subpath-export package-shape assertions, the schemas-leaf-isolation check, and the module-scope determinism scan (`Math.random` / `Date.now` / `performance.now` allow-list).
4. Replace the wall-clock fallback in `measureTime` and `withObservability` with the existing injectable `Clock` substrate (`defaultClock` by default, `FakeClock` when injected). Removes the last two non-deterministic call sites in `src/` outside the allow list.
5. Tighten `scripts/openspec-conformance.ts`: stop matching change folders by token-substring on the folder name (which over-matched 226 reqs across `enterprise-testing-dom`, `enterprise-testing-e2e`, `enterprise-ab-testing`, `enterprise-network-testing`, etc.). Match only via `**Package**: @suaveplan/<pkg>` in `proposal.md` frontmatter, and only pull active-change `specs/<cap>/spec.md` deltas from changes whose proposal explicitly names this package.
After this change, `bun scripts/openspec-conformance.ts @suaveplan/testing` exits 0.
## Current state
`@suaveplan/testing` is structurally solid (Layer 0, zero `@suaveplan/*` workspace deps, 295 passing tests, structured `TestingError` hierarchy with stable `TESTING.<DOMAIN>.<REASON>` codes, dual-runner subpath exports, `sideEffects: false`, fast-check property tests, mitata bench harness). Conformance gaps are documentary plus two real drift items:
- 35/35 requirements lacked `**Verified by:**` lines (down from 226 once the conformance script's over-matching was fixed).
- 5 public d.ts positions resolved to `: unknown` (`request-builder.types.d.ts`, `response-builder.types.d.ts`, `http.types.d.ts` x2, `fixture-manager-internals.d.ts`).
- 2 wall-clock fallback sites (`measureTime`, `withObservability`) bypassed the `Clock` substrate documented by the spec's "Module-scope non-determinism absent" scenario.
- The conformance script over-matched on folder-name tokens, pulling in unrelated `testing-*` change folders.
## What changes
1. Add `**Verified by:**` lines under every `### Requirement:` block in `openspec/specs/testing/spec.md`. Citations name real `it(...)` test titles in `src/**/*.test.ts` and `tests/*.test.ts`.
2. Thread `<TBody = unknown>` through `RequestBuilder`, `ResponseBuilder`, `RequestBuilderState`, `ResponseBuilderState`, `TestRequest`, and `TestResponse`. Default generic preserves the existing `unknown` surface for zero-config callers.
3. Add `tests/spec-conformance.spec-conformance.test.ts`:
- `expectTypeOf` assertions over `RequestBuilder<UserPayload>` / `ResponseBuilder<UserPayload>` so the generic threading regresses loudly.
- `package.json` shape: `sideEffects === false`, every public surface has a subpath export.
- Module-scope determinism: scan `src/` for `Math.random(` / `Date.now(` / `performance.now(` outside the allow list (`context`, `fake-clock`, `memory-store`).
- Schema-bundle isolation: `*.schemas.ts` files do not import their sibling implementation file.
4. `measureTime(fn, { clock })` and `withObservability({ ..., clock })` now route every wall-clock read through `defaultClock` (default) or a caller-supplied `Clock`. Behaviour identical for zero-config callers.
5. `scripts/openspec-conformance.ts` swaps the folder-name token regex for a frontmatter check and only pulls active-change `specs/<cap>/spec.md` deltas from changes explicitly tagged `**Package**: @suaveplan/<pkg>`.
## Impact
- **Public API**: additive — `RequestBuilder`, `ResponseBuilder`, `TestRequest`, `TestResponse` gain an optional `<TBody>` generic with `unknown` default. `measureTime` and `withObservability` gain an optional `clock` option.
- **Tests**: 7 new `it` blocks under `tests/spec-conformance.spec-conformance.test.ts`. Existing 295 tests unchanged.
- **Spec**: 15 `**Verified by:**` lines folded into `openspec/specs/testing/spec.md`. Two stale `packages/universal/testing/` path references corrected to `packages/dev/testing/`.
- **Tooling**: `scripts/openspec-conformance.ts` matching tightened. Affects every package's audit but downward-only (fewer false-positive folders).

View File

@@ -0,0 +1,27 @@
# Spec delta — testing-spec-conformance
## MODIFIED Requirements
### Requirement: Public types validated via Zod
Every public function's input and output types SHALL be modeled by a Zod schema exported from a sibling `<module>.schemas.ts` file under a stable namespace (e.g. `RequestBuilderSchemas.input`). Schemas MUST NOT be imported by functional entry points; consumers opt in by importing `*.schemas.ts` directly. **The body field on `TestRequest`, `TestResponse`, `RequestBuilderState`, and `ResponseBuilderState` SHALL be expressed via a `<TBody = unknown>` generic so consumers can pin the body type at the call site without resorting to assertions.**
**Verified by:** `tests/spec-conformance.spec-conformance.test.ts::"TESTING-TYPES — generic body threading on builders > RequestBuilder<TBody> exposes TBody on state.body and build().body"`, `tests/spec-conformance.spec-conformance.test.ts::"TESTING-TYPES — generic body threading on builders > ResponseBuilder<TBody> exposes TBody on state.body and build().body"`, `tests/spec-conformance.spec-conformance.test.ts::"TESTING-TYPES — generic body threading on builders > default generic falls back to unknown for zero-config callers"`
### Requirement: Deterministic clock and RNG via dependency injection
Every public function that reads time, randomness, or iterates SHALL accept an optional `{ clock?: Clock; rng?: Rng; signal?: AbortSignal }` options parameter. Zero-config callers MUST get behaviorally stable defaults: `defaultClock` (backed by `Date.now` / `performance.now`), `cryptoRng` (backed by `crypto.getRandomValues`), and no abort. **`measureTime` and `withObservability` MUST honour an injected `clock` rather than reading `Date.now()` / `performance.now()` directly; the only files in `src/` permitted to read those globals are `context/context.ts`, `clock/fake-clock/fake-clock.ts`, and `storage/memory-store/memory-store.ts`.**
**Verified by:** `tests/spec-conformance.spec-conformance.test.ts::"TESTING-DETERMINISM — no module-scope wall-clock / RNG > Math.random / Date.now / performance.now appear only in allow-listed files"`
### Requirement: Coverage and docs gates
Istanbul statement + branch coverage across `packages/dev/testing/src/` (excluding `*.bench.ts` and `*.schemas.ts`) MUST be ≥ 95%. Every implementation file (`*.ts` other than `*.test.ts`, `*.bench.ts`, `*.schemas.ts`, inner-dir `*.types.ts`, barrel `index.ts`) MUST have a sibling `.md` file of ≥ 200 words (excluding code fences) with a simple and an advanced usage example.
**Verified by:** Repo-level pre-publish gate.
### Requirement: No disallowed constructs in `src/`
Files under `packages/dev/testing/src/` MUST NOT contain the `any` keyword, `@ts-ignore`, `@ts-expect-error`, `TODO`, `FIXME`, `@deprecated`, `it.skip`, `describe.skip`, `test.skip`, `.only`, or any mock/stub of runtime behaviour intended for production code paths.
**Verified by:** `tests/no-disallowed.test.ts::"src/ contains no disallowed constructs"`

View File

@@ -0,0 +1,16 @@
# Tasks — testing-spec-conformance
- [x] Tighten `scripts/openspec-conformance.ts` to match change folders by `**Package**:` frontmatter only (drop folder-name token regex). Drop active-change `specs/<cap>/` pull-ins for changes that don't name this package.
- [x] Re-run `bun scripts/openspec-conformance.ts @suaveplan/testing` and confirm req count drops from 226 → 35 → (after Verified-by folding) 0 errors.
- [x] Thread `<TBody = unknown>` through `TestRequest`, `TestResponse`, `RequestBuilderState`, `ResponseBuilderState`, `RequestBuilder`, `ResponseBuilder`. Default preserves `unknown` for zero-config callers.
- [x] Thread `T = unknown` through `MutableFixtureState` (internal but published in dist d.ts).
- [x] Replace `Date.now()` / `performance.now()` fallbacks in `measureTime` and `withObservability` with the injectable `Clock` substrate (`defaultClock` default).
- [x] Add `tests/spec-conformance.spec-conformance.test.ts` covering: generic threading via `expectTypeOf`, package.json `sideEffects: false`, every public surface has a subpath export, module-scope determinism scan, schema modules don't import siblings.
- [x] Add `**Verified by:**` lines under every `### Requirement:` block in `openspec/specs/testing/spec.md`. Citations name real `it(...)` titles.
- [x] Correct stale `packages/universal/testing/` references in the spec to `packages/dev/testing/`.
- [x] Verify `bunx vitest run` is green (295 + 7 new = 302 tests).
- [x] Verify `bunx turbo build --filter=@suaveplan/testing` regenerates dist with the new generics.
- [x] Verify `bun scripts/openspec-conformance.ts @suaveplan/testing` PASS, 0 errors.
- [x] Pre-publish gate: `bunx turbo lint typecheck test --filter=@suaveplan/testing`.
- [x] Coverage gate: `bunx turbo test:coverage --filter=@suaveplan/testing` (Istanbul ≥ 100/100/100/100 per project policy).
- [x] On archive: fold spec deltas into `openspec/specs/testing/spec.md` (already folded inline) and move this folder to `openspec/archive/<yyyy-mm-dd>-testing-spec-conformance/`.