sonamu 0.10.7 → 0.10.9

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.
Files changed (79) hide show
  1. package/dist/api/decorators.d.ts.map +1 -1
  2. package/dist/api/decorators.js +5 -12
  3. package/dist/bin/cli.js +10 -253
  4. package/dist/database/base-model.d.ts +1 -0
  5. package/dist/database/base-model.d.ts.map +1 -1
  6. package/dist/database/base-model.js +14 -8
  7. package/dist/database/db.d.ts +2 -1
  8. package/dist/database/db.d.ts.map +1 -1
  9. package/dist/database/db.js +13 -3
  10. package/dist/database/puri-wrapper.d.ts.map +1 -1
  11. package/dist/database/puri-wrapper.js +4 -11
  12. package/dist/database/transaction-context.d.ts +8 -3
  13. package/dist/database/transaction-context.d.ts.map +1 -1
  14. package/dist/database/transaction-context.js +12 -7
  15. package/dist/migration/code-generation.js +2 -2
  16. package/dist/naite/naite-reporter.d.ts +8 -3
  17. package/dist/naite/naite-reporter.d.ts.map +1 -1
  18. package/dist/naite/naite-reporter.js +9 -4
  19. package/dist/ui-web/assets/{index-D0MHYbxl.js → index-CJf8uJYf.js} +47 -41
  20. package/dist/ui-web/assets/index-GMMIVGja.css +1 -0
  21. package/dist/ui-web/index.html +2 -2
  22. package/package.json +3 -3
  23. package/src/api/decorators.ts +11 -22
  24. package/src/bin/cli.ts +12 -375
  25. package/src/database/__tests__/transaction-scope.test.ts +227 -0
  26. package/src/database/base-model.ts +31 -6
  27. package/src/database/db.ts +17 -2
  28. package/src/database/puri-wrapper.ts +5 -22
  29. package/src/database/transaction-context.ts +14 -6
  30. package/src/migration/code-generation.ts +1 -1
  31. package/src/naite/naite-reporter.ts +8 -3
  32. package/dist/ui-web/assets/index-Dx_JX4aQ.css +0 -1
  33. package/src/skills/AGENTS.md +0 -108
  34. package/src/skills/sonamu/SKILL.md +0 -75
  35. package/src/skills/sonamu-ai-agents/SKILL.md +0 -205
  36. package/src/skills/sonamu-api/SKILL.md +0 -480
  37. package/src/skills/sonamu-auth/SKILL.md +0 -327
  38. package/src/skills/sonamu-auth/references/plugins.md +0 -310
  39. package/src/skills/sonamu-auth/references/user-id-migration-followups.md +0 -192
  40. package/src/skills/sonamu-auth/references/user-id-migration.md +0 -455
  41. package/src/skills/sonamu-config/SKILL.md +0 -203
  42. package/src/skills/sonamu-config/references/database.md +0 -452
  43. package/src/skills/sonamu-config/references/environments.md +0 -178
  44. package/src/skills/sonamu-config/references/server-options.md +0 -400
  45. package/src/skills/sonamu-entity/SKILL.md +0 -180
  46. package/src/skills/sonamu-entity/references/creation-workflow.md +0 -581
  47. package/src/skills/sonamu-entity/references/design-guides.md +0 -243
  48. package/src/skills/sonamu-entity/references/field-types.md +0 -170
  49. package/src/skills/sonamu-entity/references/relations-detail.md +0 -245
  50. package/src/skills/sonamu-entity/references/relations.md +0 -463
  51. package/src/skills/sonamu-entity/references/subset.md +0 -156
  52. package/src/skills/sonamu-fixture/SKILL.md +0 -180
  53. package/src/skills/sonamu-fixture/references/cli-usage.md +0 -439
  54. package/src/skills/sonamu-fixture/references/cone.md +0 -298
  55. package/src/skills/sonamu-frontend/SKILL.md +0 -142
  56. package/src/skills/sonamu-frontend/references/components.md +0 -323
  57. package/src/skills/sonamu-frontend/references/examples.md +0 -64
  58. package/src/skills/sonamu-frontend/references/hooks.md +0 -273
  59. package/src/skills/sonamu-frontend/references/runtime.md +0 -165
  60. package/src/skills/sonamu-frontend/references/scaffolding.md +0 -439
  61. package/src/skills/sonamu-i18n/SKILL.md +0 -287
  62. package/src/skills/sonamu-migration/SKILL.md +0 -316
  63. package/src/skills/sonamu-naite/SKILL.md +0 -266
  64. package/src/skills/sonamu-query/SKILL.md +0 -48
  65. package/src/skills/sonamu-query/references/model-patterns.md +0 -390
  66. package/src/skills/sonamu-query/references/model.md +0 -366
  67. package/src/skills/sonamu-query/references/puri.md +0 -413
  68. package/src/skills/sonamu-query/references/search.md +0 -238
  69. package/src/skills/sonamu-query/references/upsert.md +0 -324
  70. package/src/skills/sonamu-tasks/SKILL.md +0 -236
  71. package/src/skills/sonamu-testing/SKILL.md +0 -251
  72. package/src/skills/sonamu-testing/references/devrunner.md +0 -405
  73. package/src/skills/sonamu-testing/references/helpers.md +0 -185
  74. package/src/skills/sonamu-testing/references/patterns.md +0 -263
  75. package/src/skills/sonamu-testing/references/pitfalls.md +0 -588
  76. package/src/skills/sonamu-testing/references/quick-start.md +0 -285
  77. package/src/skills/sonamu-testing/references/type-safety.md +0 -172
  78. package/src/skills/sonamu-testing/references/writing-plan.md +0 -375
  79. package/src/skills/sonamu-vector/SKILL.md +0 -222
@@ -1,251 +0,0 @@
1
- ---
2
- name: sonamu-testing
3
- description: Writes and runs Sonamu Vitest tests. Use when authoring a Model or API test, asserting on query behaviour, mocking a dependency, or when sonamu test fails to run. Covers bootstrap, test and testAs, createFixtureLoader, Naite.get assertions, expectQuery, expectUB, DevRunner, HMR integration, and parallel workers.
4
- ---
5
-
6
- # Sonamu Test System
7
-
8
- Sonamu provides a Vitest-based test environment. Each test is isolated in a transaction and automatically rolled back.
9
-
10
- **Example project**: `sonamu/examples/miomock` — reference for real test code
11
-
12
- **WARNING: Projects with 10 or more entities must use a batch strategy** — see `references/writing-plan.md`.
13
-
14
- ## Reference Map
15
-
16
- | Need | Read |
17
- | --- | --- |
18
- | First test in a new project, end-to-end | `references/quick-start.md` |
19
- | Planning what to test, order, batching for 10+ entities | `references/writing-plan.md` |
20
- | bootstrap / test / testAs, CRUD, mocks, file structure, enum values | `references/patterns.md` |
21
- | expectQuery, expectUB, Naite assertions, createFixtureLoader | `references/helpers.md` |
22
- | Type errors in test code, nullable handling, partial/extend | `references/type-safety.md` |
23
- | Failing for a non-obvious reason, complex entity graphs | `references/pitfalls.md` |
24
- | `sonamu test` itself fails, HMR, parallel workers, vitest/sonamu config | `references/devrunner.md` |
25
-
26
- Fixture generation via CLI (`fixture gen/fetch/explore`) and the 3-Tier DB structure live in the
27
- `sonamu-fixture` skill, not here.
28
-
29
- ---
30
-
31
- ## Running Tests
32
-
33
- **Use `pnpm sonamu test` during development.** It reuses a Vitest instance living inside the
34
- `sonamu dev` process, so it is roughly 3.2x faster than a cold start and picks up source changes
35
- through HMR. Assume the dev server is running; start it first if it is down. `pnpm test` is for CI.
36
-
37
- ```bash
38
- # Start dev server if it's down
39
- pnpm sonamu dev
40
-
41
- # Tests during development (default)
42
- pnpm sonamu test
43
- pnpm sonamu test user.model
44
- pnpm sonamu test user.model -p "findMany" # filter by test name
45
- pnpm sonamu test user.model -t # print Naite traces
46
-
47
- # CI environments only
48
- pnpm test
49
- ```
50
-
51
- Requires `test.devRunner.enabled: true` in `sonamu.config.ts`:
52
-
53
- ```typescript
54
- export default defineConfig({
55
- test: {
56
- devRunner: { enabled: true }, // required for `pnpm sonamu test`
57
- // parallel: true, // optional: separate DB per worker
58
- // maxWorkers: 4,
59
- },
60
- });
61
- ```
62
-
63
- **→ Prerequisites, CLI argument rules, HMR integration, HTTP API, internal architecture, parallel
64
- DB flow, vitest.config.ts/global.ts, troubleshooting: `references/devrunner.md`**
65
-
66
- ---
67
-
68
- ## Pre-Test Writing Checklist
69
-
70
- - [ ] **Confirm entity design is complete** - `pnpm db:migration` and `pnpm scaffolding` completed without errors
71
- - [ ] **Plan test writing** - group entities by business process (→ see "Test Writing Plan" below)
72
- - [ ] **Handle nullable fields in types.ts (FIRST!)** - immediately after entity creation, apply partial + extend handling for nullable fields (→ see "Tasks to Do Immediately After Entity Creation" below)
73
- - [ ] **Prepare Seed Data** - base data required due to FK constraints (→ see "minimum seed data" in database.md)
74
- - [ ] **Test helper functions** - prepare helpers for handling complex entity dependencies
75
- - [ ] **For 10 or more entities** - plan batch strategy (see "Large-Scale Project Strategy" below)
76
-
77
-
78
- ## Core Test Writing Principles
79
-
80
- ### 1. Verify Actual Structure First
81
-
82
- **CRITICAL: Always verify the actual entity structure before planning tests.**
83
-
84
- Before writing tests, you must verify the following:
85
-
86
- ```typescript
87
- // STEP 1: Check entity.json
88
- // - actual field names and types
89
- // - nullable status
90
- // - enum value list
91
- // - relation structure
92
-
93
- // STEP 2: Check types.ts
94
- // - partial settings in SaveParams
95
- // - nullish handling for nullable fields
96
- // - _ids arrays for ManyToMany relations
97
-
98
- // STEP 3: Check sonamu.generated.ts
99
- // - Enum type definitions
100
- // - Subset type structure
101
- // - BaseSchema structure
102
- ```
103
-
104
- **Wrong approach:**
105
-
106
- ```typescript
107
- // BAD - writing tests based on guesses
108
- test("create user", async () => {
109
- const [userId] = await UserModel.save([
110
- {
111
- name: "Test",
112
- status: "active", // may actually be "normal"
113
- role: "user", // may actually be "normal"
114
- },
115
- ]);
116
- });
117
- ```
118
-
119
- **Correct approach:**
120
-
121
- ```typescript
122
- // GOOD - write after checking entity.json
123
- // 1. Check user.entity.json:
124
- // - role: enum ["admin", "normal", "guest"]
125
- // - status: enum ["active", "inactive"] with dbDefault: "active"
126
- // - name: string (required)
127
- // - email: string (nullable)
128
-
129
- // 2. Check user.types.ts:
130
- // - status, email are partial in SaveParams
131
-
132
- // 3. Write test
133
- test("create user", async () => {
134
- const [userId] = await UserModel.save([
135
- {
136
- name: "Test",
137
- role: "normal", // exact enum value from entity.json
138
- // status can be omitted since it has dbDefault
139
- // email can be omitted since it's nullable
140
- },
141
- ]);
142
- });
143
- ```
144
-
145
- ### 2. Understanding Subset Structure
146
-
147
- **Access nested relations using dot notation.**
148
-
149
- ```typescript
150
- // Check Subset definition in entity.json
151
- {
152
- "subsets": {
153
- "A": [
154
- "id",
155
- "title",
156
- "evaluation_form.id", // BelongsToOne relation
157
- "evaluation_form.title",
158
- "evaluation_form.category.id", // nested relation
159
- "evaluation_form.category.name"
160
- ]
161
- }
162
- }
163
-
164
- // Access in tests
165
- test("fetch evaluation item", async () => {
166
- const { itemId } = await createTestEvaluationItemWithDeps();
167
-
168
- const item = await EvaluationItemModel.findById("A", itemId);
169
-
170
- // CORRECT - nested access via dot notation
171
- expect(item.evaluation_form.id).toBe(formId);
172
- expect(item.evaluation_form.category.name).toBe("Competency Evaluation");
173
-
174
- // WRONG - attempting direct FK access
175
- // expect(item.evaluation_form_id).toBe(formId); // type error!
176
- });
177
- ```
178
-
179
- **Important rules:**
180
-
181
- - FK of BelongsToOne relation is defined as `relation.id` form in Subset
182
- - Access in tests as `entity.relation.field` form
183
- - Direct `entity.relation_id` access is not possible (not included in Subset)
184
-
185
- ### 3. Handling DECIMAL Types
186
-
187
- **DECIMAL types are returned from PostgreSQL with a `.00` suffix.**
188
-
189
- ```typescript
190
- // entity.json
191
- {
192
- "props": [
193
- { "name": "salary", "type": "number", "precision": 10, "scale": 2 }
194
- ]
195
- }
196
-
197
- // Generated in migration
198
- table.decimal("salary", 10, 2); // DECIMAL(10,2)
199
-
200
- // Writing tests
201
- test("fetch salary info", async () => {
202
- const [userId] = await UserModel.save([{
203
- name: "Test",
204
- salary: 75000, // input: number
205
- }]);
206
-
207
- const user = await UserModel.findById("A", userId);
208
-
209
- // WRONG - exact comparison may fail
210
- // expect(user.salary).toBe(75000); // DB may return "75000.00"
211
-
212
- // CORRECT - pattern matching with toMatch()
213
- expect(String(user.salary)).toMatch(/^75000(\.00)?$/);
214
-
215
- // Or convert to number and compare
216
- expect(Number(user.salary)).toBe(75000);
217
-
218
- // Or range check
219
- expect(user.salary).toBeGreaterThanOrEqual(74999.99);
220
- expect(user.salary).toBeLessThanOrEqual(75000.01);
221
- });
222
- ```
223
-
224
- **DECIMAL type comparison patterns:**
225
-
226
- ```typescript
227
- // Pattern 1: string pattern matching
228
- expect(String(value)).toMatch(/^1234\.56$/);
229
- expect(String(value)).toMatch(/^1234(\.56)?$/); // .56 optional
230
-
231
- // Pattern 2: convert to number and compare
232
- expect(Number(value)).toBe(1234.56);
233
-
234
- // Pattern 3: range check (considering floating point errors)
235
- expect(value).toBeCloseTo(1234.56, 2); // up to 2 decimal places
236
-
237
- // Pattern 4: toMatchObject (when comparing objects)
238
- expect(result).toMatchObject({
239
- salary: expect.any(Number), // type check only
240
- });
241
- ```
242
-
243
- ## Rules
244
-
245
- - `bootstrap(vi)` call required in all test files
246
- - Each test is automatically rolled back (test isolation)
247
- - Use `test` for unauthenticated tests, `testAs` for authenticated tests
248
- - Define fixtures with `createFixtureLoader` and load with `loadFixtures`
249
- - Use Naite to track and validate query/UpsertBuilder behavior
250
- - Recommend snapshot tests using `toMatchInlineSnapshot()`
251
- - Configure Mocks globally in `setup-mocks.ts` or use `vi.spyOn` within tests
@@ -1,405 +0,0 @@
1
- # DevRunner and Test Configuration
2
-
3
- ## Running Tests
4
-
5
- **Principle: Use `pnpm sonamu test` during development.** Assume the dev server is always running. If the dev server is down, start it first with `pnpm sonamu dev`, then run tests. Use `pnpm test` only in CI environments.
6
-
7
- ```bash
8
- # Check dev server (start if it's down)
9
- pnpm sonamu dev
10
-
11
- # Tests during development (default)
12
- pnpm sonamu test
13
- pnpm sonamu test user.model
14
- pnpm sonamu test user.model -p "findMany"
15
-
16
- # CI environments only
17
- pnpm test
18
- ```
19
-
20
- ---
21
-
22
- ## DevRunner — `sonamu test` (Default Test Execution Method)
23
-
24
- `sonamu test` runs tests through a Vitest Node API instance that resides inside the `sonamu dev` process. Instead of starting Vitest fresh each time, it reuses an already-initialized instance, making execution 3.2x faster, and it integrates with HMR so tests always run against the latest code immediately after source changes.
25
-
26
- ### Prerequisites
27
-
28
- **1. Enable devRunner in sonamu.config.ts:**
29
-
30
- ```typescript
31
- export default defineConfig({
32
- test: {
33
- devRunner: {
34
- enabled: true,
35
- // routePrefix: "/__test__", // optional, default value
36
- // vitestConfigPath: undefined, // optional, default: vitest.config.ts (relative to api-root)
37
- },
38
- },
39
- });
40
- ```
41
-
42
- Configuration type (`SonamuDevRunnerConfig`):
43
-
44
- - `enabled: boolean` — Whether to enable DevRunner (default: false)
45
- - `routePrefix?: string` — Test endpoint path prefix (default: `/__test__`)
46
- - `vitestConfigPath?: string` — vitest.config.ts path (relative to api-root)
47
-
48
- **2. Start the dev server:**
49
-
50
- ```bash
51
- sonamu dev # or pnpm dev
52
- ```
53
-
54
- When the dev server starts, `DevVitestManager` is automatically initialized under the `isLocal() && devRunner.enabled` condition, and test endpoints are registered with Fastify.
55
-
56
- ### CLI Usage
57
-
58
- ```bash
59
- # Run all tests
60
- sonamu test
61
-
62
- # Specify file (matched by partial filename — uses globTestSpecifications)
63
- sonamu test user.model
64
-
65
- # Multiple files
66
- sonamu test user.model order.model
67
-
68
- # Run specific test cases only (test name pattern)
69
- sonamu test user.model --pattern "findMany"
70
- sonamu test user.model -p "findMany"
71
-
72
- # Print Naite traces
73
- sonamu test user.model --traces
74
- sonamu test user.model -t
75
-
76
- # Combine file + pattern + trace
77
- sonamu test user.model -p "findMany" -t
78
- ```
79
-
80
- Argument processing rules:
81
-
82
- - `--pattern` / `-p`: test name string filter (`setGlobalTestNamePattern` → `resetGlobalTestNamePattern` after execution)
83
- - `--traces` / `-t`: boolean flag, enables Naite trace output
84
- - Arguments not starting with `-`: treated as file list
85
- - Multiple files allowed
86
- - `ok: false` in server response is reflected as exit code 1
87
-
88
- ### Naite Trace Output
89
-
90
- The `--traces` / `-t` flag lets you view `Naite.t(key, data)` records from test code in the CLI:
91
-
92
- ```
93
- Tests: 5 passed, 0 failed, 5 total
94
- Duration: 791ms
95
-
96
- Traces:
97
-
98
- UserModel > BaseModel basic functionality check > Model.findMany() with num = 0
99
- user.model.test.ts
100
-
101
- [esq-query] user.model.ts:113
102
- select "users"."id" as "id", ...
103
-
104
- [puri:executed-query] puri.ts:1349
105
- select COUNT(*)::integer as "total" from "users" limit 1
106
- ```
107
-
108
- Without the `--traces` flag, traces are not printed. The API response (`POST /__test__/run`) always includes a `traces` field, so external tools can make use of it.
109
-
110
- For trace data details: see `sonamu-naite`
111
-
112
- ### HMR Integration — Automatic Vitest Module Graph Invalidation on Source Changes
113
-
114
- When a source file is modified, `hmrAndSync` in the syncer triggers both of the following simultaneously:
115
-
116
- 1. Server HMR cache invalidation (`hot.invalidateFile`)
117
- 2. Vitest module graph invalidation (`Sonamu.devVitestManager.invalidateFiles([filePath])`)
118
-
119
- ```
120
- Modify user.model.ts → save
121
- Server log: "Test invalidated: src/application/user/user.model.ts"
122
- sonamu test user.model ← runs with latest code
123
- ```
124
-
125
- Because Vite's `moduleGraph.invalidateModule()` recursively cascades in the importer direction, invalidating a single source file automatically invalidates any test files that import it. No restart is needed.
126
-
127
- **Transitive dependency example:**
128
-
129
- - Change `utils.ts` → `user.model.ts` (imports utils) → `user.model.test.ts` all automatically invalidated
130
-
131
- ### Direct HTTP API Calls
132
-
133
- You can call the HTTP API directly instead of using the CLI:
134
-
135
- ```bash
136
- # Run tests
137
- curl -X POST http://localhost:3000/__test__/run \
138
- -H "Content-Type: application/json" \
139
- -d '{"files": ["user.model"], "pattern": "findMany"}'
140
-
141
- # Check status
142
- curl http://localhost:3000/__test__/status
143
- ```
144
-
145
- **POST `/__test__/run`** request:
146
-
147
- ```json
148
- { "files": ["src/user/user.model.test.ts"], "pattern": "should create user" }
149
- ```
150
-
151
- Response (success):
152
-
153
- ```json
154
- {
155
- "ok": true,
156
- "summary": { "total": 12, "passed": 11, "failed": 1, "skipped": 0, "durationMs": 842 },
157
- "failed": [
158
- {
159
- "file": "src/user/user.model.test.ts",
160
- "name": "UserModel > should create user",
161
- "error": "Expected ..."
162
- }
163
- ],
164
- "traces": [
165
- {
166
- "testName": "UserModel > should create user",
167
- "file": "src/user/user.model.test.ts",
168
- "traces": [
169
- {
170
- "key": "esq-query",
171
- "value": "select ...",
172
- "filePath": "user.model.ts",
173
- "lineNumber": 113,
174
- "at": "2026-02-23T14:51:35+09:00"
175
- }
176
- ]
177
- }
178
- ]
179
- }
180
- ```
181
-
182
- **GET `/__test__/status`** response:
183
-
184
- ```json
185
- { "ready": true, "running": false, "lastRunAt": "2026-02-13T12:34:56.000Z" }
186
- ```
187
-
188
- ### Internal Architecture
189
-
190
- **DevVitestManager** (`testing/dev-vitest-manager.ts`):
191
-
192
- - Creates a resident instance with `createVitest('test', cliOptions, viteOverrides)`
193
- - Configured with `watch: true, standalone: true`, but blocks automatic re-runs:
194
- - `forceRerunTriggers: []`
195
- - `server.watch: null` (chokidar not created)
196
- - `onFilterWatchedSpecification(() => false)`
197
- - Explicitly sets `env: { NODE_ENV: "test" }` so worker processes use the test DB
198
- - **Queue-based sequential execution**: prevents result mixing on concurrent requests, processes in order and responds to each
199
- - **Result aggregation**: filters only the modules requested for execution using `specModuleIds` (works around the issue where `testModules` includes all modules in standalone mode)
200
- - Keeps loading the project's `vitest.config.ts` (reuses existing sequencer/reporter/globalSetup)
201
-
202
- **Fastify integration** (`testing/dev-test-routes.ts`):
203
-
204
- - Registers routes with `registerDevTestRoutes(server, config)`
205
- - Stores manager instance in `Sonamu.devVitestManager`
206
- - Ensures `shutdown()` is called in `server.addHook('onClose')`
207
-
208
- **CLI** (`bin/test-command.ts`):
209
-
210
- - Calls `testCommand()` directly before `tsicli` matching (to handle variadic arguments)
211
- - Included in `bootstrap()`'s `notToInit` list (no need for `Sonamu.init` since it only makes HTTP calls)
212
- - Server port/host read from `server.listen` in `sonamu.config.ts`
213
-
214
- ### Performance Comparison (miomock baseline)
215
-
216
- Single file (`user.model.test.ts`):
217
-
218
- | Item | `vitest run` | `sonamu test` | Difference |
219
- | ------------------------------- | ------------ | ------------- | ----------- |
220
- | Test execution time | 2,610ms | 823ms | 3.2x faster |
221
- | Total elapsed time (wall clock) | 4,118ms | 1,907ms | 2.2x faster |
222
-
223
- Multiple files (puri tests, 4 files 147 tests):
224
-
225
- | Item | `vitest run` | `sonamu test` | Difference |
226
- | ------------------------------- | ------------ | ------------- | ----------- |
227
- | Test execution time | 5,740ms | 1,774ms | 3.2x faster |
228
- | Total elapsed time (wall clock) | 7,035ms | 2,673ms | 2.6x faster |
229
-
230
- Speed difference reason: `vitest run` requires process boot (~1.5s) + module transform (~400ms) on every execution, whereas `sonamu test` reuses an already-initialized instance and avoids this overhead.
231
-
232
- ### `pnpm sonamu test` vs `pnpm test` Comparison
233
-
234
- | | `pnpm sonamu test` (default) | `pnpm test` (CI/fallback) |
235
- | ------------------- | --------------------------------------------- | --------------------------- |
236
- | Execution method | Resident instance inside dev server | Independent Vitest process |
237
- | Initialization cost | None (already initialized) | Initialization on every run |
238
- | HMR integration | Source changes reflected immediately | Not applicable |
239
- | Naite trace | CLI output via `--traces` flag | Available through reporter |
240
- | Use case | **Default test execution during development** | CI environments |
241
- | Prerequisite | `sonamu dev` running (assumed always running) | None |
242
-
243
- ### Troubleshooting
244
-
245
- **"Cannot connect to dev server"**
246
- → Check that `sonamu dev` is running. The CLI sends HTTP requests to `config.server.listen.port`.
247
-
248
- **"devRunner is not enabled" (or 404 response)**
249
- → `test.devRunner.enabled: true` must be set in `sonamu.config.ts`. DevRunner is only activated in `isLocal()` environments.
250
-
251
- **"Vitest instance is not ready yet" (500 response)**
252
- → Request was made before Vitest initialization completed immediately after dev server startup. Check `GET /__test__/status` for `ready: true` before running.
253
-
254
- **Tests running against old code**
255
- → After saving a source file, check whether a `"Test invalidated: ..."` log appears. If not, verify that `devRunner.enabled` is `true` and that the syncer is working correctly.
256
-
257
- ---
258
-
259
- ## Complete Map of Test-Related Settings in sonamu.config.ts
260
-
261
- Both `pnpm sonamu test` (DevRunner, default) and `pnpm test` (direct Vitest execution, CI) reference settings from `sonamu.config.ts`.
262
-
263
- ### Configuration Type Definition (SonamuTestConfig)
264
-
265
- ```typescript
266
- // config.ts
267
- export type SonamuTestConfig = {
268
- /** Enable parallel testing (default: false) */
269
- parallel?: boolean;
270
- /** Number of parallel execution workers (default: 4) */
271
- maxWorkers?: number;
272
- /** Resident Vitest instance settings inside dev server */
273
- devRunner?: SonamuDevRunnerConfig;
274
- };
275
-
276
- export type SonamuDevRunnerConfig = {
277
- /** Whether to enable DevRunner (default: false) */
278
- enabled: boolean;
279
- /** Test endpoint path prefix (default: /__test__) */
280
- routePrefix?: string;
281
- /** vitest.config.ts path (relative to api-root) */
282
- vitestConfigPath?: string;
283
- };
284
- ```
285
-
286
- ### Parallel Test Configuration (Optional)
287
-
288
- Both `pnpm sonamu test` and `pnpm test` share the parallel configuration. Only configure this if parallel execution is needed:
289
-
290
- ```typescript
291
- export default defineConfig({
292
- test: {
293
- parallel: true, // Separate DB execution per worker
294
- maxWorkers: 4, // Number of workers (default: 4)
295
- },
296
- });
297
- ```
298
-
299
- When `parallel: true`, `getSonamuTestConfig()` (vitest-helpers.ts) injects `pool: "forks"`, `maxWorkers`, and `env: { SONAMU_WORKER_DB: "true" }` into vitest, and `globalSetup` (global-setup.ts) creates DBs `{database.name}_test_1` through `{database.name}_test_{maxWorkers}` by cloning from the template (`{database.name}_test`).
300
-
301
- ### DevRunner Configuration (Required)
302
-
303
- To use `pnpm sonamu test`, DevRunner must be enabled. Just add `test.devRunner.enabled: true`:
304
-
305
- ```typescript
306
- export default defineConfig({
307
- server: {
308
- listen: {
309
- port: 3000, // CLI sends HTTP requests to this port
310
- host: "localhost", // CLI connects to this host (default: localhost)
311
- },
312
- },
313
-
314
- test: {
315
- devRunner: {
316
- enabled: true, // Required: enable DevRunner
317
- // routePrefix: "/__test__", // Optional: endpoint path (default value)
318
- // vitestConfigPath: undefined, // Optional: vitest.config.ts path (default: vitest.config.ts in api-root)
319
- },
320
- // parallel: true, // Optional: independent of DevRunner
321
- // maxWorkers: 4, // Optional: when using parallel
322
- },
323
- });
324
- ```
325
-
326
- ### Source Code Reference Locations per Setting
327
-
328
- | Setting path | Default | Reference location | Purpose |
329
- | --------------------------------- | ------------- | ----------------------------------------------- | -------------------------------------------------- |
330
- | `test.devRunner.enabled` | `false` | `sonamu.ts` L394, `test-command.ts` | DevRunner activation condition |
331
- | `test.devRunner.routePrefix` | `"/__test__"` | `dev-test-routes.ts`, `test-command.ts` | HTTP endpoint path |
332
- | `test.devRunner.vitestConfigPath` | `undefined` | `dev-vitest-manager.ts` `start()` | Vitest config file location |
333
- | `test.parallel` | `false` | `vitest-helpers.ts` `getSonamuTestConfig()` | `pool: "forks"` + `SONAMU_WORKER_DB` env injection |
334
- | `test.maxWorkers` | `4` | `vitest-helpers.ts`, `global-setup.ts` | Vitest maxWorkers + number of worker DBs |
335
- | `server.listen.port` | `3000` | `test-command.ts` | CLI → dev server HTTP connection port |
336
- | `server.listen.host` | `"localhost"` | `test-command.ts` | CLI → dev server HTTP connection host |
337
- | `database.name` | — | `db.ts` `generateDBConfig()`, `global-setup.ts` | Test DB name (`{name}_test`) |
338
-
339
- ### Activation Conditions
340
-
341
- DevRunner is registered in `sonamu.ts` under the condition `isLocal() && config.test?.devRunner?.enabled`. `isLocal()` returns true when `NODE_ENV` is `development` or `test` (`controller.ts`). It works in local development and test environments and is disabled in staging/production environments.
342
-
343
- ### Parallel Test DB Flow
344
-
345
- DB flow when `test.parallel: true` is set:
346
-
347
- 1. **globalSetup** (`global-setup.ts`): Clones `{database.name}_test_1` through `_test_{maxWorkers}` from `{database.name}_test` as template
348
- 2. **getSonamuTestConfig** (`vitest-helpers.ts`): Injects `env: { SONAMU_WORKER_DB: "true" }` into vitest
349
- 3. **DB.getDB** (`db.ts`): When `SONAMU_WORKER_DB=true`, selects worker-specific DB using `VITEST_POOL_ID` environment variable (`{database.name}_test_{workerId}`)
350
- 4. **globalTeardown**: Deletes all worker DBs
351
-
352
- When `test.parallel: false` (default), all tests run sequentially on the single `{database.name}_test` DB.
353
-
354
- ---
355
-
356
- ## Configuration Files
357
-
358
- ### vitest.config.ts
359
-
360
- ```typescript
361
- import { getSonamuTestConfig, NaiteVitestReporter } from "sonamu/test";
362
- import { defineConfig } from "vitest/config";
363
-
364
- export default defineConfig(async () => ({
365
- test: await getSonamuTestConfig({
366
- include: ["src/**/*.test.ts"],
367
- exclude: ["src/**/*.test-hold.ts"],
368
- globals: true,
369
- globalSetup: ["./src/testing/global.ts"],
370
- setupFiles: ["./src/testing/setup-mocks.ts"],
371
- reporters: ["default", NaiteVitestReporter],
372
- restoreMocks: true,
373
- }),
374
- }));
375
- ```
376
-
377
- ### global.ts
378
-
379
- ```typescript
380
- import dotenv from "dotenv";
381
- dotenv.config();
382
- export { setup } from "sonamu/test";
383
- ```
384
-
385
- ### sonamu.config.ts (test configuration)
386
-
387
- ```typescript
388
- export default defineConfig({
389
- test: {
390
- parallel: true, // Enable parallel testing
391
- maxWorkers: 4, // Number of workers (default: 4)
392
- devRunner: {
393
- enabled: true, // Enable DevRunner
394
- },
395
- },
396
- });
397
- ```
398
-
399
- ---
400
-
401
- ## References
402
-
403
- - **Test writing guide**: `sonamu-testing`
404
- - **Naite tracing system**: `sonamu-naite`
405
- - **Fixture CLI**: `sonamu-fixture`