@elevasis/sdk 1.9.0 → 1.10.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/dist/cli.cjs +207 -49
- package/dist/test-utils/index.d.ts +8273 -0
- package/dist/test-utils/index.js +20070 -0
- package/dist/types/worker/index.d.ts +20 -1
- package/dist/worker/index.js +3 -2
- package/package.json +8 -2
- package/reference/_navigation.md +15 -1
- package/reference/_reference-manifest.json +56 -0
- package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +73 -0
- package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +1 -1
- package/reference/packages/core/src/test-utils/README.md +5 -10
- package/reference/packages/ui/src/test-utils/README.md +5 -0
- package/reference/scaffold/operations/workflow-recipes.md +94 -1
- package/reference/scaffold/recipes/add-a-feature.md +4 -4
- package/reference/scaffold/recipes/add-a-resource.md +1 -1
- package/reference/scaffold/recipes/customize-organization-model.md +2 -2
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +2 -2
|
@@ -26,8 +26,27 @@
|
|
|
26
26
|
* Worker -> Parent: { type: 'credential-request', id, name }
|
|
27
27
|
* Parent -> Worker: { type: 'credential-result', id, provider?, credentials?, error?, code? }
|
|
28
28
|
*/
|
|
29
|
-
import type { DeploymentSpec } from '../index.js';
|
|
29
|
+
import type { DeploymentSpec, WorkflowDefinition } from '../index.js';
|
|
30
30
|
export { platform, PlatformToolError } from './platform.js';
|
|
31
31
|
export type { PlatformCredential } from './platform.js';
|
|
32
32
|
export * from './adapters/index.js';
|
|
33
|
+
export interface LogEntry {
|
|
34
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
35
|
+
message: string;
|
|
36
|
+
timestamp: string;
|
|
37
|
+
context?: Record<string, unknown>;
|
|
38
|
+
}
|
|
39
|
+
export declare function executeWorkflow(workflow: WorkflowDefinition, input: unknown, context: {
|
|
40
|
+
executionId: string;
|
|
41
|
+
organizationId: string;
|
|
42
|
+
organizationName: string;
|
|
43
|
+
sessionId?: string;
|
|
44
|
+
sessionTurnNumber?: number;
|
|
45
|
+
parentExecutionId?: string;
|
|
46
|
+
executionDepth: number;
|
|
47
|
+
adapters?: Record<string, unknown>;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
output: unknown;
|
|
50
|
+
logs: LogEntry[];
|
|
51
|
+
}>;
|
|
33
52
|
export declare function startWorker(org: DeploymentSpec): void;
|
package/dist/worker/index.js
CHANGED
|
@@ -5083,7 +5083,7 @@ function captureConsole(executionId, logs) {
|
|
|
5083
5083
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
5084
5084
|
const entry = { level, message, timestamp, context: logContext };
|
|
5085
5085
|
logs.push(entry);
|
|
5086
|
-
parentPort
|
|
5086
|
+
parentPort?.postMessage({
|
|
5087
5087
|
type: "log",
|
|
5088
5088
|
entry: { level, message, timestamp, executionId, context: logContext }
|
|
5089
5089
|
});
|
|
@@ -5177,6 +5177,7 @@ async function executeWorkflow(workflow, input, context) {
|
|
|
5177
5177
|
sessionTurnNumber: context.sessionTurnNumber,
|
|
5178
5178
|
parentExecutionId: context.parentExecutionId,
|
|
5179
5179
|
executionDepth: context.executionDepth,
|
|
5180
|
+
adapters: context.adapters,
|
|
5180
5181
|
store: /* @__PURE__ */ new Map(),
|
|
5181
5182
|
logger: {
|
|
5182
5183
|
debug: (msg) => console.log(`[debug] ${msg}`),
|
|
@@ -5434,4 +5435,4 @@ function startWorker(org) {
|
|
|
5434
5435
|
});
|
|
5435
5436
|
}
|
|
5436
5437
|
|
|
5437
|
-
export { PlatformToolError, acqDb, approval, createAdapter, createAnymailfinderAdapter, createApifyAdapter, createAttioAdapter, createDropboxAdapter, createGmailAdapter, createGoogleSheetsAdapter, createInstantlyAdapter, createMillionVerifierAdapter, createResendAdapter, createSignatureApiAdapter, createStripeAdapter, createTombaAdapter, crm, email, execution, list, llm, notifications, pdf, platform, projects, scheduler, startWorker, storage };
|
|
5438
|
+
export { PlatformToolError, acqDb, approval, createAdapter, createAnymailfinderAdapter, createApifyAdapter, createAttioAdapter, createDropboxAdapter, createGmailAdapter, createGoogleSheetsAdapter, createInstantlyAdapter, createMillionVerifierAdapter, createResendAdapter, createSignatureApiAdapter, createStripeAdapter, createTombaAdapter, crm, email, executeWorkflow, execution, list, llm, notifications, pdf, platform, projects, scheduler, startWorker, storage };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elevasis/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "SDK for building Elevasis organization resources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./worker": {
|
|
15
15
|
"types": "./dist/types/worker/index.d.ts",
|
|
16
16
|
"import": "./dist/worker/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./test-utils": {
|
|
19
|
+
"types": "./dist/test-utils/index.d.ts",
|
|
20
|
+
"import": "./dist/test-utils/index.js"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"files": [
|
|
@@ -23,6 +27,8 @@
|
|
|
23
27
|
"dist/types/worker/index.d.ts",
|
|
24
28
|
"dist/types/worker/platform.d.ts",
|
|
25
29
|
"dist/types/worker/adapters/",
|
|
30
|
+
"dist/test-utils/index.js",
|
|
31
|
+
"dist/test-utils/index.d.ts",
|
|
26
32
|
"dist/cli.cjs",
|
|
27
33
|
"reference/"
|
|
28
34
|
],
|
|
@@ -44,7 +50,7 @@
|
|
|
44
50
|
"tsup": "^8.0.0",
|
|
45
51
|
"typescript": "5.9.2",
|
|
46
52
|
"zod": "^4.1.0",
|
|
47
|
-
"@repo/core": "0.
|
|
53
|
+
"@repo/core": "0.10.0",
|
|
48
54
|
"@repo/typescript-config": "0.0.0"
|
|
49
55
|
},
|
|
50
56
|
"scripts": {
|
package/reference/_navigation.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Auto-generated from the package reference manifests.
|
|
4
4
|
|
|
5
|
-
Package entries indexed:
|
|
5
|
+
Package entries indexed: 47.
|
|
6
6
|
|
|
7
7
|
## @elevasis/core / Core
|
|
8
8
|
|
|
@@ -40,6 +40,12 @@ Package entries indexed: 43.
|
|
|
40
40
|
| --- | --- | --- | --- |
|
|
41
41
|
| Worker Runtime | `runtime.mdx` | Worker runtime entrypoint, adapters, and platform execution surface. | (not specified) |
|
|
42
42
|
|
|
43
|
+
## @elevasis/sdk / Testing
|
|
44
|
+
|
|
45
|
+
| Resource | Location | Description | When to Load |
|
|
46
|
+
| --- | --- | --- | --- |
|
|
47
|
+
| Test Utils | `runtime.mdx` | Workflow runner, registry assertion, and typed adapter mocks for SDK consumers. | (not specified) |
|
|
48
|
+
|
|
43
49
|
## @elevasis/ui / Components
|
|
44
50
|
|
|
45
51
|
| Resource | Location | Description | When to Load |
|
|
@@ -100,6 +106,14 @@ Package entries indexed: 43.
|
|
|
100
106
|
| Provider UI | `packages/ui/src/provider/README.md` | Published provider UI entry for downstream applications. | (not specified) |
|
|
101
107
|
| Elevasis Service Context | `packages/ui/src/provider/README.md` | Standalone service context and provider that supplies apiRequest, organizationId, and isReady to child components. | (not specified) |
|
|
102
108
|
|
|
109
|
+
## @elevasis/ui / Testing
|
|
110
|
+
|
|
111
|
+
| Resource | Location | Description | When to Load |
|
|
112
|
+
| --- | --- | --- | --- |
|
|
113
|
+
| Test Utils | `packages/ui/src/test-utils/README.md` | Published rendering helpers, auth mocks, MSW handlers, and test provider utilities. | (not specified) |
|
|
114
|
+
| Test Utils Setup | `packages/ui/src/test-utils/README.md` | Vitest setup file for UI consumers using browser mocks and MSW. | (not specified) |
|
|
115
|
+
| Test Utils Integration Setup | `packages/ui/src/test-utils/README.md` | Vitest setup file for integration tests that avoid MSW and use real network boundaries. | (not specified) |
|
|
116
|
+
|
|
103
117
|
## @elevasis/ui / Visual
|
|
104
118
|
|
|
105
119
|
| Resource | Location | Description | When to Load |
|
|
@@ -85,6 +85,20 @@
|
|
|
85
85
|
"referencePath": "runtime.mdx",
|
|
86
86
|
"publishedExportPath": "./dist/worker/index.js"
|
|
87
87
|
},
|
|
88
|
+
{
|
|
89
|
+
"packageName": "@elevasis/sdk",
|
|
90
|
+
"packageDir": "packages/sdk",
|
|
91
|
+
"subpath": "./test-utils",
|
|
92
|
+
"kind": "subpath",
|
|
93
|
+
"title": "Test Utils",
|
|
94
|
+
"description": "Workflow runner, registry assertion, and typed adapter mocks for SDK consumers.",
|
|
95
|
+
"group": "Testing",
|
|
96
|
+
"order": 1,
|
|
97
|
+
"sourcePath": "packages/sdk/src/test-utils/index.ts",
|
|
98
|
+
"docPath": "apps/docs/content/docs/sdk/runtime.mdx",
|
|
99
|
+
"referencePath": "runtime.mdx",
|
|
100
|
+
"publishedExportPath": "./dist/test-utils/index.js"
|
|
101
|
+
},
|
|
88
102
|
{
|
|
89
103
|
"packageName": "@elevasis/ui",
|
|
90
104
|
"packageDir": "packages/ui",
|
|
@@ -575,6 +589,48 @@
|
|
|
575
589
|
"referencePath": "packages/ui/src/provider/README.md",
|
|
576
590
|
"publishedExportPath": "./dist/provider/ElevasisServiceContext.js"
|
|
577
591
|
},
|
|
592
|
+
{
|
|
593
|
+
"packageName": "@elevasis/ui",
|
|
594
|
+
"packageDir": "packages/ui",
|
|
595
|
+
"subpath": "./test-utils",
|
|
596
|
+
"kind": "subpath",
|
|
597
|
+
"title": "Test Utils",
|
|
598
|
+
"description": "Published rendering helpers, auth mocks, MSW handlers, and test provider utilities.",
|
|
599
|
+
"group": "Testing",
|
|
600
|
+
"order": 1,
|
|
601
|
+
"sourcePath": "packages/ui/src/test-utils/index.ts",
|
|
602
|
+
"docPath": "packages/ui/src/test-utils/README.md",
|
|
603
|
+
"referencePath": "packages/ui/src/test-utils/README.md",
|
|
604
|
+
"publishedExportPath": "./dist/test-utils/index.js"
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
"packageName": "@elevasis/ui",
|
|
608
|
+
"packageDir": "packages/ui",
|
|
609
|
+
"subpath": "./test-utils/setup",
|
|
610
|
+
"kind": "subpath",
|
|
611
|
+
"title": "Test Utils Setup",
|
|
612
|
+
"description": "Vitest setup file for UI consumers using browser mocks and MSW.",
|
|
613
|
+
"group": "Testing",
|
|
614
|
+
"order": 2,
|
|
615
|
+
"sourcePath": "packages/ui/src/test-utils/setup.ts",
|
|
616
|
+
"docPath": "packages/ui/src/test-utils/README.md",
|
|
617
|
+
"referencePath": "packages/ui/src/test-utils/README.md",
|
|
618
|
+
"publishedExportPath": "./dist/test-utils/setup.js"
|
|
619
|
+
},
|
|
620
|
+
{
|
|
621
|
+
"packageName": "@elevasis/ui",
|
|
622
|
+
"packageDir": "packages/ui",
|
|
623
|
+
"subpath": "./test-utils/setup-integration",
|
|
624
|
+
"kind": "subpath",
|
|
625
|
+
"title": "Test Utils Integration Setup",
|
|
626
|
+
"description": "Vitest setup file for integration tests that avoid MSW and use real network boundaries.",
|
|
627
|
+
"group": "Testing",
|
|
628
|
+
"order": 3,
|
|
629
|
+
"sourcePath": "packages/ui/src/test-utils/setup-integration.ts",
|
|
630
|
+
"docPath": "packages/ui/src/test-utils/README.md",
|
|
631
|
+
"referencePath": "packages/ui/src/test-utils/README.md",
|
|
632
|
+
"publishedExportPath": "./dist/test-utils/setup-integration.js"
|
|
633
|
+
},
|
|
578
634
|
{
|
|
579
635
|
"packageName": "@elevasis/ui",
|
|
580
636
|
"packageDir": "packages/ui",
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Test Utils And Template Tests
|
|
2
|
+
|
|
3
|
+
## Why this note exists
|
|
4
|
+
|
|
5
|
+
This update adds meaningful package, template, and downstream test coverage while keeping ownership boundaries clear. Package-owned contracts live in package tests/test-utils; `_template` keeps scaffold smoke tests and examples; downstream projects keep custom tests for project-specific workflows and routes.
|
|
6
|
+
|
|
7
|
+
The new package-level test-utils subpaths are being prepared in the monorepo packages:
|
|
8
|
+
|
|
9
|
+
- `@elevasis/core/test-utils`
|
|
10
|
+
- `@elevasis/ui/test-utils`
|
|
11
|
+
- `@elevasis/sdk/test-utils`
|
|
12
|
+
|
|
13
|
+
Until the bundled release train publishes those expanded package surfaces, `_template` keeps small local compatibility wrappers for tests that need the new helpers. Do not replace those wrappers with local `file:` dependencies.
|
|
14
|
+
|
|
15
|
+
## Applies to
|
|
16
|
+
|
|
17
|
+
All template-derived projects that sync from `external/_template`.
|
|
18
|
+
|
|
19
|
+
Known affected projects: `nirvana-marketing`, `ZentaraHQ`.
|
|
20
|
+
|
|
21
|
+
## Required actions
|
|
22
|
+
|
|
23
|
+
### Step 1 -- Pull template changes via `/git-sync`
|
|
24
|
+
|
|
25
|
+
Accept the new tests under sync-managed scaffold surfaces:
|
|
26
|
+
|
|
27
|
+
- `ui/src/routes/__tests__/`
|
|
28
|
+
- `core/types/**`
|
|
29
|
+
- `core/config/**`
|
|
30
|
+
- local core compatibility helpers under `core/test-utils/`
|
|
31
|
+
|
|
32
|
+
Operations tests are intentionally narrower. Treat `operations/src/**` as project-owned runtime code. Only keep or add Operations tests in a downstream project when the project owns the workflow/module being tested. The template's email-notification tests are examples, not a requirement for every derived project.
|
|
33
|
+
|
|
34
|
+
### Step 2 -- Run the expanded test chain
|
|
35
|
+
|
|
36
|
+
From project root:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm test
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The root test script now runs `operations check` between UI and operations tests so resource-registry drift fails during ordinary test runs.
|
|
43
|
+
|
|
44
|
+
### Step 3 -- Keep compatibility wrappers until the bundled release lands
|
|
45
|
+
|
|
46
|
+
Do not delete any local compatibility wrapper that is still used by a project-owned custom test until the project has upgraded to package versions that publish the expanded test-utils subpaths.
|
|
47
|
+
|
|
48
|
+
After the release train lands, projects can migrate local compatibility imports to:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { renderWithProviders } from '@elevasis/ui/test-utils'
|
|
52
|
+
import { makeProject } from '@elevasis/core/test-utils'
|
|
53
|
+
import { runWorkflow } from '@elevasis/sdk/test-utils'
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 4 -- Adjust only for intentionally removed features
|
|
57
|
+
|
|
58
|
+
If a derived project intentionally removed a feature route or workflow, skip or adjust the specific synced test case. For Operations, prefer project-owned tests that import package helpers over copied template workflow tests.
|
|
59
|
+
|
|
60
|
+
## Verification
|
|
61
|
+
|
|
62
|
+
- `pnpm -C ui test` passes.
|
|
63
|
+
- `pnpm -C operations check` passes.
|
|
64
|
+
- `pnpm -C operations test` passes.
|
|
65
|
+
- `pnpm -C core test` passes.
|
|
66
|
+
- `pnpm test` passes from project root.
|
|
67
|
+
|
|
68
|
+
## Not handled by /git-sync
|
|
69
|
+
|
|
70
|
+
- `/git-sync` does not publish or upgrade `@elevasis/*` package versions.
|
|
71
|
+
- `/git-sync` does not remove compatibility wrappers after the release train.
|
|
72
|
+
- `/git-sync` does not decide how a project-specific removed feature should be represented in tests.
|
|
73
|
+
- `/git-sync` does not force template-only Operations example tests into downstream projects that do not own the matching workflow files.
|
|
@@ -32,7 +32,7 @@ Run from project root:
|
|
|
32
32
|
pnpm up @elevasis/ui @elevasis/core @elevasis/sdk --latest
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
-
Dep bumps are already written into `_template/ui/package.json` and `_template/
|
|
35
|
+
Dep bumps are already written into `_template/ui/package.json`, `_template/operations/package.json`, and `_template/core/package.json` by the release train (`@elevasis/core` ^0.9.0, `@elevasis/ui` ^2.19.0, `@elevasis/sdk` ^1.9.0).
|
|
36
36
|
|
|
37
37
|
### Step 3 -- Replace inlined type defs with package imports
|
|
38
38
|
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Published test helpers for downstream consumers of `@elevasis/core`.
|
|
4
4
|
|
|
5
|
-
The public `@elevasis/core/test-utils` subpath
|
|
5
|
+
The public `@elevasis/core/test-utils` subpath exposes:
|
|
6
6
|
|
|
7
7
|
- `RLSTestContext` for dev-database RLS integration tests
|
|
8
8
|
- `setupMatchMedia`, `setupResizeObserver`, and `setupBrowserMocks` for jsdom/browser test setup
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
- `TEST_USERS`, `TEST_ORGS`, `TEST_MEMBERSHIPS`, and related fixture factories
|
|
10
|
+
- `createMockSupabaseClient`, `createMockWorkOSClient`, and related mocks
|
|
11
|
+
- base entity factories such as `makeProject`, `makeDeal`, and `makeTask`
|
|
12
|
+
- organization model/profile builders such as `makeOrganizationModel`, `makeInitializationState`, and `makeUserProfile`
|
|
11
13
|
|
|
12
14
|
## Published Usage
|
|
13
15
|
|
|
@@ -33,10 +35,3 @@ const ctx = new RLSTestContext()
|
|
|
33
35
|
- `SUPABASE_ANON_KEY`
|
|
34
36
|
- `SUPABASE_SERVICE_KEY`
|
|
35
37
|
- `SUPABASE_JWT_SECRET`
|
|
36
|
-
|
|
37
|
-
## Internal Scope
|
|
38
|
-
|
|
39
|
-
The following folders remain implementation detail for the monorepo and are not published:
|
|
40
|
-
|
|
41
|
-
- `fixtures/`
|
|
42
|
-
- `mocks/`
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# UI Test Utilities
|
|
2
|
+
|
|
3
|
+
Published test helpers for consumers that test Elevasis UI composition.
|
|
4
|
+
|
|
5
|
+
Use `@elevasis/ui/test-utils` for provider-aware React rendering, WorkOS auth mocks, MSW handlers, and test query clients. Use `@elevasis/ui/test-utils/setup` or `@elevasis/ui/test-utils/setup-integration` from Vitest `setupFiles` when a consumer wants the shared browser and auth mocks.
|
|
@@ -433,4 +433,97 @@ export const agents: never[] = []
|
|
|
433
433
|
3. Import the group barrel in `operations/src/index.ts` and spread into `workflows`/`agents`.
|
|
434
434
|
4. Run `pnpm -C operations check` to validate, then `pnpm -C operations deploy` to publish.
|
|
435
435
|
|
|
436
|
-
**Note:** Use `.js` extensions in imports even though the source is TypeScript. The TypeScript compiler and esbuild bundler both require this for ESM interoperability.
|
|
436
|
+
**Note:** Use `.js` extensions in imports even though the source is TypeScript. The TypeScript compiler and esbuild bundler both require this for ESM interoperability.
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## 5. Testing Custom Workflows And UI
|
|
441
|
+
|
|
442
|
+
Package-owned test helpers are the stable way to test custom downstream code. Do not copy template-only tests into a project unless the project owns the matching workflow, route, or component.
|
|
443
|
+
|
|
444
|
+
After the bundled package release lands, use these public subpaths:
|
|
445
|
+
|
|
446
|
+
```typescript
|
|
447
|
+
import { makeProject } from '@elevasis/core/test-utils'
|
|
448
|
+
import { renderWithProviders, mockAuthenticatedUser } from '@elevasis/ui/test-utils'
|
|
449
|
+
import { assertResourceRegistry, mockNotifications, runWorkflow } from '@elevasis/sdk/test-utils'
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### Workflow Smoke Test
|
|
453
|
+
|
|
454
|
+
Use `runWorkflow` for project-owned workflows. This tests the workflow contract, step execution, and parsed output without deploying.
|
|
455
|
+
|
|
456
|
+
```typescript
|
|
457
|
+
import { describe, expect, it } from 'vitest'
|
|
458
|
+
import { runWorkflow, mockNotifications } from '@elevasis/sdk/test-utils'
|
|
459
|
+
import { emailNotification } from './index'
|
|
460
|
+
import type { EmailNotificationOutput } from '@foundation/types'
|
|
461
|
+
|
|
462
|
+
describe('emailNotification workflow', () => {
|
|
463
|
+
it('runs the notify step with a mocked notification adapter', async () => {
|
|
464
|
+
const notifications = mockNotifications({
|
|
465
|
+
create: { id: 'notification-1' }
|
|
466
|
+
})
|
|
467
|
+
|
|
468
|
+
const result = await runWorkflow<EmailNotificationOutput>(
|
|
469
|
+
emailNotification,
|
|
470
|
+
{
|
|
471
|
+
recipientEmail: 'jane@example.com',
|
|
472
|
+
recipientName: 'Jane',
|
|
473
|
+
subject: 'Action ready',
|
|
474
|
+
body: 'Your request has been processed.'
|
|
475
|
+
},
|
|
476
|
+
{ adapters: { notification: notifications } }
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
expect(result.output.delivered).toBe(true)
|
|
480
|
+
expect(result.stepEvents.map((event) => event.stepId)).toContain('notify')
|
|
481
|
+
})
|
|
482
|
+
})
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Registry Smoke Test
|
|
486
|
+
|
|
487
|
+
Use `assertResourceRegistry` for a project-owned `operations/src/index.ts` manifest. Keep assertions generic unless the project intentionally owns a fixed workflow list.
|
|
488
|
+
|
|
489
|
+
```typescript
|
|
490
|
+
import { describe, expect, it } from 'vitest'
|
|
491
|
+
import { assertResourceRegistry } from '@elevasis/sdk/test-utils'
|
|
492
|
+
import org from './index'
|
|
493
|
+
|
|
494
|
+
describe('operations registry', () => {
|
|
495
|
+
it('registers a valid operations manifest', () => {
|
|
496
|
+
const spec = assertResourceRegistry(org, { organizationName: 'Example Project' })
|
|
497
|
+
const workflows = spec.workflows ?? []
|
|
498
|
+
|
|
499
|
+
expect(workflows.length + (spec.agents?.length ?? 0)).toBeGreaterThan(0)
|
|
500
|
+
expect(new Set(workflows.map((workflow) => workflow.config.resourceId)).size).toBe(workflows.length)
|
|
501
|
+
})
|
|
502
|
+
})
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### UI And Core Fixtures
|
|
506
|
+
|
|
507
|
+
Use `@elevasis/ui/test-utils` for route/component tests and `@elevasis/core/test-utils` for schema-compatible fixtures.
|
|
508
|
+
|
|
509
|
+
```tsx
|
|
510
|
+
import { describe, expect, it } from 'vitest'
|
|
511
|
+
import { screen } from '@testing-library/react'
|
|
512
|
+
import { makeProject } from '@elevasis/core/test-utils'
|
|
513
|
+
import { mockAuthenticatedUser, renderWithProviders } from '@elevasis/ui/test-utils'
|
|
514
|
+
import { ProjectCard } from './ProjectCard'
|
|
515
|
+
|
|
516
|
+
describe('ProjectCard', () => {
|
|
517
|
+
it('renders a project fixture for an authenticated user', () => {
|
|
518
|
+
const project = makeProject({ name: 'Website Refresh' })
|
|
519
|
+
|
|
520
|
+
renderWithProviders(<ProjectCard project={project} />, {
|
|
521
|
+
auth: mockAuthenticatedUser()
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
expect(screen.getByText('Website Refresh')).toBeInTheDocument()
|
|
525
|
+
})
|
|
526
|
+
})
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
Template tests are examples and smoke coverage. Downstream projects should keep custom tests close to the feature they validate, then consume these package helpers instead of copying scaffold internals.
|
|
@@ -16,7 +16,7 @@ See [glossary.md](../reference/glossary.md) for term disambiguation throughout t
|
|
|
16
16
|
A shell feature requires a `feature.id` in the org model's `features[]` array to gate it. You have two options:
|
|
17
17
|
|
|
18
18
|
- **Reuse an existing feature** (e.g., `operations`, `monitoring`). The new shell module shares the on/off toggle with the existing feature entry. Fine for sub-modules within the same product area.
|
|
19
|
-
- **Add a new feature object** -- add an entry to the `features[]` array in `
|
|
19
|
+
- **Add a new feature object** -- add an entry to the `features[]` array in `core/config/organization-model.ts`. This is always a template-local change; no core package change is required.
|
|
20
20
|
|
|
21
21
|
For a genuinely new capability (e.g., `analytics`), you add a feature object to the defaults array and author a matching manifest.
|
|
22
22
|
|
|
@@ -26,7 +26,7 @@ See [glossary.md](../reference/glossary.md) under **Feature** (three contexts).
|
|
|
26
26
|
|
|
27
27
|
## 2. Update the organization model
|
|
28
28
|
|
|
29
|
-
File: `
|
|
29
|
+
File: `core/config/organization-model.ts`
|
|
30
30
|
|
|
31
31
|
Add a new feature object to the `features[]` array passed to `defineOrganizationModel`.
|
|
32
32
|
|
|
@@ -63,7 +63,7 @@ Each field of the feature object:
|
|
|
63
63
|
|
|
64
64
|
No domain entry or separate key resolver is needed. The `features[]` array is the sole source of truth.
|
|
65
65
|
|
|
66
|
-
**Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `
|
|
66
|
+
**Two-step pattern:** in a template-derived project, the `defineOrganizationModel` output is passed to `createFoundationOrganizationModel(override)` in `core/config/organization-model.ts`. The result exposes `.model`, `.canonical`, and `.homeLabel`. See `external/_template/core/config/organization-model.ts` for the canonical two-step example.
|
|
67
67
|
|
|
68
68
|
---
|
|
69
69
|
|
|
@@ -154,5 +154,5 @@ pnpm -C ui dev
|
|
|
154
154
|
|
|
155
155
|
- Feature appears in the nav sidebar.
|
|
156
156
|
- Route is accessible and the subshell sidebar renders.
|
|
157
|
-
- Toggle `features.enabled.analytics` to `false` in `
|
|
157
|
+
- Toggle `features.enabled.analytics` to `false` in `core/config/organization-model.ts` and confirm the nav item disappears and the route redirects.
|
|
158
158
|
- Check `FeatureGuard` by navigating directly to `/analytics` with the feature disabled.
|
|
@@ -115,7 +115,7 @@ Full relationship and checkpoint types are defined in `@elevasis/sdk` (`Deployme
|
|
|
115
115
|
|
|
116
116
|
## 4. (Optional) Map to a domain
|
|
117
117
|
|
|
118
|
-
To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `
|
|
118
|
+
To make the resource referenceable from the org model (so the Operations graph and Command View can link to it), add an entry to `resourceMappings` in `core/config/organization-model.ts`:
|
|
119
119
|
|
|
120
120
|
```ts
|
|
121
121
|
resourceMappings: [
|
|
@@ -5,7 +5,7 @@ description: Annotated walkthrough for customizing the organization model in tem
|
|
|
5
5
|
|
|
6
6
|
# Customize organization-model.ts
|
|
7
7
|
|
|
8
|
-
`
|
|
8
|
+
`core/config/organization-model.ts` is the semantic contract between your UI runtime
|
|
9
9
|
and your platform operations. Every feature your users can access, every nav surface they can
|
|
10
10
|
navigate to, and every resource backed by a workflow is declared here. The provider reads this
|
|
11
11
|
contract at startup; everything downstream -- routing, gating, nav rendering -- derives from it.
|
|
@@ -366,7 +366,7 @@ Both sides must be consistent (schema validates bidirectionality):
|
|
|
366
366
|
|
|
367
367
|
The organization model flows through the runtime in one direction:
|
|
368
368
|
|
|
369
|
-
1. `
|
|
369
|
+
1. `core/config/organization-model.ts` calls `resolveOrganizationModel` at module load.
|
|
370
370
|
The resolved `canonicalOrganizationModel` is exported.
|
|
371
371
|
2. `ui/src/routes/__root.tsx` imports `canonicalOrganizationModel` and passes it to
|
|
372
372
|
`ElevasisFeaturesProvider` along with the `FEATURE_MANIFESTS` array.
|
|
@@ -27,7 +27,7 @@ Do not substitute one for the other. `FeatureGuard` reads feature flags; `AdminG
|
|
|
27
27
|
|
|
28
28
|
## 2. Feature gate -- org level
|
|
29
29
|
|
|
30
|
-
Ensure a feature object with the matching `id` exists in the org model. File: `
|
|
30
|
+
Ensure a feature object with the matching `id` exists in the org model. File: `core/config/organization-model.ts`.
|
|
31
31
|
|
|
32
32
|
```ts
|
|
33
33
|
import { defineOrganizationModel, OPERATIONS_FEATURE_ID, SALES_FEATURE_ID } from '@elevasis/core/organization-model'
|
|
@@ -155,4 +155,4 @@ State matrix -- confirm each combination:
|
|
|
155
155
|
| true | (absent) | non-admin | Admin-gated route redirects, admin nav hidden |
|
|
156
156
|
| true | (absent) | admin | Admin-gated route accessible, nav visible |
|
|
157
157
|
|
|
158
|
-
Check each gate independently: feature toggle in `
|
|
158
|
+
Check each gate independently: feature toggle in `core/config/organization-model.ts`, membership config in `org_memberships.config`, and admin status in the user profile.
|