Files
suaveplan/openspec/archive/2026-05-25-enterprise-test-vite/design.md
2026-05-27 23:29:53 +01:00

121 lines
5.3 KiB
Markdown

# Design — @suaveplan/test-vite
## Tier and dependency allowlist
Tier: **universal-ish-tooling** — runs in Node-build contexts (`vite build`) and Vitest test files. Not browser-runtime.
Dependency allowlist (production):
- `@suaveplan/error` (workspace) — `defineCodes` + `SuaveplanError` for `TestViteError`.
- `@suaveplan/types` (workspace) — `Clock`, `LoggerLike` injection contracts.
- `@suaveplan/opentelemetry` (workspace, transitive) — meter wiring via `@opentelemetry/api`.
- `@opentelemetry/api` (catalog:observability) — counters + histograms.
- `vite` (catalog:build) — `UserConfig` type + `defineConfig` re-imported by factories.
- `vitest` (catalog:testing) — `UserConfig` / `defineConfig` from `vitest/config`.
- `vite-plugin-dts` (catalog:build) — used inside `createViteLibraryConfig`.
- `zod` (catalog:forms) — boundary validation of every public option object.
- `tslib` (catalog:build) — helper runtime.
Dev-only: `@suaveplan/testing` for `./runner` wrapper, `@opentelemetry/sdk-metrics` for in-memory MeterProvider test setup, `@types/node`, `typescript`, `@vitest/coverage-istanbul`.
`vite` / `vitest` / `vite-plugin-dts` are production deps because callers inherit them via this package (matching the upstream convention from the enterprise plan §2).
## Folder layout
```
src/
index.ts # explicit named re-exports
vite-library-config/
vite-library-config.ts # createViteLibraryConfig(opts)
vite-library-config.md
vite-library-config.test.ts
vite-app-config/
vite-app-config.ts # createViteAppConfig(opts)
vite-app-config.md
vite-app-config.test.ts
vitest-config/
vitest-config.ts # createVitestConfig(opts)
vitest-config.md
vitest-config.test.ts
vitest-browser-config/
vitest-browser-config.ts # createVitestBrowserConfig(opts)
vitest-browser-config.md
vitest-browser-config.test.ts
browser-environment/
browser-environment.ts # setupBrowserEnvironment
browser-environment.md
browser-environment.test.ts
tree-shake-validator/
tree-shake-validator.ts # verifyTreeShake
tree-shake-validator.md
tree-shake-validator.test.ts
bundle-size-snapshot/
bundle-size-snapshot.ts # snapshotBundleSize
bundle-size-snapshot.md
bundle-size-snapshot.test.ts
port-allocator/
port-allocator.ts # allocate/releasePort
port-allocator.md
port-allocator.test.ts
hmr-tester/
hmr-tester.ts # withHMR
hmr-tester.md
hmr-tester.test.ts
matchers/
matchers.ts # createMatchers
matchers.md
matchers.test.ts
error-codes/
error-codes.ts # TEST_VITE_CODES, TestViteError
error-codes.md
error-codes.test.ts
telemetry/
telemetry.ts # OTel instruments
telemetry.md
telemetry.test.ts
types/
test-vite.types.ts # shared interfaces
tests/
setup/
polyfills.ts # in-memory MeterProvider + webcrypto
```
## Error-code plan
`defineCodes("TEST_VITE", [...])` with these codes:
- `INVALID_OPTIONS` — Zod parse failure on any factory option object.
- `MISSING_ENTRY` — bundle file required by `verifyTreeShake` / `snapshotBundleSize` cannot be read.
- `TREE_SHAKE_VIOLATION` — bundle exports a symbol not in `expectedSymbols`.
- `SIZE_BUDGET_EXCEEDED` — bundle size exceeds snapshot + tolerance.
- `SNAPSHOT_MISSING` — snapshot file not found and `update: false`.
- `PORT_EXHAUSTED` — no port in the configured range is available.
- `PORT_NOT_HELD` — release of an unheld port.
- `HMR_TIMEOUT` — HMR round-trip exceeded timeout.
8 codes — every one is exercised by a test (see spec deltas).
## OTel instrument plan
Meter name: `@suaveplan/test-vite`. Instruments:
- `test_vite_config_built_total` (counter) — one per factory invocation; attribute `kind` = `vite_library`/`vite_app`/`vitest`/`vitest_browser`.
- `test_vite_validator_runs_total` (counter) — one per `verifyTreeShake` or `snapshotBundleSize` call.
- `test_vite_validator_violations_total` (counter) — one per detected violation.
- `test_vite_port_allocations_total` (counter) — one per successful `allocatePort`.
- `test_vite_hmr_round_trip_ms` (histogram) — recorded on every `withHMR` resolution.
All wired into a single `telemetry.ts` module with a real MeterProvider asserted in `telemetry.test.ts`.
## Boundary validation
Every public factory accepts an options object validated by a Zod schema. Invalid input → `TestViteError(TEST_VITE_CODES.INVALID_OPTIONS, …)` carrying the Zod issue list on `details`.
## Test-runner discipline
All `*.test.ts` files import from `@suaveplan/testing/runner` (rule 11). No `vitest` or `bun:test` direct imports.
## File-size budget
Every implementation file stays under 300 lines hard / 250 soft. Where logic is dense (`tree-shake-validator`, `bundle-size-snapshot`), shared helpers are extracted into private module-local functions; if necessary they spill into a sibling `<feature>.helpers.ts` (still inside the feature folder, with its own `.md`).