@happyvertical/smrt-vitest 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,109 @@
1
+ # @happyvertical/smrt-vitest
2
+
3
+ Vitest plugin for manifest generation and test database utilities. **Required for all SMRT projects.**
4
+
5
+ ## Plugin Setup
6
+
7
+ ```typescript
8
+ // vitest.config.ts
9
+ import { defineConfig } from 'vitest/config';
10
+ import { smrtVitestPlugin } from '@happyvertical/smrt-vitest';
11
+ export default defineConfig({
12
+ plugins: [smrtVitestPlugin()],
13
+ test: { setupFiles: ['@happyvertical/smrt-vitest/setup'] } // optional: globalThis isolation
14
+ });
15
+ ```
16
+
17
+ Without the plugin → "unregistered class" / "No field metadata found" errors.
18
+
19
+ ## What the Plugin Does
20
+
21
+ 1. Scans `src/**/*.ts` for SMRT classes via ManifestBuilder
22
+ 2. Discovers `@happyvertical/smrt-*` dependencies from package.json
23
+ 3. Loads external manifests via ManifestManager
24
+ 4. Registers all classes in ObjectRegistry
25
+ 5. Watch mode caveat: manifest only generated at startup — restart vitest after adding new classes/fields
26
+
27
+ ## CI retry (flaky-test resilience)
28
+
29
+ The plugin injects `test.retry` into every consuming package's config: **2 in CI
30
+ (`process.env.CI`), 0 locally** (`resolveCiRetry`). Several packages have rare,
31
+ CI-environment-specific timing flakes that pass on re-run (none reproducible
32
+ locally); retry keeps the shared cross-package "Test Packages" job reliable
33
+ without masking real failures — a deterministic failure still fails all attempts,
34
+ and vitest flags retried tests as `flaky`. Local runs keep retry at 0 so flakes
35
+ surface during development. Override with `SMRT_VITEST_RETRY=<n>`.
36
+
37
+ Packages that don't use `smrtVitestPlugin` (notably `cli`, plus `core`) set the
38
+ same `retry` policy inline in their own `vitest.config.ts`.
39
+
40
+ ## Test Database Utilities
41
+
42
+ | Function | Use Case |
43
+ |----------|----------|
44
+ | `createIsolatedTestDbFromManifest()` | Multi-table tests — auto-creates schema from manifest with FK ordering and STI dedup |
45
+ | `createIsolatedTestDb({ schema })` | Single-table tests — pass raw DDL |
46
+ | `createTestDb()` | No transaction isolation (legacy) |
47
+ | `getTestDbConfig()` | Get DB config for current environment |
48
+
49
+ **DB adapter auto-detection**: `DATABASE_URL` set → PostgreSQL; otherwise → SQLite temp files.
50
+
51
+ ```typescript
52
+ let db, cleanup;
53
+ beforeEach(async () => {
54
+ ({ db, cleanup } = await createIsolatedTestDbFromManifest());
55
+ });
56
+ afterEach(async () => { await cleanup(); }); // rolls back transaction
57
+ ```
58
+
59
+ ## Singleton Cache Gotcha
60
+
61
+ Module-level singleton caches (common in SMRT collections) persist across tests, ignoring new mocks.
62
+
63
+ **Fix**: `vi.resetModules()` in beforeEach + `await import(...)` in each test (not top-level imports).
64
+
65
+ ## Svelte component testing (S11 #1416)
66
+
67
+ Shared component-test harness so any UI package can render Svelte components, drive
68
+ them, and assert a11y — without copying setup or adding Testing Library deps
69
+ (smrt-vitest carries `@testing-library/{svelte,jest-dom,user-event}` + `axe-core`).
70
+
71
+ Wire it into a package's `vitest.config.ts` (keep `environment: 'node'` as default
72
+ so DB tests are unaffected — the harness only activates under a DOM):
73
+
74
+ ```typescript
75
+ test: {
76
+ environment: 'node',
77
+ setupFiles: [smrtVitestSetupPath, '@happyvertical/smrt-vitest/svelte-setup'],
78
+ }
79
+ ```
80
+
81
+ `svelte-setup` adds jest-dom matchers, Testing Library auto-cleanup, and a jsdom
82
+ `<dialog>` `showModal`/`close` polyfill — guarded behind a `document` check, so it
83
+ is inert in node-environment test files.
84
+
85
+ Component tests opt into the DOM per-file and import the whole surface from one place:
86
+
87
+ ```typescript
88
+ // @vitest-environment jsdom
89
+ import { render, screen, userEvent, expectNoA11yViolations }
90
+ from '@happyvertical/smrt-vitest/svelte';
91
+
92
+ const { container } = render(MyComponent, { props });
93
+ await userEvent.click(screen.getByRole('button', { name: 'Save' }));
94
+ await expectNoA11yViolations(container); // axe; color-contrast off (jsdom can't paint)
95
+ ```
96
+
97
+ Exports: `./svelte` (render/screen/fireEvent/within/userEvent + `expectNoA11yViolations`),
98
+ `./svelte-setup` (the setupFiles entry), `./a11y` (just the axe helper). The plugin
99
+ aliases these subpaths to source for workspace consumers (`getWorkspaceViteAliases`).
100
+ Pattern: render → assert role/name/state → drive with user-event → prove axe-clean.
101
+
102
+ ## Key Files
103
+
104
+ - `src/index.ts` — Vite plugin, manifest generation, workspace aliases, all exports
105
+ - `src/setup.ts` — globalThis isolation setup file
106
+ - `src/svelte-setup.ts` — Svelte component-test setup (jest-dom, cleanup, dialog polyfill)
107
+ - `src/svelte.ts` — component-test surface (Testing Library + a11y, one import)
108
+ - `src/a11y.ts` — `expectNoA11yViolations` (axe-core)
109
+ - `src/test-db.ts` — createIsolatedTestDb, createIsolatedTestDbFromManifest, createTestDb
package/CLAUDE.md ADDED
@@ -0,0 +1 @@
1
+ @AGENTS.md
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright <2025> <Happy Vertical Corporation>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @happyvertical/smrt-vitest
2
+
3
+ Vitest plugin for SMRT projects -- **required** for all SMRT tests. Auto-generates manifests, loads cross-package class metadata, and provides transaction-isolated test database utilities.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @happyvertical/smrt-vitest
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Required Plugin Setup
14
+
15
+ Every SMRT project must include `smrtVitestPlugin()` in vitest.config.ts:
16
+
17
+ ```typescript
18
+ import { defineConfig } from 'vitest/config';
19
+ import { smrtVitestPlugin } from '@happyvertical/smrt-vitest';
20
+
21
+ export default defineConfig({
22
+ plugins: [smrtVitestPlugin()],
23
+ });
24
+ ```
25
+
26
+ Without this plugin, tests fail with `"No field metadata found"` or `"unregistered class"` errors.
27
+
28
+ ### Plugin Options
29
+
30
+ | Option | Type | Default | Description |
31
+ |--------|------|---------|-------------|
32
+ | `generateManifest` | `boolean` | `true` | Auto-generate manifest at startup |
33
+ | `include` | `string[]` | `['src/**/*.ts']` | Source patterns to scan |
34
+ | `exclude` | `string[]` | `['**/*.d.ts', ...]` | Patterns to exclude |
35
+ | `packages` | `string[]` | `[]` | Additional packages beyond auto-discovered |
36
+ | `verbose` | `boolean` | `false` | Enable detailed logging |
37
+ | `root` | `string` | `process.cwd()` | Root directory |
38
+
39
+ ### Watch Mode Note
40
+
41
+ The manifest is generated once at vitest startup. Restart vitest after adding new `@smrt()` classes or fields.
42
+
43
+ ## API
44
+
45
+ ### Plugin
46
+
47
+ | Export | Description |
48
+ |--------|-------------|
49
+ | `smrtVitestPlugin(options?)` | Vite plugin -- generates manifest and loads cross-package classes |
50
+ | `setupSmrtManifests(options?)` | Imperative alternative for non-Vite setups (e.g., globalSetup files) |
51
+
52
+ ### Test Database Utilities
53
+
54
+ | Export | Description |
55
+ |--------|-------------|
56
+ | `createIsolatedTestDbFromManifest(options?)` | Create DB from manifest with FK ordering and STI dedup (recommended) |
57
+ | `createIsolatedTestDb(options?)` | Create DB with raw DDL schema and transaction isolation |
58
+ | `createTestDb(prefix?)` | Create DB with cleanup function (no transaction isolation) |
59
+ | `getTestDbConfig(prefix?)` | Get DB config for current environment |
60
+ | `getInMemoryDbConfig()` | Get in-memory SQLite config |
61
+ | `getTestAdapter()` | Detect adapter: `'postgres'` or `'sqlite'` |
62
+ | `getAdapterDisplayName()` | Human-readable adapter name for test labels |
63
+ | `isPostgresAvailable()` | Check if `DATABASE_URL` is set |
64
+
65
+ DB adapter auto-detection: `DATABASE_URL` set -> PostgreSQL; otherwise -> SQLite temp files.
66
+
67
+ ### Transaction Isolation Example
68
+
69
+ ```typescript
70
+ import { createIsolatedTestDb } from '@happyvertical/smrt-vitest';
71
+
72
+ let db, cleanup;
73
+
74
+ beforeEach(async () => {
75
+ ({ db, cleanup } = await createIsolatedTestDb({
76
+ schema: `CREATE TABLE users (id TEXT PRIMARY KEY, name TEXT NOT NULL)`
77
+ }));
78
+ });
79
+
80
+ afterEach(async () => {
81
+ await cleanup(); // Rolls back transaction
82
+ });
83
+
84
+ it('should insert and query', async () => {
85
+ await db.insert('users', { id: '1', name: 'Alice' });
86
+ const user = await db.get('users', { id: '1' });
87
+ expect(user?.name).toBe('Alice');
88
+ });
89
+ ```
90
+
91
+ ### Types
92
+
93
+ `IsolatedTestDbOptions`, `IsolatedTestDbResult`, `ManifestTestDbOptions`, `TestDbAdapter`, `TestDbConfig`, `TransactionHandle`
94
+
95
+ ## Dependencies
96
+
97
+ - `@happyvertical/smrt-core` -- manifest builder, object registry
98
+ - `@happyvertical/sql` -- database connections and transactions
99
+ - `vitest` (peer) -- Vite test framework
100
+
101
+ ## License
102
+
103
+ MIT