cabloy 5.1.204 → 5.1.205
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/.cabloy-version +1 -1
- package/.gitignore +2 -0
- package/CHANGELOG.md +11 -0
- package/lint-staged.config.mjs +2 -0
- package/oxfmt.config.ts +2 -0
- package/oxlint.config.ts +2 -0
- package/package.json +2 -3
- package/repo-agent-governance/managed-assets.json +6 -6
- package/repo-agent-governance/policies/repository.md +3 -2
- package/repo-agent-governance/skills/cabloy-workflow/SKILL.md +2 -0
- package/repo-docs/backend/migration-and-changes.md +13 -12
- package/repo-docs/backend/runtime-and-flavors.md +2 -1
- package/repo-docs/backend/unit-testing.md +12 -8
- package/repo-docs/blogs/ai-coding-one-prompt-crud-ssr-multitasking/index.md +9 -9
- package/repo-docs/frontend/scripts.md +1 -1
- package/repo-docs/fullstack/parallel-worktree-environment.md +6 -6
- package/repo-docs/fullstack/ssr-entry-modes.md +19 -0
- package/repo-docs/reference/repo-scripts.md +22 -1
- package/repo-e2e/config/playwright.config.ts +32 -14
- package/repo-e2e/scripts/e2e.test.ts +39 -0
- package/repo-e2e/scripts/e2e.ts +19 -1
- package/repo-e2e/scripts/managedTest.test.ts +389 -0
- package/repo-e2e/scripts/managedTest.ts +210 -0
- package/repo-e2e/scripts/managedTestImports.test.ts +74 -0
- package/repo-e2e/scripts/managedTestImports.ts +110 -0
- package/repo-e2e/scripts/runE2e.ts +12 -1
- package/repo-e2e/scripts/startE2eVona.ts +37 -5
- package/repo-e2e/specs/a-commerce.spec.ts +1 -1
- package/repo-e2e/specs/cabloy-basic.spec.ts +1 -1
- package/repo-e2e/specs/controller-boundary.spec.ts +1 -1
- package/repo-e2e/specs/home-user-account.spec.ts +2 -1
- package/repo-e2e/specs/markdown.spec.ts +1 -1
- package/repo-e2e/specs/routed-dialog.spec.ts +1 -1
- package/scripts/runIsolatedTest.test.ts +426 -0
- package/scripts/runIsolatedTest.ts +454 -0
- package/scripts/testClaimCleanup.test.ts +346 -0
- package/scripts/testClaimCleanup.ts +375 -0
- package/scripts/testClaimProcesses.test.ts +106 -0
- package/scripts/testClaimProcesses.ts +129 -0
- package/scripts/testProcessGuardian.ts +163 -0
- package/scripts/upgrade.ts +1 -16
- package/vona/oxfmt.config.ts +2 -0
- package/vona/oxlint.config.ts +2 -0
- package/vona/package.original.json +2 -2
- package/vona/packages-cli/cli/package.json +1 -1
- package/vona/packages-cli/cli/src/play.test.ts +37 -0
- package/vona/packages-cli/cli/src/play.ts +23 -1
- package/vona/packages-cli/cli-set-api/package.json +1 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dbReset.ts +16 -7
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.dev.ts +13 -7
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.play.ts +5 -1
- package/vona/packages-cli/cli-set-api/src/lib/bean/cli.bin.test.ts +12 -7
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/configUtils.ts +21 -2
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/generateVonaMeta.ts +10 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/resolveTestCleanupConfig.test.ts +153 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/resolveTestCleanupConfig.ts +141 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupAdapters.test.ts +148 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupAdapters.ts +127 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupProcess.test.ts +47 -0
- package/vona/packages-cli/cli-set-api/src/lib/bean/toolsBin/testCleanupProcess.ts +139 -0
- package/vona/packages-cli/cli-set-api/src/lib/utils.ts +2 -3
- package/vona/packages-cli/cli-set-api/templates/config/_tsconfig_project.json +1 -0
- package/vona/packages-cli/cli-set-api/templates/config/_tsconfig_source.json +1 -0
- package/vona/packages-cli/cli-set-api/test/binDevMode.test.ts +18 -0
- package/vona/packages-cli/cli-set-api/toolsIsolate/dbReset.ts +15 -2
- package/vona/packages-cli/cli-set-api/tsconfig.build.json +2 -1
- package/vona/packages-utils/babel-plugin-vona-bean-module/package.json +1 -1
- package/vona/packages-utils/babel-plugin-vona-bean-module/src/index.test.ts +16 -0
- package/vona/packages-utils/babel-plugin-vona-bean-module/src/index.ts +3 -2
- package/vona/packages-vona/vona/package.json +1 -1
- package/vona/packages-vona/vona-core/package.json +1 -1
- package/vona/packages-vona/vona-core/src/lib/addon/sqlite3.ts +1 -1
- package/vona/packages-vona/vona-core/src/lib/core/config.ts +44 -6
- package/vona/packages-vona/vona-core/src/lib/core/configCleanup.test.ts +40 -0
- package/vona/packages-vona/vona-core/src/lib/core/index.ts +3 -0
- package/vona/packages-vona/vona-core/src/lib/core/isolationGuard.test.ts +301 -0
- package/vona/packages-vona/vona-core/src/lib/core/isolationGuard.ts +312 -0
- package/vona/packages-vona/vona-core/src/lib/core/testClaim.test.ts +577 -0
- package/vona/packages-vona/vona-core/src/lib/core/testClaim.ts +985 -0
- package/vona/packages-vona/vona-core/src/lib/core/testIsolation.ts +129 -0
- package/vona/packages-vona/vona-core/src/lib/framework/createApp.ts +2 -0
- package/vona/packages-vona/vona-core/src/lib/framework/start.ts +4 -0
- package/vona/packages-vona/vona-core/src/lib/framework/useApp.ts +5 -1
- package/vona/packages-vona/vona-core/src/types/application/app.ts +2 -0
- package/vona/packages-vona/vona-core/src/types/utils/env.ts +1 -0
- package/vona/packages-vona/vona-mock/package.json +1 -1
- package/vona/pnpm-lock.yaml +1 -1
- package/vona/src/suite/a-commerce/modules/commerce-payment/test/paymentIndexes.test.ts +73 -10
- package/vona/src/suite-vendor/a-cabloy/modules/a-rbac/package.json +1 -1
- package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
- package/vona/src/suite-vendor/a-vona/modules/a-core/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/src/bean/middlewareSystem.httpLog.ts +15 -1
- package/vona/src/suite-vendor/a-vona/modules/a-logger/src/lib/redactIsolatedReadyHeader.test.ts +24 -0
- package/vona/src/suite-vendor/a-vona/modules/a-logger/src/lib/redactIsolatedReadyHeader.ts +11 -0
- package/vona/src/suite-vendor/a-vona/modules/a-metrics/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-metrics/src/bean/middlewareSystem.health.ts +15 -0
- package/vona/src/suite-vendor/a-vona/modules/a-orm/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/extend/schemaBuilder.ts +11 -4
- package/vona/src/suite-vendor/a-vona/modules/a-orm/src/service/databaseClient_.ts +6 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.betterSqlite3.ts +41 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.mysql.ts +4 -1
- package/vona/src/suite-vendor/a-vona/modules/a-ormdialect/src/bean/databaseDialect.pg.ts +2 -1
- package/vona/src/suite-vendor/a-vona/modules/a-permission/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-redis/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/lib/redis.ts +8 -0
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redis.ts +23 -6
- package/vona/src/suite-vendor/a-vona/modules/a-redis/src/service/redisClient_.ts +18 -1
- package/vona/src/suite-vendor/a-vona/modules/a-startup/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-startup/src/service/startup.ts +43 -15
- package/vona/src/suite-vendor/a-vona/modules/a-version/package.json +1 -1
- package/vona/src/suite-vendor/a-vona/modules/a-version/src/lib/databaseTestName.ts +3 -37
- package/vona/src/suite-vendor/a-vona/modules/a-version/src/service/database.ts +93 -15
- package/vona/src/suite-vendor/a-vona/package.json +1 -1
- package/vona/tsconfig.json +1 -0
- package/scripts/initTestData.ts +0 -25
package/.cabloy-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
5.1.
|
|
1
|
+
5.1.205
|
package/.gitignore
CHANGED
package/CHANGELOG.md
CHANGED
package/lint-staged.config.mjs
CHANGED
package/oxfmt.config.ts
CHANGED
package/oxlint.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cabloy",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.205",
|
|
4
4
|
"gitHead": "2c5c19284bab738e492856189acb6fad74b8a7b7",
|
|
5
5
|
"description": "A Node.js fullstack framework",
|
|
6
6
|
"keywords": [
|
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
"type": "module",
|
|
23
23
|
"scripts": {
|
|
24
24
|
"init": "node scripts/init.ts",
|
|
25
|
-
"init:test-data": "node scripts/initTestData.ts",
|
|
26
25
|
"upgrade": "node scripts/upgrade.ts",
|
|
27
26
|
"upgrade:dry-run": "node scripts/upgrade.ts --dry-run",
|
|
28
27
|
"vona": "node ./vona/packages-cli/cli/src/bin/vona.ts --projectPath=vona",
|
|
@@ -47,7 +46,7 @@
|
|
|
47
46
|
"start": "cd vona && npm run start",
|
|
48
47
|
"start:one": "cd vona && npm run start:one",
|
|
49
48
|
"test": "cd vona && npm run test",
|
|
50
|
-
"test:e2e": "node
|
|
49
|
+
"test:e2e": "node scripts/runIsolatedTest.ts e2e",
|
|
51
50
|
"test:docs:e2e": "npm run docs:build && playwright test --config repo-e2e/docs/playwright.config.ts",
|
|
52
51
|
"db:reset": "cd vona && npm run db:reset",
|
|
53
52
|
"tsc": "npm run tsc:zova && pnpm --dir vona run tsc",
|
|
@@ -277,7 +277,7 @@
|
|
|
277
277
|
{
|
|
278
278
|
"adapter": "codex",
|
|
279
279
|
"category": "skill",
|
|
280
|
-
"sha256": "
|
|
280
|
+
"sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
|
|
281
281
|
"source": "skills/cabloy-workflow/SKILL.md",
|
|
282
282
|
"target": ".agents/skills/cabloy-workflow/SKILL.md"
|
|
283
283
|
},
|
|
@@ -613,7 +613,7 @@
|
|
|
613
613
|
{
|
|
614
614
|
"adapter": "claude",
|
|
615
615
|
"category": "skill",
|
|
616
|
-
"sha256": "
|
|
616
|
+
"sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
|
|
617
617
|
"source": "skills/cabloy-workflow/SKILL.md",
|
|
618
618
|
"target": ".claude/skills/cabloy-workflow/SKILL.md"
|
|
619
619
|
},
|
|
@@ -683,7 +683,7 @@
|
|
|
683
683
|
{
|
|
684
684
|
"adapter": "cursor",
|
|
685
685
|
"category": "policy",
|
|
686
|
-
"sha256": "
|
|
686
|
+
"sha256": "539fa24fc49fa8402ea0d9ab89c058762c441d5b3ed87af34a16235d1f8251a0",
|
|
687
687
|
"source": "policies/repository.md",
|
|
688
688
|
"target": ".cursor/rules/cabloy-governance.mdc"
|
|
689
689
|
},
|
|
@@ -963,7 +963,7 @@
|
|
|
963
963
|
{
|
|
964
964
|
"adapter": "cursor",
|
|
965
965
|
"category": "skill",
|
|
966
|
-
"sha256": "
|
|
966
|
+
"sha256": "eccad69c3969f97e80a3766fc2149b9f3e0bf2acd0c8586ed7bed0418f6878a9",
|
|
967
967
|
"source": "skills/cabloy-workflow/SKILL.md",
|
|
968
968
|
"target": ".cursor/skills/cabloy-workflow/SKILL.md"
|
|
969
969
|
},
|
|
@@ -1005,14 +1005,14 @@
|
|
|
1005
1005
|
{
|
|
1006
1006
|
"adapter": "codex",
|
|
1007
1007
|
"category": "policy",
|
|
1008
|
-
"sha256": "
|
|
1008
|
+
"sha256": "f8172d4e80dc8b84bf99a0e926184eb78af5bd1fdfcdeebe63b02160f459afce",
|
|
1009
1009
|
"source": "policies/repository.md",
|
|
1010
1010
|
"target": "AGENTS.md"
|
|
1011
1011
|
},
|
|
1012
1012
|
{
|
|
1013
1013
|
"adapter": "claude",
|
|
1014
1014
|
"category": "policy",
|
|
1015
|
-
"sha256": "
|
|
1015
|
+
"sha256": "f8172d4e80dc8b84bf99a0e926184eb78af5bd1fdfcdeebe63b02160f459afce",
|
|
1016
1016
|
"source": "policies/repository.md",
|
|
1017
1017
|
"target": "CLAUDE.md"
|
|
1018
1018
|
}
|
|
@@ -71,7 +71,8 @@ Before inventing a custom implementation path:
|
|
|
71
71
|
- Treat hooks, permissions, local settings, credentials, MCP registration, command discovery, and automatic command execution as platform-specific integrations, not portable rule or skill capabilities.
|
|
72
72
|
- After implementation, do not launch broad reviews automatically; when review is needed, scope it to the current diff and report only high-confidence issues.
|
|
73
73
|
- Do not modify shared environment identity or ports merely to bypass a busy resource. For intentional parallel worktree setup, follow `repo-docs/fullstack/parallel-worktree-environment.md`; otherwise wait for the shared resource or ask the user. Create or change worktree-local environment overrides only through the explicitly invoked `cabloy-worktree-environment` skill and its confirmation phase, and only in `vona/env/.env.local` and `zova/env/.env.local`; never modify flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. The skill derives the standard `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and API-derived `API_BASE_URL` tuple only from Git worktree metadata and fixed port baselines; never read or expose `.env*` content while recommending values. Admin and Web are alternative commands using this shared tuple and must not run concurrently in one worktree; use another linked worktree for concurrent use. Detect the active edition before choosing scripts, and never run `npm run init` as an automatic follow-up.
|
|
74
|
-
-
|
|
74
|
+
- In Cabloy Basic, root `npm run test` and `npm run test:e2e` always allocate an isolated same-checkout test run: disposable run-specific database and Redis namespaces, runtime/public paths, and listener. This protects ordinary development business data, including when a dev server is active in the same checkout. Shared preparation writes (such as builds or dependency generation) are separate accepted prerequisites, not test cleanup of dev business data; do not treat the test isolation as permission to run manual resets or change shared configuration. Check the active edition's scripts before extending this guarantee to Cabloy Start. See `repo-docs/reference/repo-scripts.md`.
|
|
75
|
+
- For isolated E2E through Vona integrated SSR, do not edit Zova `API_BASE_URL` environment values or rebuild solely to match the test port: Vona supplies runtime server/browser API origins. On an origin mismatch, check explicit SSR Site and module-specific API URL overrides first; follow the active repository's scripts for changed SSR/REST artifacts and dependency synchronization. Do not generalize this handoff to Zova standalone SSR or SPA. See [Runtime API origins](repo-docs/fullstack/ssr-entry-modes.md#runtime-api-origins-in-vona-integrated-ssr).
|
|
75
76
|
- For SSR theme-sensitive frontend work, detect the active edition marker and UI library before making assumptions. Cabloy Basic currently means DaisyUI + Tailwind CSS assumptions; Cabloy Start currently means Vuetify assumptions.
|
|
76
77
|
- In Web SSR without cookie-backed theme resolution, do not treat server reads of `$theme.dark`, `$theme.darkMode`, or `$token` as final browser truth. Keep theme-sensitive SSR branching hydration-tolerant or defer final theme-sensitive decisions to the client.
|
|
77
78
|
- Do not assume Cabloy Basic and Cabloy Start use the same adapter-level SSR theme handoff. Verify the active theme handler and client hydration path before changing SSR theme behavior.
|
|
@@ -95,7 +96,7 @@ Before inventing a custom implementation path:
|
|
|
95
96
|
- Do not set `TEST_CONCURRENCY=false` for normal `npm run test` or CI runs: an unset value defaults to concurrent execution. For stateful `node:test` suites, declare `{ concurrency: false }` explicitly. Prove business contention by explicitly launching competing operations and asserting their combined durable outcome, never through runner parallelism or scheduling.
|
|
96
97
|
- Unit tests must not temporarily mutate process-global origin or proxy configuration, including `app.config.server.serve.protocol`, `app.config.server.serve.host`, and `app.proxy`. Model request-origin cases with an explicit `req` fixture, and use the established `AppUtil` loopback fallback for requestless local URLs. Do not introduce a broad origin lock to serialize such tests; retain narrowly scoped locks only for genuinely shared domain state.
|
|
97
98
|
- Unit tests must delete every test-owned persisted resource in `finally`, using precise owned identities and reverse dependency order.
|
|
98
|
-
- Shared durable test or local-development fixtures must be created through the owning module's `meta.version.ts` `seed()` hook and treated as read-only by tests;
|
|
99
|
+
- Shared durable test or local-development fixtures must be created through the owning module's `meta.version.ts` `seed()` hook and treated as read-only by tests; seeds run on isolated test-mode startup or after an explicit dev-mode `npm run db:reset` against a newly recreated disposable database, not on ordinary dev startup or repeatedly against one database.
|
|
99
100
|
|
|
100
101
|
## Verification expectations
|
|
101
102
|
|
|
@@ -113,6 +113,8 @@ This routing skill provides read-only guidance only. Do not infer an `APP_NAME`
|
|
|
113
113
|
|
|
114
114
|
The invoked skill detects Basic or Start to select the active root scripts and managed E2E command. It uses Git worktree metadata, fixed Vona/Zova port baselines, and the worktree basename to recommend the complete standard tuple for confirmation: `APP_NAME`, `SERVER_LISTEN_PORT`, `DEV_SERVER_PORT`, `DEV_SERVER_HMR_PORT`, and an `API_BASE_URL` derived from the Vona port. After confirmation, it writes both `vona/env/.env.local` and `zova/env/.env.local`; never use flavor-, mode-, app-mode-, or runtime-specific `.env.*.local` files. It does not inspect environment-file content or allocate/reserve a live port. The shared environment is Vona + Zova development: Admin and Web are alternative commands using the same configuration, and they must not run concurrently in one worktree. Concurrent use requires separately configured linked worktrees.
|
|
115
115
|
|
|
116
|
+
For isolated E2E through Vona integrated SSR, use the [runtime API-origin guidance](../../../repo-docs/fullstack/ssr-entry-modes.md#runtime-api-origins-in-vona-integrated-ssr): a dynamic test port alone requires neither a Zova `.env` edit nor a frontend rebuild. This is separate from explicitly requested worktree development configuration; check the active scripts for artifact preparation and explicit API URL overrides.
|
|
117
|
+
|
|
116
118
|
## Step 4: Prefer CLI-first workflows
|
|
117
119
|
|
|
118
120
|
Whenever the task maps to an existing generator, initializer, refactor, or metadata command, prefer the CLI.
|
|
@@ -94,11 +94,11 @@ export class MetaVersion extends BeanBase {}
|
|
|
94
94
|
|
|
95
95
|
Three migration scenarios are defined:
|
|
96
96
|
|
|
97
|
-
| Scenario | Purpose
|
|
98
|
-
| -------- |
|
|
99
|
-
| `update` | schema evolution such as tables and fields
|
|
100
|
-
| `init` | instance- or tenant-specific initialization data
|
|
101
|
-
| `seed` |
|
|
97
|
+
| Scenario | Purpose |
|
|
98
|
+
| -------- | --------------------------------------------------- |
|
|
99
|
+
| `update` | schema evolution such as tables and fields |
|
|
100
|
+
| `init` | instance- or tenant-specific initialization data |
|
|
101
|
+
| `seed` | baseline data for test runs and explicit dev resets |
|
|
102
102
|
|
|
103
103
|
This split is one of the most important Vona migration ideas because it separates:
|
|
104
104
|
|
|
@@ -110,7 +110,7 @@ A practical generated-thread interpretation is:
|
|
|
110
110
|
|
|
111
111
|
- `update` follows schema and entity/model evolution
|
|
112
112
|
- `init` follows instance-aware initialization needs introduced by the backend feature
|
|
113
|
-
- `seed` provides shared baseline data
|
|
113
|
+
- `seed` provides shared baseline data during test-mode startup or an explicit development database reset
|
|
114
114
|
|
|
115
115
|
## Update: schema migration
|
|
116
116
|
|
|
@@ -153,7 +153,7 @@ export class MetaVersion extends BeanBase implements IMetaVersionInit {
|
|
|
153
153
|
|
|
154
154
|
The important point is that initialization can run per instance or tenant, which keeps tenant data isolated.
|
|
155
155
|
|
|
156
|
-
## Seed: test
|
|
156
|
+
## Seed: test and reset baseline data
|
|
157
157
|
|
|
158
158
|
Representative pattern:
|
|
159
159
|
|
|
@@ -171,9 +171,9 @@ export class MetaVersion extends BeanBase implements IMetaVersionSeed {
|
|
|
171
171
|
|
|
172
172
|
This is valuable because shared baseline data becomes part of the structured version lifecycle instead of being scattered across unrelated setup code.
|
|
173
173
|
|
|
174
|
-
Vona invokes `seed()` while the application starts in test mode. Use
|
|
174
|
+
Vona invokes `seed()` while the application starts in test mode (`npm run test` or managed E2E), and during an explicit `npm run db:reset` in dev mode. Ordinary development startup and framework upgrades do not seed or reset development data automatically. Use `seed()` for durable baseline fixtures shared by tests or for freshly prepared local development data. Both paths seed after instance initialization on a newly recreated disposable database; `seed()` is not a repeatable, same-database data-import mechanism.
|
|
175
175
|
|
|
176
|
-
Treat shared `seed()` records as read-only in ordinary tests. A scenario that needs different state must create independent, test-owned data and clean it up in `finally`; it must not mutate or delete the shared baseline. `seed()` remains distinct from `init()`: use `init()` for instance-aware initialization data and reserve `seed()` for
|
|
176
|
+
Treat shared `seed()` records as read-only in ordinary tests. A scenario that needs different state must create independent, test-owned data and clean it up in `finally`; it must not mutate or delete the shared baseline. `seed()` remains distinct from `init()`: use `init()` for instance-aware initialization data and reserve `seed()` for baseline data in test runs or explicit development resets.
|
|
177
177
|
|
|
178
178
|
## Version changes across the generated backend thread
|
|
179
179
|
|
|
@@ -199,13 +199,14 @@ Representative commands:
|
|
|
199
199
|
|
|
200
200
|
```bash
|
|
201
201
|
npm run test
|
|
202
|
-
|
|
202
|
+
npm run db:reset
|
|
203
203
|
```
|
|
204
204
|
|
|
205
205
|
A practical decision rule is:
|
|
206
206
|
|
|
207
|
-
- use `db:reset`
|
|
208
|
-
-
|
|
207
|
+
- use `db:reset` to recreate the disposable **dev-mode** databases, rerun migrations and instance initialization, and then invoke module `seed()` hooks; it deletes existing matching development databases, so do not run it against data you need to keep
|
|
208
|
+
- `db:reset` requires `database.testDatabase: true` in dev config and a connection outside the disposable database; it refuses to reset a configured non-disposable database
|
|
209
|
+
- use `test` when you need **test-mode** verification of migration, controller behavior, and the broader generated contract thread; E2E also remains test-mode
|
|
209
210
|
|
|
210
211
|
## Implementation checks for migration-sensitive changes
|
|
211
212
|
|
|
@@ -57,7 +57,8 @@ cd vona && npm run start:one
|
|
|
57
57
|
In the current repo, those scripts map naturally to:
|
|
58
58
|
|
|
59
59
|
- `dev` commands -> development mode
|
|
60
|
-
- `test` / `cov`
|
|
60
|
+
- `test` / `cov` -> test mode through the same per-run isolated runner as root `npm run test` (root `npm run test:e2e` also uses an isolated test mode); raw `:bin:test` bypasses the wrapper
|
|
61
|
+
- `db:reset` -> development mode (explicitly recreates disposable development databases and runs module seeds)
|
|
61
62
|
- `build` / `start` -> production mode
|
|
62
63
|
|
|
63
64
|
## Flavors
|
|
@@ -47,12 +47,14 @@ npm run test
|
|
|
47
47
|
A typical Vona test flow includes:
|
|
48
48
|
|
|
49
49
|
1. create one shared global `app` object for the test run
|
|
50
|
-
2. clean Redis
|
|
51
|
-
3. recreate the database
|
|
52
|
-
4. execute migration code
|
|
50
|
+
2. clean the run's Redis namespace and run-specific public/runtime paths
|
|
51
|
+
3. recreate the run's disposable test database
|
|
52
|
+
4. execute migration and instance initialization code, then module `seed()` hooks
|
|
53
53
|
5. run the test files
|
|
54
54
|
6. close the shared application after the test run
|
|
55
55
|
|
|
56
|
+
In Cabloy Basic, root `npm run test` delegates to `vona/`'s `npm run test`; both allocate an isolated test identity, database and Redis namespace, Vona generated/runtime/public paths, and loopback listener. They can run in the same checkout as an ordinary development server without resetting or mutating that server's business data. Even a targeted run performs the test-mode setup. The Vona `npm run cov` script uses the same isolation; raw `:bin:test` commands do not. Shared build/dependency preparation may still write to shared artifacts, and custom external resources need separate isolation. See [Repo Scripts](/reference/repo-scripts#test-isolation-and-development-data-in-cabloy-basic).
|
|
57
|
+
|
|
56
58
|
The runner owns this application lifecycle. Test files import the shared app from `vona-mock` and must not create or close it themselves:
|
|
57
59
|
|
|
58
60
|
```typescript
|
|
@@ -61,15 +63,15 @@ import { app } from 'vona-mock';
|
|
|
61
63
|
|
|
62
64
|
This is one of the most important distinctions from ordinary app flow: test execution rebuilds and verifies the framework lifecycle, not only the target function.
|
|
63
65
|
|
|
64
|
-
## Reset database without running tests
|
|
66
|
+
## Reset development database without running tests
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
From the repository root:
|
|
67
69
|
|
|
68
70
|
```bash
|
|
69
|
-
|
|
71
|
+
npm run db:reset
|
|
70
72
|
```
|
|
71
73
|
|
|
72
|
-
This is
|
|
74
|
+
This is an explicit, destructive **dev-mode** command, not test isolation: it recreates matching disposable development databases, reapplies migration and instance initialization, and runs module `seed()` hooks. It requires `database.testDatabase: true` in dev configuration and a connection outside the disposable database. Ordinary dev startup does not seed; do not reset if you need to keep its existing business data. See [Migration and Changes](/backend/migration-and-changes#local-development-workflow).
|
|
73
75
|
|
|
74
76
|
## Coverage
|
|
75
77
|
|
|
@@ -79,6 +81,8 @@ Representative command:
|
|
|
79
81
|
cd vona && npm run cov
|
|
80
82
|
```
|
|
81
83
|
|
|
84
|
+
This script runs under the same isolated test environment as Vona's `npm run test`. It writes `vona/coverage/lcov.info` and, unless `--ci` is supplied, `vona/coverage/report`. These reports are shared checkout-level artifacts rather than per-run test data; do not run coverage jobs simultaneously in one checkout. Use `npm run cov -- --ci` to skip the viewer in CI.
|
|
85
|
+
|
|
82
86
|
## Runner concurrency
|
|
83
87
|
|
|
84
88
|
The Vona runner uses Node's built-in test runner with one shared application and process isolation disabled. `TEST_CONCURRENCY` controls runner scheduling:
|
|
@@ -129,7 +133,7 @@ Locale-sensitive variants and additional request-context helpers are also availa
|
|
|
129
133
|
Classify persisted test data before creating it:
|
|
130
134
|
|
|
131
135
|
- use a **test-local fixture** for a single test or scenario;
|
|
132
|
-
- use an owning module's `meta.version.ts` `seed()` hook only for stable baseline data shared across
|
|
136
|
+
- use an owning module's `meta.version.ts` `seed()` hook only for stable baseline data shared across isolated test runs or intentionally prepared by an explicit dev-mode database reset.
|
|
133
137
|
|
|
134
138
|
A test owns every persisted resource it creates. Keep the returned entity or exact ID and delete owned records from `finally`, including when an assertion or action fails. Delete dependents before their owners and use the same active tenant/instance context that created them. Do not discover cleanup targets through broad table queries, time-based prefixes, or business conditions when the test already knows the exact identity.
|
|
135
139
|
|
|
@@ -57,11 +57,11 @@ It examines the project and generator commands, then uses Vona's CRUD generator
|
|
|
57
57
|
|
|
58
58
|
The resulting book form has three fields:
|
|
59
59
|
|
|
60
|
-
| Field
|
|
61
|
-
|
|
|
62
|
-
| Title
|
|
63
|
-
| Author
|
|
64
|
-
| Description | Book description | Optional
|
|
60
|
+
| Field | Purpose | Requirement |
|
|
61
|
+
| ----------- | ---------------- | ----------- |
|
|
62
|
+
| Title | Book title | Required |
|
|
63
|
+
| Author | Book author | Required |
|
|
64
|
+
| Description | Book description | Optional |
|
|
65
65
|
|
|
66
66
|
One useful part of the development experience is immediately apparent: **once the business resource is defined, the list, detail view, and forms can reuse CabloyJS's existing schema-driven CRUD pages. There is no need to build a new management interface from scratch.**
|
|
67
67
|
|
|
@@ -163,10 +163,10 @@ Don't submit this time. Leave the form as a draft.
|
|
|
163
163
|
|
|
164
164
|
The task tabs now contain three open tasks:
|
|
165
165
|
|
|
166
|
-
| Task
|
|
167
|
-
|
|
|
168
|
-
| Edit
|
|
169
|
-
| Detail | Book One's detail view
|
|
166
|
+
| Task | Content |
|
|
167
|
+
| ------ | --------------------------- |
|
|
168
|
+
| Edit | Book One's edit form |
|
|
169
|
+
| Detail | Book One's detail view |
|
|
170
170
|
| Create | Book Two's unsubmitted form |
|
|
171
171
|
|
|
172
172
|
### Switch Back and Continue Where You Left Off
|
|
@@ -51,7 +51,7 @@ The `dev:zova:*` commands start the Zova development server, which uses `9000` i
|
|
|
51
51
|
|
|
52
52
|
## Vona integrated SSR browser acceptance
|
|
53
53
|
|
|
54
|
-
The default Basic Web and Admin sites have browser smoke commands that exercise Vona integrated SSR through Vona SSR dispatch at
|
|
54
|
+
The default Basic Web and Admin sites have browser smoke commands that exercise Vona integrated SSR through Vona SSR dispatch at the managed run's dynamically allocated test listener, not through the ordinary Vona development listener (`7102` by default) or the Zova standalone SSR development-server port. Vona supplies the API origin at runtime, so no Zova `.env` change or rebuild is needed solely for the test port; see [Runtime API origins in Vona integrated SSR](/fullstack/ssr-entry-modes#runtime-api-origins-in-vona-integrated-ssr).
|
|
55
55
|
|
|
56
56
|
Prepare current SSR and REST artifacts explicitly when frontend output has changed:
|
|
57
57
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Parallel Worktree Environment
|
|
2
2
|
|
|
3
|
-
Use worktree-local environment overrides when two Cabloy Basic or Cabloy Start worktrees need to run ordinary local development
|
|
3
|
+
Use worktree-local environment overrides when two Cabloy Basic or Cabloy Start worktrees need to run ordinary local development at the same time. In Cabloy Basic, root `npm run test` and `npm run test:e2e` already isolate their test-mode runtime and data on every run, including alongside ordinary dev in the **same** checkout; they do not require this worktree setup for that purpose.
|
|
4
4
|
|
|
5
|
-
This Cabloy Basic page is the canonical shared recipe for both editions. Detect the active edition before selecting commands, but keep the same two-file environment model.
|
|
5
|
+
This Cabloy Basic page is the canonical shared recipe for both editions. Detect the active edition before selecting commands, but keep the same two-file environment model for worktree-local development.
|
|
6
6
|
|
|
7
|
-
This workflow creates a standard isolated local runtime without changing committed environment defaults. It does not automatically isolate every external dependency.
|
|
7
|
+
This workflow creates a standard isolated local development runtime without changing committed environment defaults. It does not automatically isolate every external dependency.
|
|
8
8
|
|
|
9
9
|
## Before creating local overrides
|
|
10
10
|
|
|
@@ -82,13 +82,13 @@ Use commands from the active repository root.
|
|
|
82
82
|
| Cabloy Basic | `__CABLOY_BASIC__` | `npm run dev:zova:admin` or `npm run dev:zova:web` | `npm run test:e2e` |
|
|
83
83
|
| Cabloy Start | `__CABLOY_START__` | `npm run dev:zova:admin` or `npm run dev:zova:web` | `npm run test:e2e` |
|
|
84
84
|
|
|
85
|
-
Run one frontend command, not both, in each worktree.
|
|
85
|
+
Run one frontend command, not both, in each worktree. In Cabloy Basic, root `npm run test` and `npm run test:e2e` allocate a fresh run-specific identity, test database and Redis namespace, generated/runtime/public paths, and loopback listener independently of the worktree's development environment. Managed E2E starts a fresh Vona test-mode worker, and startup initializes test resources and module seeds without a separate dev-mode reset. This also isolates tests from a dev process in the same checkout. Cabloy Start's managed E2E uses the effective local test-mode Vona listener and its own ownership rules; inspect its root scripts before relying on Basic's isolation. Leave `E2E_BASE_URL` unset: externally managed targets are unsupported. Do not change shared identity or ports merely to bypass a busy development resource.
|
|
86
86
|
|
|
87
87
|
## What this isolates
|
|
88
88
|
|
|
89
|
-
A unique `APP_NAME` separates the
|
|
89
|
+
A unique worktree `APP_NAME` separates the identity of ordinary development resources across worktrees, including framework-managed development database names and Redis-related key prefixes. Worktree-local generated files, runtime files, build output, and coverage output are already separated by their worktree paths. Cabloy Basic root tests use a separate run-specific identity even when invoked inside a worktree; they do not clean its ordinary development business data.
|
|
90
90
|
|
|
91
|
-
The generated Vona, Zova development HTTP, and Zova HMR ports let worktrees run their ordinary local processes concurrently. The matching Zova API URL prevents the frontend in one worktree from calling the Vona process in another.
|
|
91
|
+
The generated Vona, Zova development HTTP, and Zova HMR ports let worktrees run their ordinary local processes concurrently. The matching Zova API URL prevents the frontend in one worktree from calling the Vona process in another. Builds, dependency generation, and other shared preparation writes remain accepted prerequisites rather than part of test data cleanup.
|
|
92
92
|
|
|
93
93
|
This is sufficient for the normal local workflows:
|
|
94
94
|
|
|
@@ -15,6 +15,25 @@ Zova standalone SSR: browser → Zova development server → frontend SSR →
|
|
|
15
15
|
|
|
16
16
|
In the Cabloy Basic default environment, `SERVER_LISTEN_PORT=7102` is the Vona entry and `DEV_SERVER_PORT=9000` is the Zova development entry. These are separate listeners, not two ports for the same server. Zova's `API_BASE_URL` points to Vona, not to its own development port. Local environment overrides can change the ports; use the effective values in your checkout.
|
|
17
17
|
|
|
18
|
+
## Runtime API origins in Vona integrated SSR
|
|
19
|
+
|
|
20
|
+
Vona integrated SSR supplies API origins at runtime; this mechanism is not specific to an edition or frontend flavor. By default, Vona derives the origin from its effective protocol and host and passes:
|
|
21
|
+
|
|
22
|
+
- `envServer.SSR_API_BASE_URL` to the built Zova server bundle during initialization.
|
|
23
|
+
- `envClient.API_BASE_URL` through the SSR state to the browser during client initialization.
|
|
24
|
+
|
|
25
|
+
These runtime values override Zova's build-time environment defaults used by the normal API client. They do not rewrite hard-coded URLs or arbitrary build-time substitutions in application code.
|
|
26
|
+
|
|
27
|
+
For an isolated `npm run test:e2e` that enters through Vona integrated SSR, the runner's dynamic Vona origin is therefore sufficient: **do not edit Zova `.env` files or rebuild the flavor solely to match the test port**. A new listener address alone does not make the bundle stale.
|
|
28
|
+
|
|
29
|
+
Artifact preparation is a separate concern. When frontend code, routes, metadata, or other build inputs change, refresh the required SSR/REST artifacts and synchronize Vona dependencies as required. Resolve commands and flavors from the active repository's scripts; do not assume every edition's E2E command builds the frontend automatically. See [SSR Build and Deploy Guide](/frontend/ssr-build-deploy-guide) and [Repo Scripts](/reference/repo-scripts).
|
|
30
|
+
|
|
31
|
+
The injected origins are defaults, with these boundaries:
|
|
32
|
+
|
|
33
|
+
- Vona merges the default origins first, then the `a-ssr` module's `site.default` configuration, then the individual SSR Site options. An explicit `envServer.SSR_API_BASE_URL` or `envClient.API_BASE_URL` in those site settings overrides the corresponding default; a value only in Zova's build-time `.env` does not count as a site override.
|
|
34
|
+
- Generated OpenAPI clients prefer their module-specific `OPENAPI_BASE_URL_*`, then `OPENAPI_BASE_URL_DEFAULT`, before the server or browser API-origin fallback. Custom API configuration and hard-coded URLs also require separate inspection when requests reach the wrong origin.
|
|
35
|
+
- Zova standalone SSR and SPA do not automatically receive this Vona integrated SSR handoff. Keep their environment setup separate from this rule, including deliberate [parallel worktree development configuration](/fullstack/parallel-worktree-environment).
|
|
36
|
+
|
|
18
37
|
## Start and use them in Cabloy Basic
|
|
19
38
|
|
|
20
39
|
Start the Vona server from the repository root and visit a Vona-served site:
|
|
@@ -41,6 +41,7 @@ Cabloy Basic exposes these shared root scripts:
|
|
|
41
41
|
- `npm run start:one`
|
|
42
42
|
- `npm run test`
|
|
43
43
|
- `npm run test:e2e`
|
|
44
|
+
- `npm run db:reset`
|
|
44
45
|
- `npm run tsc`
|
|
45
46
|
- `npm run docs:dev`
|
|
46
47
|
- `npm run docs:build`
|
|
@@ -48,6 +49,26 @@ Cabloy Basic exposes these shared root scripts:
|
|
|
48
49
|
|
|
49
50
|
`npm run init` prepares all Cabloy Basic SSR and REST artifacts with `npm run build:zova:all`, which sequentially builds the Basic and Commerce flavor batches before Vona initialization. Use `build:zova` or `build:zova:commerce` for focused artifact refreshes; use `build:zova:all` only when every shipped Basic flavor must be prepared.
|
|
50
51
|
|
|
52
|
+
## Test isolation and development data in Cabloy Basic
|
|
53
|
+
|
|
54
|
+
Root `npm run test` delegates to Vona's `npm run test`; both it and direct `cd vona && npm run test` use the same isolated runner. Vona's `npm run cov` also uses that runner and enables coverage. Root `npm run test:e2e` retains its own isolated E2E entrypoint. Each command launches a new test-mode run, even in the same checkout as a running development server. The runner chooses a UTC `YYYYMMDDHHmmss` timestamp plus eight lowercase cryptographically random hexadecimal characters for one run ID (for example, `20261014010203-a1b2c3d4`). This ID names both owned Vona directories (`.app-test-<id>` and `.vona-test-<id>`) and the disposable database and Redis namespaces; the runner also allocates a loopback listener. The runner exclusively creates an ignored JSON claim at `vona/.vona-test-claim/<id>.json` before allocating resources. A rare claim or directory collision fails without adopting or deleting the existing paths; rerun the command. Independent checkouts sharing database or Redis services do not share these claims, so their random suffixes reduce, but cannot eliminate, cross-checkout collisions.
|
|
55
|
+
|
|
56
|
+
Claims contain a versioned, nonsecret resource inventory: owned local roots, exact database allocation intents, Redis namespaces and endpoint identities, process ownership, and cleanup progress. Allocators must receive an acknowledgment that their intent is recorded before creating a database or using framework-managed Redis resources. Credentials, full environment/configuration snapshots, and readiness secrets are not stored in claims.
|
|
57
|
+
|
|
58
|
+
Successful unit, coverage, and managed application E2E runs release inventoried database and Redis resources and remove their owned local roots after process shutdown is verified. Managed E2E uses a registered browser fixture to verify detached browser-group shutdown; its run-owned reports, traces, and temporary profiles are deleted on success too. The claim is deleted last. Failed or interrupted runs retain their claim and resources for inspection. Cleanup failure also makes the command fail and retains the journal for retry.
|
|
59
|
+
|
|
60
|
+
Before each new invocation, the runner checks retained claims against their immutable UTC creation timestamp. Claims older than one day are eligible for cleanup; set `VONA_TEST_CLAIM_TTL_SECONDS` to a positive integer to change the default `86400` seconds. Eligibility is not permission to delete a live or unowned resource: the runner retains malformed claims, mismatched owner markers, symlinked paths, changed service endpoints, live or uncertain process identities, incomplete launch registrations, and claims with an existing cleanup lock. Inspect these warnings manually; a lock is never taken over merely because it is old. Cleanup resolves current trusted configuration without starting the application, running seeds, or opening a listener. It drops only recorded database names and scans only exact recorded Redis prefixes, never flushing Redis. Partial progress is journaled so a later eligible cleanup can retry safely. Legacy `.vona-test-claim-<id>` directories and inventory-less run roots are not automatically migrated or deleted.
|
|
61
|
+
|
|
62
|
+
All three commands initialize test databases and run module `seed()` hooks; none resets the ordinary dev-mode database or deletes its business data. A narrow test selection still initializes the test environment. Raw `:bin:test` invocations bypass the public scripts and do not get the runner's isolation guarantee.
|
|
63
|
+
|
|
64
|
+
Coverage reports (`vona/coverage/lcov.info` and, without `--ci`, `vona/coverage/report`) are shared checkout-level artifacts, not run-owned data. Avoid overlapping coverage runs or relying on these reports as independent per-run output.
|
|
65
|
+
|
|
66
|
+
Builds, generated artifacts, dependency installation/generation, and other shared preparation writes remain accepted prerequisites when needed. Test isolation does not make those writes private or authorize an unrelated reset of development data. The run-specific identity namespaces framework-managed resources; separately configured external databases, Redis targets or unprefixed custom keys, and third-party providers still require deliberate ownership and isolation. Inspect the active edition's scripts rather than assuming Cabloy Start already uses the same root runner.
|
|
67
|
+
|
|
68
|
+
For Vona integrated SSR, the allocated E2E origin is supplied to Zova at runtime as server `SSR_API_BASE_URL` and browser `API_BASE_URL`. Do not edit Zova `.env` files or rebuild solely to match the test port. The current root `npm run test:e2e` consumes prebuilt frontend artifacts; refresh affected SSR/REST output and synchronize dependencies when their inputs change. See [Runtime API origins in Vona integrated SSR](/fullstack/ssr-entry-modes#runtime-api-origins-in-vona-integrated-ssr) for configuration overrides and scope.
|
|
69
|
+
|
|
70
|
+
For a deliberate **dev-mode** database recreation, `npm run db:reset` is a separate, destructive command: it drops matching disposable development databases, reruns migrations and instance initialization, then runs module `seed()` hooks. It requires `database.testDatabase: true` in the dev configuration and a connection outside the disposable database. Ordinary `npm run dev` does not seed or reset; never run `db:reset` against development data you need to retain. Upgrades no longer initialize development test data automatically. See [Migration and Changes](/backend/migration-and-changes#local-development-workflow).
|
|
71
|
+
|
|
51
72
|
## Specification planning and derived charts
|
|
52
73
|
|
|
53
74
|
The current Cabloy Basic root scripts also expose:
|
|
@@ -151,7 +172,7 @@ The public-package upgrade flow does not source or reconcile the Start-owned bas
|
|
|
151
172
|
|
|
152
173
|
## SSR browser checks
|
|
153
174
|
|
|
154
|
-
Cabloy Basic and Cabloy Start each use a
|
|
175
|
+
Cabloy Basic and Cabloy Start each use a managed local `npm run test:e2e` command. In Basic, the root wrapper allocates a run-specific test identity, disposable database and Redis namespaces, Vona generated/runtime/public paths, and an available loopback port, then starts a fresh `--workers=1 --flavor=normal --mode=test` worker. Test-mode startup initializes test resources and invokes module seeds without a separate dev-mode `db:reset`; Playwright does not reuse an existing process. This protects ordinary same-checkout development data and permits a Basic root E2E run alongside a dev server, subject to the shared-preparation and external-resource boundaries above. Inspect the Start repository's current scripts for its own resource-ownership rules.
|
|
155
176
|
|
|
156
177
|
Both editions' browser checks target Vona integrated SSR. In the Cabloy Basic default environment, the Vona listener is `7102`; the Zova standalone SSR development server uses `9000` and is not an acceptance target.
|
|
157
178
|
|
|
@@ -4,26 +4,44 @@ import { E2E_LOCAL_BASE_URL, E2E_ROOT_DIR } from '../scripts/e2e.ts';
|
|
|
4
4
|
|
|
5
5
|
export default defineConfig({
|
|
6
6
|
testDir: `${E2E_ROOT_DIR}/repo-e2e/specs`,
|
|
7
|
+
outputDir: process.env.VONA_TEST_RUN_ID
|
|
8
|
+
? `${E2E_ROOT_DIR}/vona/.app-test-${process.env.VONA_TEST_RUN_ID}/test-results`
|
|
9
|
+
: `${E2E_ROOT_DIR}/repo-e2e/test-results`,
|
|
7
10
|
fullyParallel: false,
|
|
8
11
|
workers: 1,
|
|
9
12
|
forbidOnly: !!process.env.CI,
|
|
10
13
|
retries: process.env.CI ? 2 : 0,
|
|
11
|
-
reporter: process.env.CI
|
|
14
|
+
reporter: process.env.CI
|
|
15
|
+
? [
|
|
16
|
+
[
|
|
17
|
+
'html',
|
|
18
|
+
{
|
|
19
|
+
open: 'never',
|
|
20
|
+
outputFolder: process.env.VONA_TEST_RUN_ID
|
|
21
|
+
? `${E2E_ROOT_DIR}/vona/.app-test-${process.env.VONA_TEST_RUN_ID}/playwright-report`
|
|
22
|
+
: `${E2E_ROOT_DIR}/repo-e2e/playwright-report`,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
['list'],
|
|
26
|
+
]
|
|
27
|
+
: 'list',
|
|
12
28
|
use: {
|
|
13
29
|
baseURL: E2E_LOCAL_BASE_URL,
|
|
14
30
|
trace: 'on-first-retry',
|
|
15
31
|
},
|
|
16
|
-
webServer:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
webServer: process.env.VONA_TEST_RUN_ID
|
|
33
|
+
? undefined
|
|
34
|
+
: {
|
|
35
|
+
command: 'node repo-e2e/scripts/startE2eVona.ts',
|
|
36
|
+
cwd: E2E_ROOT_DIR,
|
|
37
|
+
url: `${E2E_LOCAL_BASE_URL}/health/ready`,
|
|
38
|
+
timeout: 180_000,
|
|
39
|
+
reuseExistingServer: false,
|
|
40
|
+
stdout: 'pipe',
|
|
41
|
+
stderr: 'pipe',
|
|
42
|
+
gracefulShutdown: {
|
|
43
|
+
signal: 'SIGINT',
|
|
44
|
+
timeout: 10_000,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
29
47
|
});
|
|
@@ -15,3 +15,42 @@ test('rejects a defined E2E_BASE_URL before loading local configuration', () =>
|
|
|
15
15
|
assert.doesNotMatch(result.stderr, /SERVER_LISTEN_PORT/);
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
+
|
|
19
|
+
test('isolated E2E target follows the assigned listener', () => {
|
|
20
|
+
const entrypoint = fileURLToPath(new URL('./e2e.ts', import.meta.url));
|
|
21
|
+
const result = spawnSync(
|
|
22
|
+
process.execPath,
|
|
23
|
+
[
|
|
24
|
+
'--input-type=module',
|
|
25
|
+
'-e',
|
|
26
|
+
`import { E2E_LOCAL_BASE_URL } from ${JSON.stringify(entrypoint)}; console.log(E2E_LOCAL_BASE_URL)`,
|
|
27
|
+
],
|
|
28
|
+
{
|
|
29
|
+
env: {
|
|
30
|
+
...process.env,
|
|
31
|
+
E2E_BASE_URL: undefined,
|
|
32
|
+
VONA_TEST_RUN_ID: '20261014010203-a1b2c3d4',
|
|
33
|
+
APP_NAME: 'cabtest20261014010203-a1b2c3d4',
|
|
34
|
+
SERVER_LISTEN_PORT: '42321',
|
|
35
|
+
},
|
|
36
|
+
encoding: 'utf8',
|
|
37
|
+
},
|
|
38
|
+
);
|
|
39
|
+
assert.equal(result.status, 0, result.stderr);
|
|
40
|
+
assert.equal(result.stdout.trim(), 'http://127.0.0.1:42321');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('rejects a malformed isolated E2E run ID', () => {
|
|
44
|
+
const entrypoint = fileURLToPath(new URL('./e2e.ts', import.meta.url));
|
|
45
|
+
const result = spawnSync(process.execPath, [entrypoint], {
|
|
46
|
+
env: {
|
|
47
|
+
...process.env,
|
|
48
|
+
E2E_BASE_URL: undefined,
|
|
49
|
+
VONA_TEST_RUN_ID: '20260230010203-a1b2c3d4',
|
|
50
|
+
SERVER_LISTEN_PORT: '42321',
|
|
51
|
+
},
|
|
52
|
+
encoding: 'utf8',
|
|
53
|
+
});
|
|
54
|
+
assert.notEqual(result.status, 0);
|
|
55
|
+
assert.match(result.stderr, /Invalid isolated test run ID/);
|
|
56
|
+
});
|
package/repo-e2e/scripts/e2e.ts
CHANGED
|
@@ -13,7 +13,25 @@ const vonaEnv = dotenv.loadEnvs(
|
|
|
13
13
|
resolve(E2E_ROOT_DIR, 'vona', 'env'),
|
|
14
14
|
'.env',
|
|
15
15
|
);
|
|
16
|
-
const
|
|
16
|
+
const runId = process.env.VONA_TEST_RUN_ID;
|
|
17
|
+
if (runId) {
|
|
18
|
+
const match = /^(\d{14})-[a-f0-9]{8}$/.exec(runId);
|
|
19
|
+
const timestamp = match?.[1];
|
|
20
|
+
const date = timestamp
|
|
21
|
+
? new Date(
|
|
22
|
+
`${timestamp.slice(0, 4)}-${timestamp.slice(4, 6)}-${timestamp.slice(6, 8)}T${timestamp.slice(8, 10)}:${timestamp.slice(10, 12)}:${timestamp.slice(12, 14)}Z`,
|
|
23
|
+
)
|
|
24
|
+
: undefined;
|
|
25
|
+
if (
|
|
26
|
+
!timestamp ||
|
|
27
|
+
!date ||
|
|
28
|
+
Number.isNaN(date.getTime()) ||
|
|
29
|
+
date.toISOString().slice(0, 19).replace(/[-:T]/g, '') !== timestamp
|
|
30
|
+
) {
|
|
31
|
+
throw new Error('Invalid isolated test run ID: expected a UTC timestamp plus eight hex digits');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const e2ePort = Number(runId ? process.env.SERVER_LISTEN_PORT : vonaEnv?.SERVER_LISTEN_PORT);
|
|
17
35
|
if (!Number.isInteger(e2ePort) || e2ePort <= 0 || e2ePort > 65535) {
|
|
18
36
|
throw new Error('Missing or invalid SERVER_LISTEN_PORT for local E2E target');
|
|
19
37
|
}
|