Initial Commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Coverage and docs gates
|
||||
|
||||
> Original: "Istanbul statement + branch coverage across `packages/universal/testing/src/` (excluding `*.bench.ts` and `*.schemas.ts`) MUST be ≥ 95%. […]"
|
||||
|
||||
Istanbul statement, branch, function, AND line coverage across `packages/testing/testing/src/` (excluding `*.bench.ts`, `*.schemas.ts`, barrel `index.ts` files, and inner-dir `*.types.ts`) MUST each be exactly **100 %**. There is no foundation carve-out, no degraded-situation floor, and no exception for any genesis package — the gate applies to `@suaveplan/testing` and to every other `@suaveplan/*` package equally. The pre-publish gate (`bunx turbo test:coverage --filter=@suaveplan/testing`) MUST hard-fail when any of statements, branches, functions, or lines is below `100 %`.
|
||||
|
||||
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. Mutation testing, contract testing, property testing, and fuzz coverage layer **on top of** 100 % line coverage; they do not substitute for it, and 100 % line coverage does not substitute for them.
|
||||
|
||||
#### Scenario: Coverage gate at 100 %
|
||||
|
||||
- **WHEN** `bunx turbo test:coverage --filter=@suaveplan/testing` runs
|
||||
- **THEN** reported statement, branch, function, and line coverage are each `100 %` AND the gate fails the build if any dimension drops below `100 %`
|
||||
|
||||
#### Scenario: Docs coverage enforced
|
||||
|
||||
- **WHEN** a script enumerates implementation files under `src/` (excluding the stated exclusions) and checks for sibling `.md` files
|
||||
- **THEN** every implementation file has a sibling `.md` AND every `.md` is ≥ 200 non-code words
|
||||
|
||||
### Requirement: Property-based coverage for pure helpers
|
||||
|
||||
> Original: "Pure functions and deterministic state machines in the package […] SHALL have fast-check property tests covering round-trip, idempotency, associativity, and boundary invariants […]"
|
||||
|
||||
Pure functions and deterministic state machines in `@suaveplan/testing` SHALL have fast-check property tests covering round-trip, idempotency, associativity, and boundary invariants as applicable. **The same requirement extends to every other pure-function `@suaveplan/*` package** — every package whose public surface includes deterministic, side-effect-free helpers MUST ship fast-check property tests that exercise round-trip, idempotency, associativity, or boundary invariants where each applies. Load-bearing examples include `@suaveplan/crypto-utils` (encoding round-trips), `@suaveplan/diff` (apply ∘ invert, structural equality), `@suaveplan/pagination` (cursor encode/decode round-trip, slice associativity), and `@suaveplan/validation` (parse / safeParse equivalence on valid inputs).
|
||||
|
||||
#### Scenario: Builder composition is associative
|
||||
|
||||
- **WHEN** fast-check runs over arbitrary RequestBuilder presets `a`, `b`, `c` applied in different groupings
|
||||
- **THEN** `(a then b) then c` produces the same final state as `a then (b then c)`
|
||||
|
||||
#### Scenario: Pure-function package ships round-trip property
|
||||
|
||||
- **WHEN** any genesis package whose public surface is pure (e.g. `@suaveplan/crypto-utils` `hexEncode`/`hexDecode`) is audited for property tests
|
||||
- **THEN** at least one fast-check test exists asserting `decode(encode(x)) === x` for arbitrary `Uint8Array` inputs
|
||||
|
||||
### Requirement: Deterministic clock and RNG via dependency injection
|
||||
|
||||
> Original: "Every public function that reads time, randomness, or iterates SHALL accept an optional `{ clock?: Clock; rng?: Rng; signal?: AbortSignal }` options parameter. […]"
|
||||
|
||||
Every public function in `@suaveplan/testing` 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.
|
||||
|
||||
**This contract additionally extends to integration test fixtures via `TestEnvironmentOptions`** — `@suaveplan/testing-integration`'s `TestEnvironment` MUST accept `{ clock?, rng?, signal? }` and propagate them to fixtures whose configs declare `acceptsContext: true`, so that integration tests can run against the same deterministic time and randomness sources as unit tests.
|
||||
|
||||
#### Scenario: Injected clock controls observed time
|
||||
|
||||
- **WHEN** `waitFor(predicate, { clock: fakeClock })` runs and `fakeClock.advance(1000)` is called
|
||||
- **THEN** the helper observes 1000 ms elapsed AND does NOT read `Date.now()` or `performance.now()` directly
|
||||
|
||||
#### Scenario: Injected RNG produces deterministic factory output
|
||||
|
||||
- **WHEN** `Factory.build({ rng: seededRng(42) })` is called twice with the same factory definition
|
||||
- **THEN** both calls return byte-identical output (for factories whose definition is otherwise deterministic)
|
||||
|
||||
#### Scenario: TestEnvironment forwards clock to opt-in fixtures
|
||||
|
||||
- **WHEN** a `TestEnvironment` is constructed with `{ clock: fakeClock }` and a fixture's config declares `acceptsContext: true`
|
||||
- **THEN** that fixture's `config.clock === fakeClock` at the time `start()` is invoked
|
||||
Reference in New Issue
Block a user