## Why `@suaveplan/testing-dom` is the entry point for every React/DOM component test in the genesis monorepo and the home of the test runner adapter. Per the testing-package separation hard rule (see `openspec/project.md`), it owns: - The vitest primitive re-exports (`describe`, `it`, `expect`, `vi`, `fn`, `spy`, `stub`, `mock`, `fakeClock`, `restoreMocks`, `restoreTimers`) - The `createTestConfig()` factory and runner/environment detectors (`detectRunner`, `detectEnvironment`, `createVitestConfig`, `createBunTestConfig`) - The polyfills setup file (`@suaveplan/testing-dom/polyfills`) - React/DOM-specific helpers built on `@testing-library/react`, `@testing-library/jest-dom`, `@testing-library/user-event` Genesis Layer 0 — testing-infra packages take no `@suaveplan/*` workspace deps. External catalog deps only. The runner adapter + DOM helpers live here (not in `@suaveplan/testing`) because DOM tests already imply vitest+happy-dom; co-locating the runner adapter with the DOM helpers is the natural home. ## What Changes - New package `@suaveplan/testing-dom` at `packages/universal/testing-dom/` (genesis-fresh, version `0.1.0`). - **Imports** the staged runner/config/polyfills code from `packages/universal/testing-dom-staging/` (created during the testing split refactor) and absorbs it cleanly. - **Substitutions per genesis rules:** - Local `TestingDomError extends Error` with `{ code, cause, context }` shape (no `@suaveplan/error`) - `@opentelemetry/api` direct (no `@suaveplan/opentelemetry`) - `zod` direct (no `@suaveplan/schema-registry`) - English-only `code` machine-contract messages (no `@suaveplan/i18n`) - **No `@suaveplan/*` workspace deps.** External catalog deps only. ### Public surface (this package) - **Runner re-exports** (vitest under default condition; bun-test under `bun` condition): `describe`, `it`, `test`, `expect`, `vi`, `beforeAll`, `beforeEach`, `afterAll`, `afterEach`, `fn`, `spy`, `stub`, `mock`, `fakeClock`, `restoreMocks`, `restoreTimers` - **Config**: `createTestConfig`, `TestConfigOptions`, `TestRunner`, `TestEnvironment`, `VitestConfigOverrides`, `BunTestConfig`, `BunTestConfigOverrides` - **Polyfills**: `@suaveplan/testing-dom/polyfills` side-effect module - **DOM render**: `renderComponent` (typed wrapper around `@testing-library/react`'s `render` with sensible defaults: act-aware, cleanup hooked into vitest's `afterEach`) - **DOM queries**: re-exports `screen`, `within`, `findByRole`/`getByRole`/`queryByRole`, etc.; surfaces accessibility-first names with clearer aliases (e.g. `byRole(name, opts)` shortcut). `getByTestId` still re-exported but documented as a fallback. - **User events**: `userEvent` (v14+ instance) + a `setupUser()` factory wired to vitest fake timers when present - **Matchers**: extends `expect` with `@testing-library/jest-dom` matchers - **Errors**: `TestingDomError`, `RenderError`, `MatcherError`, `ConfigError`, `AbortedError` — each with stable `TESTING_DOM..` codes ## Capabilities ### New Capabilities - `testing-dom`: DOM/React testing infrastructure for genesis — runner adapter (vitest+bun-test conditional exports), `createTestConfig` factory, polyfills, React 19 render helpers, accessibility-first queries, jest-dom matchers, user-event v14. ### Modified Capabilities (none — no prior spec) ## Impact - **Affected code**: `packages/universal/testing-dom/**` (fresh). - **Affected consumers**: every React/DOM-testing package (none yet on genesis; this is Layer 0). - **Version**: `0.1.0` (genesis baseline). - **Catalogs added/extended**: `@testing-library/react`, `@testing-library/jest-dom`, `@testing-library/user-event`, `@testing-library/dom` to a new `catalogs.dom-testing` (or extend `catalogs.testing`). - **Pre-publish gate**: `bunx turbo lint typecheck test --filter=@suaveplan/testing-dom` green + ≥ 95% coverage on touched modules.