5.3 KiB
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+SuaveplanErrorforTestViteError.@suaveplan/types(workspace) —Clock,LoggerLikeinjection contracts.@suaveplan/opentelemetry(workspace, transitive) — meter wiring via@opentelemetry/api.@opentelemetry/api(catalog:observability) — counters + histograms.vite(catalog:build) —UserConfigtype +defineConfigre-imported by factories.vitest(catalog:testing) —UserConfig/defineConfigfromvitest/config.vite-plugin-dts(catalog:build) — used insidecreateViteLibraryConfig.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 byverifyTreeShake/snapshotBundleSizecannot be read.TREE_SHAKE_VIOLATION— bundle exports a symbol not inexpectedSymbols.SIZE_BUDGET_EXCEEDED— bundle size exceeds snapshot + tolerance.SNAPSHOT_MISSING— snapshot file not found andupdate: 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; attributekind=vite_library/vite_app/vitest/vitest_browser.test_vite_validator_runs_total(counter) — one perverifyTreeShakeorsnapshotBundleSizecall.test_vite_validator_violations_total(counter) — one per detected violation.test_vite_port_allocations_total(counter) — one per successfulallocatePort.test_vite_hmr_round_trip_ms(histogram) — recorded on everywithHMRresolution.
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).