Files
2026-05-27 23:29:53 +01:00

42 lines
1.9 KiB
Markdown

# Capability Spec Delta: testing (2026-04-27-testing-runner-subpath)
**Package**: `@suaveplan/testing`
**Status**: PROPOSED
## ADDED Requirements
### Requirement: Central runner subpath
The package SHALL expose a `./runner` subpath that re-exports the active
test runner's primitives (`describe`, `it`, `test`, `expect`,
`expectTypeOf`, `vi`, `beforeAll`/`beforeEach`/`afterAll`/`afterEach`)
together with generic mock helpers (`fn`, `spy`, `stub`, `mock`,
`fakeClock`, `restoreMocks`, `restoreTimers`) and runner-neutral types
(`RunnerMock<TArgs, TReturn>`, `SpyHandle`). The subpath SHALL resolve
to the vitest implementation by default and to `bun:test` under the
`bun` package.json condition, so consumers swap runners without
changing imports.
#### Scenario: vitest path re-exports primitives
- **WHEN** a consumer imports `describe`, `it`, `expect`, `vi`,
`expectTypeOf` from `@suaveplan/testing/runner` under the default or
`vitest` condition
- **THEN** the imports resolve to the corresponding vitest exports
#### Scenario: bun-test path re-exports primitives with `expectTypeOf` shim
- **WHEN** a consumer imports the same surface under the `bun`
condition
- **THEN** `describe`/`it`/`expect`/`vi` resolve to `bun:test`
equivalents and `expectTypeOf` resolves to a Proxy-backed no-op chain
whose calls succeed (type assertions are erased at compile time)
#### Scenario: generic mock helpers preserve call signature
- **WHEN** a test calls `fn<[string], number>()` from the subpath
- **THEN** the returned `RunnerMock<[string], number>` is callable as
`(arg: string) => number` under both the vitest and bun-test paths
**Verified by:** `src/runner/mocks.test.ts::"creates a mock that records calls"` AND `src/runner/runner.spec-conformance.test.ts::"fn<[string], number>() preserves call-signature typing"` AND `src/runner/runner.spec-conformance.test.ts::"BunRunnerMock<TArgs, TReturn> shape mirrors the vitest path"`