Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,100 @@
# Runner — vitest / bun-test conditional re-exports
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs --> - vitest — The `runner/vitest` module re-exports vite…
- [vitest](./vitest.md) — The `runner/vitest` module re-exports vitest's `describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll…
- vitest — The `runner/vitest` module re-exports vite…
- [vitest](./vitest.md) — The `runner/vitest` module re-exports vitest's `describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll…
- vitest — The `runner/vitest` module re-exports vite…
- [vitest](./vitest.md) — The `runner/vitest` module re-exports vitest's `describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll…
- vitest — The `runner/vitest` module re-exports vite…
- [vitest](./vitest.md) — The `runner/vitest` module re-exports vitest's `describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll…
- [vitest](./vitest.md) — The `runner/vitest` module re-exports vitest's `describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll…
## Purpose
The runner barrel re-exports the test primitives (`describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll`, `afterEach`, `vi`) plus a runner-neutral mock surface (`fn`, `spy`, `stub`, `mock`, `fakeClock`, `restoreMocks`, `restoreTimers`). Two backends are supported: vitest (the default) and bun's built-in `bun:test`. Which backend resolves at import time is driven by `package.json` conditional exports — under the `bun` condition Node resolves `./dist/runner/bun-test.js`; under `vitest` or `default` it resolves `./dist/index.js` which barrels in `vitest.ts`.
The mock helpers exist so test code can stay runner-agnostic. A package that uses `fn()` / `spy()` / `stub()` instead of importing `vi` directly will run unchanged when its consumers swap test runners — no test-source rewrites required. This is the pattern the original `2026-04-08-testing-libraries` change established and we preserve it here.
## Features
- Re-exports of `vitest` primitives under the default / vitest conditions
- `bun:test` re-exports under the bun condition with API-shaped equivalents (`vi` is aliased to bun's `jest` namespace)
- Runner-neutral mock helpers: `fn`, `spy`, `stub`, `mock(modulePath)`, `fakeClock`, `restoreMocks`, `restoreTimers`
- `mock(modulePath, factory?)` returns a `{ restore() }` handle for symmetry across runners
- `fakeClock()` exists for legacy compatibility — new code should prefer the deterministic `FakeClock` class from `@suaveplan/testing/clock/fake-clock`
## Usage
### Basic example — runner-neutral test
```ts
import {
describe,
it,
expect,
fn,
spy,
} from "@suaveplan/testing";
describe("user service", () => {
it("calls the dependency exactly once", { timeout: 5000 }, () => {
const dep = { fetch: () => "real" };
const handle = spy(dep, "fetch");
const callback = fn();
callback("hello");
expect(callback).toHaveBeenCalledWith("hello");
expect(handle).toHaveBeenCalledTimes(0);
});
});
```
### Advanced example — module mocking with restore
```ts
import { mock, restoreMocks } from "@suaveplan/testing";
const handle = mock("./network.js", () => ({
fetchUser: () => ({ id: 42 }),
}));
// run tests against the mocked module ...
handle.restore();
restoreMocks();
```
### Switching to bun-test
In a consumer's `package.json`, set the `bun` condition (or run via `bun test`). Resolution picks `@suaveplan/testing/dist/runner/bun-test.js` automatically; no test-source changes are needed.
## API Reference
### Test primitives
`describe`, `it`, `test`, `expect`, `beforeAll`, `beforeEach`, `afterAll`, `afterEach`, `vi` — re-exported from the active runner.
### Mock helpers
- `fn<TArgs, TReturn>(implementation?): Mock`
- `spy<T, K>(obj: T, method: K): SpyHandle`
- `stub<T, K>(obj: T, method: K, implementation?): SpyHandle`
- `mock(modulePath: string, factory?: () => unknown): { restore() }`
- `fakeClock(): { advance(ms), restore() }`
- `restoreMocks(): void`
- `restoreTimers(): void`
## Implementation Notes
- **`vi` on the bun path is aliased to `jest`.** Bun-test's mock surface lives under `jest` for API compatibility; the alias keeps consumer code identical across runners.
- **`fakeClock` is legacy.** Prefer the deterministic `FakeClock` class from the clock module — it's runner-independent, supports `Clock` injection across the package, and gives you `snapshot()` / `restore()` for fine control.
- **`mock()` on bun has a no-op `restore()`** because `bun:test` does not expose `unmock`. Call `restoreMocks()` (which delegates to `jest.restoreAllMocks()`) to reset state.
- **The conditional-exports routing** is load-bearing — see `package.json#exports.".".bun` and `.vitest`. Removing either branch breaks the dual-runner contract documented in the spec.
- **Type safety on cross-runner mocks** is approximate. The wrappers use `as never` casts internally because the spy/stub generics differ between the two libraries; consumer code sees a stable shape.