Move docs/ package mirror into document-navigator plugin
Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# bun-test-config
|
||||
|
||||
## Purpose
|
||||
|
||||
`createBunTestConfig` produces a minimal `bun test` configuration object with the same polyfill preload and environment defaults as the vitest variant. It exists because `@suaveplan/testing-dom` is a dual-runner package — the same test suite should run under vitest AND under `bun test` without manual config divergence. The shape it returns is intentionally small because `bun test` has a far narrower config surface than vitest.
|
||||
|
||||
## Features
|
||||
|
||||
- Prepends `@suaveplan/testing-dom/polyfills` to the `preload` array
|
||||
- Honours the `happy-dom` runtime via a warning (bun-test does NOT support happy-dom natively; tests that depend on DOM must switch runners)
|
||||
- Pass-through defaults for `coverage` and `testTimeoutMs`
|
||||
- Stateless — no module-level config caching
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
// bunfig.toml is usually the entry, but this runner can be invoked directly:
|
||||
import { createBunTestConfig } from "@suaveplan/testing-dom/config";
|
||||
|
||||
const cfg = createBunTestConfig(__dirname, { testTimeoutMs: 10_000 });
|
||||
// cfg.preload includes "@suaveplan/testing-dom/polyfills"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { createBunTestConfig } from "@suaveplan/testing-dom/config";
|
||||
|
||||
// Opt into coverage when running under CI.
|
||||
const cfg = createBunTestConfig(__dirname, {
|
||||
testTimeoutMs: 30_000,
|
||||
coverageEnabled: process.env.CI === "true",
|
||||
environment: "node",
|
||||
preload: ["./tests/install-matchers.ts"],
|
||||
});
|
||||
|
||||
// Hand off to a custom bun-test spawner:
|
||||
await spawnBunTestRunner(cfg);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createBunTestConfig(callerDir, overrides): BunTestConfig`
|
||||
|
||||
- `callerDir` — reserved for future resolution use
|
||||
- `overrides.preload` — extra preloads appended after the package polyfills
|
||||
- `overrides.coverageEnabled` — default `false`
|
||||
- `overrides.testTimeoutMs` — default `5000`
|
||||
- `overrides.environment` — `"node"` is the only fully-supported value; `"happy-dom"` logs a warning
|
||||
|
||||
### `interface BunTestConfig`
|
||||
|
||||
- `preload: string[]`
|
||||
- `coverageEnabled: boolean`
|
||||
- `testTimeoutMs: number`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The warning on `happy-dom` is logged via `console.warn` rather than thrown because some consumers intentionally use bun-test only for their Node-side suites and vitest for DOM; throwing would break the dual-runner contract. The config object is deliberately shallow — bun-test has no nested blocks, so there's no surface for the package to over-specify. Callers who need additional bun-test features (`timeout`, `coverage`, `bail`) pass them through their `bunfig.toml` directly.
|
||||
@@ -0,0 +1,125 @@
|
||||
# createTestConfig — vitest / bun-test config factory
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs --> - detect-environment — `detectEnvironment` probes the…
|
||||
- [detect-environment](./detect-environment.md) — `detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"`…
|
||||
- [detect-runner](./detect-runner.md) — `detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-…
|
||||
- [vitest-config](./vitest-config.md) — `createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloa…
|
||||
- detect-environment — `detectEnvironment` probes the…
|
||||
|
||||
- [detect-environment](./detect-environment.md) — `detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"`…
|
||||
- [detect-runner](./detect-runner.md) — `detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-…
|
||||
- [vitest-config](./vitest-config.md) — `createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloa…
|
||||
|
||||
- detect-environment — `detectEnvironment` probes the…
|
||||
|
||||
- [detect-environment](./detect-environment.md) — `detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"`…
|
||||
- [detect-runner](./detect-runner.md) — `detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-…
|
||||
- [vitest-config](./vitest-config.md) — `createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloa…
|
||||
|
||||
- detect-environment — `detectEnvironment` probes the…
|
||||
|
||||
- [detect-environment](./detect-environment.md) — `detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"`…
|
||||
- [detect-runner](./detect-runner.md) — `detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-…
|
||||
- [vitest-config](./vitest-config.md) — `createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloa…
|
||||
- [detect-environment](./detect-environment.md) — `detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"`…
|
||||
- [detect-runner](./detect-runner.md) — `detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-…
|
||||
- [vitest-config](./vitest-config.md) — `createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloa…
|
||||
|
||||
## Purpose
|
||||
|
||||
`createTestConfig(options?)` builds a runner-appropriate test config absorbing every WSL2-safe default and dual-runner consideration Suaveplan cares about: `pool: "forks"` (because `vmThreads` and `threads` both fail in Bun on WSL2), `setupFiles: ["@suaveplan/testing-dom/polyfills"]`, optional `@vitejs/plugin-react` loaded only when the caller targets `happy-dom` and the peer is installed, `fileParallelism: false` for happy-dom suites that would otherwise time out under 20+ concurrent forks. The factory reads the caller's `package.json` to detect runner + environment when not explicitly overridden.
|
||||
|
||||
This is the entry point every other package's `vitest.config.ts` should call. The `@suaveplan/testing` package itself uses an inline equivalent (it cannot import its own factory before being built).
|
||||
|
||||
## Features
|
||||
|
||||
- Auto-detects runner (`vitest` vs `bun:test`) from `BUN_TEST` env, package scripts mentioning `bun test`, or `vitest` in deps
|
||||
- Auto-detects environment (`node` / `happy-dom` / `jsdom`) from `react` / `react-dom` / `jsdom` deps
|
||||
- Returns a vitest `UserConfig` via `defineConfig` for the vitest path; returns `BunTestConfig` for bun-test
|
||||
- WSL2 defaults: `pool: "forks"`, polyfills setupFile, `fileParallelism: false` for happy-dom
|
||||
- `@vitejs/plugin-react` is loaded **only** when `environment === "happy-dom"` AND the optional peer is installed — missing peer doesn't break non-React consumers
|
||||
- Coverage block `provider: "istanbul"` with 95% thresholds when `options.coverage === true`
|
||||
- Throws `ConfigError("TESTING.CONFIG.UNKNOWN_RUNNER")` if asked for a runner outside the supported set
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic example — Node-side test config
|
||||
|
||||
```ts
|
||||
// packages/universal/foo/vitest.config.ts
|
||||
import { createTestConfig } from "@suaveplan/testing/config";
|
||||
|
||||
export default await createTestConfig();
|
||||
```
|
||||
|
||||
### React component testing with happy-dom
|
||||
|
||||
```ts
|
||||
import { createTestConfig } from "@suaveplan/testing/config";
|
||||
|
||||
export default await createTestConfig({
|
||||
environment: "happy-dom",
|
||||
coverage: true,
|
||||
});
|
||||
```
|
||||
|
||||
### Force bun-test runner
|
||||
|
||||
```ts
|
||||
const config = await createTestConfig({ runner: "bun:test" });
|
||||
// → BunTestConfig with preload + warnings array
|
||||
```
|
||||
|
||||
### Custom include / exclude
|
||||
|
||||
```ts
|
||||
export default await createTestConfig({
|
||||
include: ["src/**/*.spec.ts"],
|
||||
exclude: ["src/__benchmarks__/**"],
|
||||
testTimeout: 30_000,
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createTestConfig(options?: TestConfigOptions): Promise<UserConfig | BunTestConfig>`
|
||||
|
||||
Async because it dynamically imports the React plugin when needed.
|
||||
|
||||
### `interface TestConfigOptions extends VitestConfigOverrides`
|
||||
|
||||
- `runner?: TestRunner` — `"vitest" | "bun:test"`; auto-detected if omitted
|
||||
|
||||
### `interface VitestConfigOverrides`
|
||||
|
||||
- `environment?: TestEnvironment` — `"node" | "happy-dom" | "jsdom"`
|
||||
- `testTimeout?: number` — default `5000`
|
||||
- `coverage?: boolean | Record<string, unknown>` — `true` enables defaults
|
||||
- `setupFiles?: readonly string[]` — concatenated after polyfills
|
||||
- `include?: readonly string[]` — concatenated after defaults
|
||||
- `exclude?: readonly string[]` — concatenated after defaults
|
||||
- `fileParallelism?: boolean` — defaults to `false` for happy-dom, `true` otherwise
|
||||
|
||||
### `type TestRunner` / `type TestEnvironment`
|
||||
|
||||
### `interface BunTestConfig` / `interface BunTestConfigOverrides`
|
||||
|
||||
- `callerDir`, `environment`, `testTimeoutMs`, `coverageEnabled`, `preload`, `warnings`
|
||||
|
||||
### Error codes thrown
|
||||
|
||||
| Code | Condition |
|
||||
|---|---|
|
||||
| `TESTING.CONFIG.UNKNOWN_RUNNER` | `options.runner` is set to a value other than `"vitest"` / `"bun:test"` |
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- **`pool: "forks"` is non-negotiable on WSL2.** `vmThreads` and `threads` both fail in Bun on WSL2 — see CLAUDE.md for "Vitest / WSL2 quirks". The factory hardcodes `forks`; consumers cannot override.
|
||||
- **`fileParallelism: false`** for happy-dom because 20+ concurrent forks time out. Caller can override via `options.fileParallelism` if their suite is small.
|
||||
- **`@vitejs/plugin-react`** is an optional peer in `package.json#peerDependenciesMeta`. Dynamic `await import` so the missing-peer case doesn't blow up at config-load time. If the import fails (no React), the factory returns the vitest config without the plugin.
|
||||
- **`detectRunner`** reads `BUN_TEST` env first, then scans scripts for `bun test`, then falls back to vitest. Explicit `options.runner` always wins.
|
||||
- **`detectEnvironment`** triggers `happy-dom` on `react` / `react-dom`, `jsdom` on `jsdom`, else `node`. Override via `options.environment`.
|
||||
- **Coverage thresholds** default to 95% statements/branches/functions/lines, matching the quality gate. `options.coverage` as an object lets callers fully customize.
|
||||
- **`callerDir` is exposed on `BunTestConfig`** so a future bun-test runner-script could resolve relative paths without re-detecting.
|
||||
@@ -0,0 +1,51 @@
|
||||
# detect-environment
|
||||
|
||||
## Purpose
|
||||
|
||||
`detectEnvironment` probes the current runtime and returns the most-specific test environment available: `"happy-dom"` when it's importable, otherwise `"jsdom"` when that is, otherwise `"node"`. It lets config factories auto-select a DOM environment without forcing every consumer to hard-code one — the right answer depends on what devDependencies the consumer happens to have installed.
|
||||
|
||||
## Features
|
||||
|
||||
- Pure probe — returns a string, never throws
|
||||
- Ordered preference: `happy-dom` → `jsdom` → `node`
|
||||
- Non-throwing `require.resolve` via a safe try/catch
|
||||
- Zero runtime dependencies — just reads the module graph
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { detectEnvironment } from "@suaveplan/testing-dom/config";
|
||||
|
||||
const env = detectEnvironment();
|
||||
// "happy-dom" | "jsdom" | "node"
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { createVitestConfig, detectEnvironment } from "@suaveplan/testing-dom/config";
|
||||
import { defineConfig } from "vitest/config";
|
||||
|
||||
export default defineConfig(
|
||||
createVitestConfig(__dirname, {
|
||||
environment: detectEnvironment(),
|
||||
coverage: true,
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `detectEnvironment(): TestEnvironment`
|
||||
|
||||
Returns one of:
|
||||
|
||||
- `"happy-dom"` — when `happy-dom` is resolvable from the caller
|
||||
- `"jsdom"` — when `jsdom` is resolvable from the caller
|
||||
- `"node"` — fallback when neither DOM library is available
|
||||
|
||||
### `type TestEnvironment = "happy-dom" | "jsdom" | "node"`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Resolution uses `require.resolve` wrapped in a try/catch so missing modules don't surface as unhandled exceptions. The function runs at config-build time, not at test-run time, so the cost is paid once per vitest invocation and never per test. Consumers who need a deterministic test suite across environments should override the probe by passing an explicit `environment` to `createVitestConfig` — `detectEnvironment` is a convenience for the common case where the DOM preference follows which devDependency is installed.
|
||||
@@ -0,0 +1,60 @@
|
||||
# detect-runner
|
||||
|
||||
## Purpose
|
||||
|
||||
`detectRunner` tells the caller whether the currently-executing process is vitest or bun-test. It's used by the runner-adapter module to pick the right implementation of `describe`/`it`/`expect` at runtime when a test file wants to be dual-runner. Since vitest and bun-test expose slightly different globals, consumers either import the detected runner's API from this package or branch on the returned string.
|
||||
|
||||
## Features
|
||||
|
||||
- Pure probe of `globalThis` / environment variables
|
||||
- Three possible outcomes: `"vitest"`, `"bun-test"`, `"unknown"`
|
||||
- Safe to call outside any test context — returns `"unknown"` rather than throwing
|
||||
- Deterministic under a single runner — no heuristics that flip between runs
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { detectRunner } from "@suaveplan/testing-dom/config";
|
||||
|
||||
const runner = detectRunner();
|
||||
if (runner === "bun-test") {
|
||||
// Use bun:test APIs
|
||||
}
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { detectRunner } from "@suaveplan/testing-dom/config";
|
||||
|
||||
// A shared test-helper module that branches on runner.
|
||||
export function useHelper(): unknown {
|
||||
const runner = detectRunner();
|
||||
switch (runner) {
|
||||
case "vitest":
|
||||
return loadVitestHelper();
|
||||
case "bun-test":
|
||||
return loadBunTestHelper();
|
||||
case "unknown":
|
||||
throw new Error(
|
||||
"useHelper() called outside a supported test runner"
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `detectRunner(): TestRunner`
|
||||
|
||||
Returns one of:
|
||||
|
||||
- `"vitest"` — detected via `import.meta.vitest` or vitest-owned globals
|
||||
- `"bun-test"` — detected via bun's `Bun.version` + `process.env.BUN_TEST`
|
||||
- `"unknown"` — neither was detected
|
||||
|
||||
### `type TestRunner = "vitest" | "bun-test" | "unknown"`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Detection reads multiple signals for each runner to remain robust against future runtime changes — relying on a single global is fragile. The function never reads from disk or spawns a child process, so it's safe to call at module-top during config import. For test files that want to statically import one runner's API, prefer importing `@suaveplan/testing-dom/runner` (which internally calls `detectRunner`) over writing the branch manually.
|
||||
@@ -0,0 +1,62 @@
|
||||
# vitest-config
|
||||
|
||||
## Purpose
|
||||
|
||||
`createVitestConfig` builds a ready-to-use vitest test block with WSL2-safe defaults and the package's polyfills preloaded. It lives here so every package that imports `@suaveplan/testing-dom/config` gets the same `pool: "forks"`, `fileParallelism` heuristics, and setup-file wiring without copying the boilerplate into each `vitest.config.ts`.
|
||||
|
||||
## Features
|
||||
|
||||
- `pool: "forks"` — the only pool that consistently works under Bun on WSL2
|
||||
- `fileParallelism` defaults to `false` for `happy-dom` / `jsdom` environments (avoids 20+ fork timeouts on WSL2)
|
||||
- Prepends `@suaveplan/testing-dom/polyfills` to the user's `setupFiles`
|
||||
- Accepts a `coverage` boolean (enables istanbul defaults) or a custom coverage object (pass-through)
|
||||
- Appends user overrides to defaults rather than replacing them
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
// vitest.config.ts
|
||||
import { defineConfig } from "vitest/config";
|
||||
import { createVitestConfig } from "@suaveplan/testing-dom/config";
|
||||
|
||||
export default defineConfig(createVitestConfig(__dirname));
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
// vitest.config.ts
|
||||
import { defineConfig } from "vitest/config";
|
||||
import { createVitestConfig } from "@suaveplan/testing-dom/config";
|
||||
|
||||
export default defineConfig(
|
||||
createVitestConfig(__dirname, {
|
||||
environment: "happy-dom",
|
||||
coverage: true,
|
||||
setupFiles: ["./tests/install-matchers.ts"],
|
||||
include: ["tests/**/*.test.ts"],
|
||||
fileParallelism: false,
|
||||
testTimeout: 10_000,
|
||||
})
|
||||
);
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createVitestConfig(callerDir, overrides): { test: Record<string, unknown> }`
|
||||
|
||||
- `callerDir` — the consumer package's root, passed to `root`; reserved for future alias resolution
|
||||
- `overrides.environment` — `"node" | "happy-dom" | "jsdom"`; default `"node"`
|
||||
- `overrides.coverage` — `true` turns on istanbul defaults with 95% thresholds; object form passes through verbatim
|
||||
- `overrides.setupFiles` — appended to the polyfill import
|
||||
- `overrides.include` / `overrides.exclude` — appended to defaults
|
||||
- `overrides.testTimeout` — default 5000
|
||||
- `overrides.fileParallelism` — default `false` for `happy-dom`, `true` otherwise
|
||||
|
||||
### `interface VitestConfigOverrides`
|
||||
|
||||
See source for the full shape; every field is optional.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The returned shape is intentionally untyped from vitest's internals — consumers spread or merge it without tight coupling to the library's evolving generic parameters. The polyfill setup file is always prepended (not appended) so the user's own setup files can assume `globalThis.crypto` / `TextEncoder` are present. Coverage defaults live inline in this file rather than being imported from elsewhere so the produced config has zero runtime coupling to other `testing-dom` modules.
|
||||
Reference in New Issue
Block a user