@ontrails/testing 1.0.0-beta.11 → 1.0.0-beta.12
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/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/context.d.ts +30 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +14 -1
- package/dist/context.js.map +1 -1
- package/dist/examples.d.ts.map +1 -1
- package/dist/examples.js +28 -8
- package/dist/examples.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/__tests__/examples.test.ts +94 -0
- package/src/context.ts +45 -1
- package/src/examples.ts +39 -9
- package/src/index.ts +10 -2
package/.turbo/turbo-lint.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @ontrails/testing
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Complete trifecta for config, permits, and crumbs (formerly tracks)
|
|
8
|
+
|
|
9
|
+
- **config**: Add `configService`, `config.layer`, `config.trail`, and `config.workspace` trails with full `defineConfig`, `resolve`, `describe`, `explain`, `doctor`, and code generation support
|
|
10
|
+
- **permits**: Add `authService` and `auth.verify` trail for runtime authorization checks
|
|
11
|
+
- **crumbs**: Rename tracks to crumbs; add `crumbsService` and `crumbs.status` trail for structured event tracking
|
|
12
|
+
- **cli**: Fix build flag handling and improve bootstrap scaffolding
|
|
13
|
+
- **testing**: Expand test context helpers and example-based testing utilities
|
|
14
|
+
- **core/mcp/http**: Internal alignment for service and composition updates
|
|
15
|
+
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
- @ontrails/core@1.0.0-beta.12
|
|
18
|
+
- @ontrails/cli@1.0.0-beta.12
|
|
19
|
+
- @ontrails/mcp@1.0.0-beta.12
|
|
20
|
+
- @ontrails/logging@1.0.0-beta.12
|
|
21
|
+
|
|
3
22
|
## 1.0.0-beta.11
|
|
4
23
|
|
|
5
24
|
### Minor Changes
|
package/dist/context.d.ts
CHANGED
|
@@ -15,9 +15,34 @@ export declare const createTestContext: (overrides?: TestTrailContextOptions) =>
|
|
|
15
15
|
export interface CreateFollowContextOptions {
|
|
16
16
|
readonly responses?: Record<string, Result<unknown, Error>> | undefined;
|
|
17
17
|
}
|
|
18
|
+
/** Minimal permit shape returned by the mint function. */
|
|
19
|
+
export interface MintedPermit {
|
|
20
|
+
readonly id: string;
|
|
21
|
+
readonly scopes: readonly string[];
|
|
22
|
+
}
|
|
23
|
+
/** Trail shape consumed by the mint function — avoids importing permits. */
|
|
24
|
+
export interface MintableTrail {
|
|
25
|
+
readonly permit?: {
|
|
26
|
+
readonly scopes: readonly string[];
|
|
27
|
+
} | 'public' | undefined;
|
|
28
|
+
}
|
|
18
29
|
export interface TestExecutionOptions {
|
|
19
30
|
readonly ctx?: Partial<TrailContext> | undefined;
|
|
20
31
|
readonly services?: ServiceOverrideMap | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* When true, disables automatic permit minting. Tests must provide
|
|
34
|
+
* explicit permits.
|
|
35
|
+
*/
|
|
36
|
+
readonly strictPermits?: boolean | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Optional function to mint a test permit for a trail. When provided,
|
|
39
|
+
* called for each trail with a non-public `permit` requirement.
|
|
40
|
+
* Returning `undefined` skips minting for that trail.
|
|
41
|
+
*
|
|
42
|
+
* A default inline implementation is used when this is not provided,
|
|
43
|
+
* keeping the testing package free of a hard dependency on `@ontrails/permits`.
|
|
44
|
+
*/
|
|
45
|
+
readonly mintPermit?: (trail: MintableTrail) => MintedPermit | undefined;
|
|
21
46
|
}
|
|
22
47
|
/**
|
|
23
48
|
* Create a mock `FollowFn` for testing composite trails.
|
|
@@ -34,6 +59,11 @@ export interface TestExecutionOptions {
|
|
|
34
59
|
* ```
|
|
35
60
|
*/
|
|
36
61
|
export declare const createFollowContext: (options?: CreateFollowContextOptions) => FollowFn;
|
|
62
|
+
/**
|
|
63
|
+
* Default permit minter — reads `trail.permit.scopes` and produces a
|
|
64
|
+
* minimal permit object. No dependency on `@ontrails/permits`.
|
|
65
|
+
*/
|
|
66
|
+
export declare const defaultMintPermit: (trail: MintableTrail) => MintedPermit | undefined;
|
|
37
67
|
export declare const normalizeTestExecutionOptions: (input?: Partial<TrailContext> | TestExecutionOptions) => TestExecutionOptions;
|
|
38
68
|
export declare const mergeServiceOverrides: (autoResolved: ServiceOverrideMap, ctx: Partial<TrailContext> | undefined, explicit: ServiceOverrideMap | undefined) => ServiceOverrideMap;
|
|
39
69
|
export declare const resolveMockServices: (app: Topo) => Promise<ServiceOverrideMap>;
|
package/dist/context.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,kBAAkB,EAClB,IAAI,EACJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAuB,MAAM,gBAAgB,CAAC;AAG7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAaF,CAAC;AAMF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,QAAQ,EACR,kBAAkB,EAClB,IAAI,EACJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAuB,MAAM,gBAAgB,CAAC;AAG7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAaF,CAAC;AAMF,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED,0DAA0D;AAC1D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EACZ;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GACtC,QAAQ,GACR,SAAS,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7C;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,YAAY,GAAG,SAAS,CAAC;CAC1E;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,0BAA0B,KACnC,QAcF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,aAAa,KACnB,YAAY,GAAG,SAKjB,CAAC;AAWF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,KACnD,oBACqD,CAAC;AAEzD,eAAO,MAAM,qBAAqB,GAChC,cAAc,kBAAkB,EAChC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,EACtC,UAAU,kBAAkB,GAAG,SAAS,KACvC,kBAID,CAAC;AAaH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,IAAI,KACR,OAAO,CAAC,kBAAkB,CAAiC,CAAC;AAE/D;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,OAAO,CAAC,YAAY,CAAC,EAC3B,WAAW,kBAAkB,KAC5B,YAcF,CAAC"}
|
package/dist/context.js
CHANGED
|
@@ -51,8 +51,21 @@ export const createFollowContext = (options) => {
|
|
|
51
51
|
return Promise.resolve(response);
|
|
52
52
|
};
|
|
53
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Default permit minter — reads `trail.permit.scopes` and produces a
|
|
56
|
+
* minimal permit object. No dependency on `@ontrails/permits`.
|
|
57
|
+
*/
|
|
58
|
+
export const defaultMintPermit = (trail) => {
|
|
59
|
+
if (!trail.permit || trail.permit === 'public') {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
return { id: 'test-permit', scopes: trail.permit.scopes };
|
|
63
|
+
};
|
|
54
64
|
const isTestExecutionOptions = (input) => input !== undefined &&
|
|
55
|
-
(Object.hasOwn(input, 'ctx') ||
|
|
65
|
+
(Object.hasOwn(input, 'ctx') ||
|
|
66
|
+
Object.hasOwn(input, 'services') ||
|
|
67
|
+
Object.hasOwn(input, 'strictPermits') ||
|
|
68
|
+
Object.hasOwn(input, 'mintPermit'));
|
|
56
69
|
export const normalizeTestExecutionOptions = (input) => isTestExecutionOptions(input) ? input : { ctx: input };
|
|
57
70
|
export const mergeServiceOverrides = (autoResolved, ctx, explicit) => ({
|
|
58
71
|
...autoResolved,
|
package/dist/context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAO/C,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAmC,EACrB,EAAE;IAChB,MAAM,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAC5C,MAAM,GAAG,GAAG;QACV,GAAG;QACH,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE;QAC7C,UAAU,EAAE,SAAS;QACrB,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,gBAAgB,EAAE;QAC/C,SAAS,EAAE,SAAS,EAAE,SAAS,IAAI,kBAAkB;QACrD,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,MAAM;QACzD,aAAa,EAAE,GAAG;KACI,CAAC;IACzB,GAAG,CAAC,OAAO,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC;IAC7C,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/examples.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAGV,IAAI,EAGJ,YAAY,EACb,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAGV,IAAI,EAGJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AAmCxB,OAAO,KAAK,EAAiB,oBAAoB,EAAE,MAAM,cAAc,CAAC;AA6MxE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,IAAI,EACT,eACI,OAAO,CAAC,YAAY,CAAC,GACrB,oBAAoB,GACpB,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,CAAC,KACvD,IA0EF,CAAC"}
|
package/dist/examples.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { describe, expect, test } from 'bun:test';
|
|
10
10
|
import { AlreadyExistsError, AmbiguousError, AssertionError, AuthError, CancelledError, ConflictError, InternalError, NetworkError, NotFoundError, PermissionError, RateLimitError, executeTrail, Result, TimeoutError, TrailsError, ValidationError, validateInput, } from '@ontrails/core';
|
|
11
11
|
import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
|
|
12
|
-
import { mergeServiceOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockServices, } from './context.js';
|
|
12
|
+
import { defaultMintPermit, mergeServiceOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockServices, } from './context.js';
|
|
13
13
|
// ---------------------------------------------------------------------------
|
|
14
14
|
// Error class name -> constructor map
|
|
15
15
|
// ---------------------------------------------------------------------------
|
|
@@ -65,17 +65,36 @@ const handleValidationError = (validated, example) => {
|
|
|
65
65
|
}
|
|
66
66
|
throw new Error(`Example "${example.name}" has invalid input: ${validated.error.message}`);
|
|
67
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* Apply auto-minting: if the trail declares scoped permits and the context
|
|
70
|
+
* doesn't already have a permit, mint one and merge it into the context.
|
|
71
|
+
*/
|
|
72
|
+
const applyAutoMint = (ctx, trailDef, opts) => {
|
|
73
|
+
if (opts.strictPermits) {
|
|
74
|
+
return ctx;
|
|
75
|
+
}
|
|
76
|
+
if (ctx.permit !== undefined) {
|
|
77
|
+
return ctx;
|
|
78
|
+
}
|
|
79
|
+
const mint = opts.mintPermit ?? defaultMintPermit;
|
|
80
|
+
const permit = mint(trailDef);
|
|
81
|
+
if (!permit) {
|
|
82
|
+
return ctx;
|
|
83
|
+
}
|
|
84
|
+
return { ...ctx, permit };
|
|
85
|
+
};
|
|
68
86
|
/**
|
|
69
87
|
* Run a single example against a trail.
|
|
70
88
|
* Handles validation, execution, and assertions.
|
|
71
89
|
*/
|
|
72
|
-
const runExample = async (t, example, output, testCtx, services) => {
|
|
90
|
+
const runExample = async (t, example, output, testCtx, services, opts) => {
|
|
73
91
|
const validated = validateInput(t.input, example.input);
|
|
74
92
|
if (handleValidationError(validated, example)) {
|
|
75
93
|
return;
|
|
76
94
|
}
|
|
95
|
+
const ctx = opts ? applyAutoMint(testCtx, t, opts) : testCtx;
|
|
77
96
|
const result = await executeTrail(t, example.input, {
|
|
78
|
-
ctx
|
|
97
|
+
ctx,
|
|
79
98
|
services,
|
|
80
99
|
});
|
|
81
100
|
assertProgressiveMatch(result, example, output);
|
|
@@ -110,13 +129,14 @@ const createCoverageFollow = (called, baseFollow, topo, ctx, services) => {
|
|
|
110
129
|
/**
|
|
111
130
|
* Run a single example against a composition trail, recording follow calls.
|
|
112
131
|
*/
|
|
113
|
-
const runCompositionExample = async (trailDef, example, output, baseCtx, called, topo, services) => {
|
|
132
|
+
const runCompositionExample = async (trailDef, example, output, baseCtx, called, topo, services, opts) => {
|
|
114
133
|
const validated = validateInput(trailDef.input, example.input);
|
|
115
134
|
if (handleValidationError(validated, example)) {
|
|
116
135
|
return;
|
|
117
136
|
}
|
|
118
|
-
const
|
|
119
|
-
const
|
|
137
|
+
const mintedCtx = opts ? applyAutoMint(baseCtx, trailDef, opts) : baseCtx;
|
|
138
|
+
const follow = createCoverageFollow(called, mintedCtx.follow, topo, mintedCtx, services);
|
|
139
|
+
const testCtx = { ...mintedCtx, follow };
|
|
120
140
|
const result = await executeTrail(trailDef, example.input, {
|
|
121
141
|
ctx: testCtx,
|
|
122
142
|
services,
|
|
@@ -154,7 +174,7 @@ export const testExamples = (app, ctxOrFactory) => {
|
|
|
154
174
|
const resolved = normalizeTestExecutionOptions(resolveInput());
|
|
155
175
|
const services = mergeServiceOverrides(await resolveMockServices(app), resolved.ctx, resolved.services);
|
|
156
176
|
const testCtx = mergeTestContext(resolved.ctx);
|
|
157
|
-
await runExample(t, example, output, testCtx, services);
|
|
177
|
+
await runExample(t, example, output, testCtx, services, resolved);
|
|
158
178
|
});
|
|
159
179
|
});
|
|
160
180
|
}
|
|
@@ -170,7 +190,7 @@ export const testExamples = (app, ctxOrFactory) => {
|
|
|
170
190
|
const resolved = normalizeTestExecutionOptions(resolveInput());
|
|
171
191
|
const services = mergeServiceOverrides(await resolveMockServices(app), resolved.ctx, resolved.services);
|
|
172
192
|
const baseCtx = mergeTestContext(resolved.ctx);
|
|
173
|
-
await runCompositionExample(t, example, output, baseCtx, called, app, services);
|
|
193
|
+
await runCompositionExample(t, example, output, baseCtx, called, app, services, resolved);
|
|
174
194
|
});
|
|
175
195
|
test('follow coverage', () => {
|
|
176
196
|
const uncovered = t.follow.filter((id) => !called.has(id));
|
package/dist/examples.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAWlD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,SAAS,EACT,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,YAAY,EACZ,MAAM,EACN,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAClB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,6BAA6B,EAC7B,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,8EAA8E;AAC9E,sCAAsC;AACtC,8EAA8E;AAE9E,MAAM,SAAS,GAAoD;IACjE,kBAAkB,EAAE,kBAAqD;IACzE,cAAc,EAAE,cAAiD;IACjE,cAAc,EAAE,cAAiD;IACjE,SAAS,EAAE,SAA4C;IACvD,cAAc,EAAE,cAAiD;IACjE,aAAa,EAAE,aAAgD;IAC/D,aAAa,EAAE,aAAgD;IAC/D,YAAY,EAAE,YAA+C;IAC7D,aAAa,EAAE,aAAgD;IAC/D,eAAe,EAAE,eAAkD;IACnE,cAAc,EAAE,cAAiD;IACjE,YAAY,EAAE,YAA+C;IAC7D,WAAW,EAAE,WAAyD;IACtE,eAAe,EAAE,eAAkD;CACpE,CAAC;AAEF;;;GAGG;AACH,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAqC,EAAE,CAC5E,SAAS,CAAC,IAAI,CAAC,IAAK,KAAyC,CAAC;AAEhE,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,sBAAsB,GAAG,CAC7B,MAA8B,EAC9B,OAAuC,EACvC,MAA6B,EACvB,EAAE;IACR,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpD,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACrC,OAAO;IACT,CAAC;IAED,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,qBAAqB,GAAG,CAC5B,SAAiC,EACjC,OAAuC,EAC9B,EAAE;IACX,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,KAAK,CACb,YAAY,OAAO,CAAC,IAAI,wBAAwB,SAAS,CAAC,KAAK,CAAC,OAAO,EAAE,CAC1E,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,GAAG,KAAK,EACtB,CAA0B,EAC1B,OAAuC,EACvC,MAA6B,EAC7B,OAAqB,EACrB,QAA6B,
|
|
1
|
+
{"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,12 +5,12 @@ export { testTrail } from './trail.js';
|
|
|
5
5
|
export { testContracts } from './contracts.js';
|
|
6
6
|
export { testDetours } from './detours.js';
|
|
7
7
|
export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
|
|
8
|
-
export { createFollowContext, createTestContext } from './context.js';
|
|
8
|
+
export { createFollowContext, createTestContext, defaultMintPermit, } from './context.js';
|
|
9
9
|
export { createTestLogger } from './logger.js';
|
|
10
10
|
export { createCliHarness } from './harness-cli.js';
|
|
11
11
|
export { createMcpHarness } from './harness-mcp.js';
|
|
12
12
|
export type { CreateFollowContextOptions } from './context.js';
|
|
13
|
-
export type { TestExecutionOptions } from './context.js';
|
|
13
|
+
export type { MintableTrail, MintedPermit, TestExecutionOptions, } from './context.js';
|
|
14
14
|
export type { TestFollowOptions } from './follows.js';
|
|
15
15
|
export type { FollowScenario, TestScenario, TestLogger, TestTrailContextOptions, CliHarness, CliHarnessOptions, CliHarnessResult, McpHarness, McpHarnessOptions, McpHarnessResult, } from './types.js';
|
|
16
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAGpD,YAAY,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC/D,YAAY,EACV,aAAa,EACb,YAAY,EACZ,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEtD,YAAY,EACV,cAAc,EACd,YAAY,EACZ,UAAU,EACV,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ export { testDetours } from './detours.js';
|
|
|
8
8
|
// Assertions
|
|
9
9
|
export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
|
|
10
10
|
// Mock factories
|
|
11
|
-
export { createFollowContext, createTestContext } from './context.js';
|
|
11
|
+
export { createFollowContext, createTestContext, defaultMintPermit, } from './context.js';
|
|
12
12
|
export { createTestLogger } from './logger.js';
|
|
13
13
|
// Surface harnesses
|
|
14
14
|
export { createCliHarness } from './harness-cli.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,aAAa;AACb,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,iBAAiB;AACjB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,aAAa;AACb,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,SAAS,EACT,QAAQ,GACT,MAAM,iBAAiB,CAAC;AAEzB,iBAAiB;AACjB,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,oBAAoB;AACpB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/testing",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./src/index.ts",
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
15
15
|
},
|
|
16
16
|
"peerDependencies": {
|
|
17
|
-
"@ontrails/cli": "^1.0.0-beta.
|
|
18
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
19
|
-
"@ontrails/logging": "^1.0.0-beta.
|
|
20
|
-
"@ontrails/mcp": "^1.0.0-beta.
|
|
17
|
+
"@ontrails/cli": "^1.0.0-beta.12",
|
|
18
|
+
"@ontrails/core": "^1.0.0-beta.12",
|
|
19
|
+
"@ontrails/logging": "^1.0.0-beta.12",
|
|
20
|
+
"@ontrails/mcp": "^1.0.0-beta.12",
|
|
21
21
|
"zod": "^4.3.5"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -437,3 +437,97 @@ describe('testExamples nested follow chain (A → B → C)', () => {
|
|
|
437
437
|
} as Record<string, unknown>)
|
|
438
438
|
);
|
|
439
439
|
});
|
|
440
|
+
|
|
441
|
+
// ---------------------------------------------------------------------------
|
|
442
|
+
// Auto-minting permit tests (B3)
|
|
443
|
+
// ---------------------------------------------------------------------------
|
|
444
|
+
|
|
445
|
+
const scopedTrail = trail('scoped.trail', {
|
|
446
|
+
description: 'Trail requiring admin scope',
|
|
447
|
+
examples: [
|
|
448
|
+
{
|
|
449
|
+
expected: { ok: true },
|
|
450
|
+
input: {},
|
|
451
|
+
name: 'Runs with auto-minted permit',
|
|
452
|
+
},
|
|
453
|
+
],
|
|
454
|
+
input: z.object({}),
|
|
455
|
+
output: z.object({ ok: z.boolean() }),
|
|
456
|
+
permit: { scopes: ['admin'] },
|
|
457
|
+
run: (_input, ctx) => {
|
|
458
|
+
// Verify the permit was auto-minted with declared scopes
|
|
459
|
+
const permit = ctx.permit as
|
|
460
|
+
| { id: string; scopes: readonly string[] }
|
|
461
|
+
| undefined;
|
|
462
|
+
if (!permit || !permit.scopes.includes('admin')) {
|
|
463
|
+
return Result.err(new Error('Missing permit or scopes'));
|
|
464
|
+
}
|
|
465
|
+
return Result.ok({ ok: true });
|
|
466
|
+
},
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
const publicTrail = trail('public.trail', {
|
|
470
|
+
description: 'Public trail — no permit needed',
|
|
471
|
+
examples: [
|
|
472
|
+
{
|
|
473
|
+
expected: { ok: true },
|
|
474
|
+
input: {},
|
|
475
|
+
name: 'Runs without a permit',
|
|
476
|
+
},
|
|
477
|
+
],
|
|
478
|
+
input: z.object({}),
|
|
479
|
+
output: z.object({ ok: z.boolean() }),
|
|
480
|
+
permit: 'public',
|
|
481
|
+
run: (_input, ctx) => {
|
|
482
|
+
// Public trail should NOT get a permit
|
|
483
|
+
if (ctx.permit !== undefined) {
|
|
484
|
+
return Result.err(new Error('Unexpected permit on public trail'));
|
|
485
|
+
}
|
|
486
|
+
return Result.ok({ ok: true });
|
|
487
|
+
},
|
|
488
|
+
});
|
|
489
|
+
|
|
490
|
+
describe('testExamples auto-minting permits', () => {
|
|
491
|
+
describe('scoped trail gets auto-minted permit', () => {
|
|
492
|
+
// eslint-disable-next-line jest/require-hook
|
|
493
|
+
testExamples(
|
|
494
|
+
topo('mint-scoped-app', {
|
|
495
|
+
scopedTrail,
|
|
496
|
+
} as Record<string, unknown>)
|
|
497
|
+
);
|
|
498
|
+
});
|
|
499
|
+
|
|
500
|
+
describe('public trail does NOT get a permit', () => {
|
|
501
|
+
// eslint-disable-next-line jest/require-hook
|
|
502
|
+
testExamples(
|
|
503
|
+
topo('mint-public-app', {
|
|
504
|
+
publicTrail,
|
|
505
|
+
} as Record<string, unknown>)
|
|
506
|
+
);
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
describe('strictPermits skips auto-minting', () => {
|
|
510
|
+
const strictScopedTrail = trail('strict.scoped', {
|
|
511
|
+
description: 'Trail that expects no permit under strictPermits',
|
|
512
|
+
examples: [
|
|
513
|
+
{
|
|
514
|
+
expected: { hasPermit: false },
|
|
515
|
+
input: {},
|
|
516
|
+
name: 'No auto-minted permit when strictPermits is true',
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
input: z.object({}),
|
|
520
|
+
output: z.object({ hasPermit: z.boolean() }),
|
|
521
|
+
permit: { scopes: ['admin'] },
|
|
522
|
+
run: (_input, ctx) => Result.ok({ hasPermit: ctx.permit !== undefined }),
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// eslint-disable-next-line jest/require-hook
|
|
526
|
+
testExamples(
|
|
527
|
+
topo('strict-app', {
|
|
528
|
+
strictScopedTrail,
|
|
529
|
+
} as Record<string, unknown>),
|
|
530
|
+
{ strictPermits: true }
|
|
531
|
+
);
|
|
532
|
+
});
|
|
533
|
+
});
|
package/src/context.ts
CHANGED
|
@@ -53,9 +53,37 @@ export interface CreateFollowContextOptions {
|
|
|
53
53
|
readonly responses?: Record<string, Result<unknown, Error>> | undefined;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/** Minimal permit shape returned by the mint function. */
|
|
57
|
+
export interface MintedPermit {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly scopes: readonly string[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Trail shape consumed by the mint function — avoids importing permits. */
|
|
63
|
+
export interface MintableTrail {
|
|
64
|
+
readonly permit?:
|
|
65
|
+
| { readonly scopes: readonly string[] }
|
|
66
|
+
| 'public'
|
|
67
|
+
| undefined;
|
|
68
|
+
}
|
|
69
|
+
|
|
56
70
|
export interface TestExecutionOptions {
|
|
57
71
|
readonly ctx?: Partial<TrailContext> | undefined;
|
|
58
72
|
readonly services?: ServiceOverrideMap | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* When true, disables automatic permit minting. Tests must provide
|
|
75
|
+
* explicit permits.
|
|
76
|
+
*/
|
|
77
|
+
readonly strictPermits?: boolean | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Optional function to mint a test permit for a trail. When provided,
|
|
80
|
+
* called for each trail with a non-public `permit` requirement.
|
|
81
|
+
* Returning `undefined` skips minting for that trail.
|
|
82
|
+
*
|
|
83
|
+
* A default inline implementation is used when this is not provided,
|
|
84
|
+
* keeping the testing package free of a hard dependency on `@ontrails/permits`.
|
|
85
|
+
*/
|
|
86
|
+
readonly mintPermit?: (trail: MintableTrail) => MintedPermit | undefined;
|
|
59
87
|
}
|
|
60
88
|
|
|
61
89
|
/**
|
|
@@ -90,11 +118,27 @@ export const createFollowContext = (
|
|
|
90
118
|
};
|
|
91
119
|
};
|
|
92
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Default permit minter — reads `trail.permit.scopes` and produces a
|
|
123
|
+
* minimal permit object. No dependency on `@ontrails/permits`.
|
|
124
|
+
*/
|
|
125
|
+
export const defaultMintPermit = (
|
|
126
|
+
trail: MintableTrail
|
|
127
|
+
): MintedPermit | undefined => {
|
|
128
|
+
if (!trail.permit || trail.permit === 'public') {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
return { id: 'test-permit', scopes: trail.permit.scopes };
|
|
132
|
+
};
|
|
133
|
+
|
|
93
134
|
const isTestExecutionOptions = (
|
|
94
135
|
input: Partial<TrailContext> | TestExecutionOptions | undefined
|
|
95
136
|
): input is TestExecutionOptions =>
|
|
96
137
|
input !== undefined &&
|
|
97
|
-
(Object.hasOwn(input, 'ctx') ||
|
|
138
|
+
(Object.hasOwn(input, 'ctx') ||
|
|
139
|
+
Object.hasOwn(input, 'services') ||
|
|
140
|
+
Object.hasOwn(input, 'strictPermits') ||
|
|
141
|
+
Object.hasOwn(input, 'mintPermit'));
|
|
98
142
|
|
|
99
143
|
export const normalizeTestExecutionOptions = (
|
|
100
144
|
input?: Partial<TrailContext> | TestExecutionOptions
|
package/src/examples.ts
CHANGED
|
@@ -45,12 +45,13 @@ import {
|
|
|
45
45
|
assertSchemaMatch,
|
|
46
46
|
} from './assertions.js';
|
|
47
47
|
import {
|
|
48
|
+
defaultMintPermit,
|
|
48
49
|
mergeServiceOverrides,
|
|
49
50
|
mergeTestContext,
|
|
50
51
|
normalizeTestExecutionOptions,
|
|
51
52
|
resolveMockServices,
|
|
52
53
|
} from './context.js';
|
|
53
|
-
import type { TestExecutionOptions } from './context.js';
|
|
54
|
+
import type { MintableTrail, TestExecutionOptions } from './context.js';
|
|
54
55
|
|
|
55
56
|
// ---------------------------------------------------------------------------
|
|
56
57
|
// Error class name -> constructor map
|
|
@@ -127,6 +128,29 @@ const handleValidationError = (
|
|
|
127
128
|
);
|
|
128
129
|
};
|
|
129
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Apply auto-minting: if the trail declares scoped permits and the context
|
|
133
|
+
* doesn't already have a permit, mint one and merge it into the context.
|
|
134
|
+
*/
|
|
135
|
+
const applyAutoMint = (
|
|
136
|
+
ctx: TrailContext,
|
|
137
|
+
trailDef: MintableTrail,
|
|
138
|
+
opts: TestExecutionOptions
|
|
139
|
+
): TrailContext => {
|
|
140
|
+
if (opts.strictPermits) {
|
|
141
|
+
return ctx;
|
|
142
|
+
}
|
|
143
|
+
if (ctx.permit !== undefined) {
|
|
144
|
+
return ctx;
|
|
145
|
+
}
|
|
146
|
+
const mint = opts.mintPermit ?? defaultMintPermit;
|
|
147
|
+
const permit = mint(trailDef);
|
|
148
|
+
if (!permit) {
|
|
149
|
+
return ctx;
|
|
150
|
+
}
|
|
151
|
+
return { ...ctx, permit };
|
|
152
|
+
};
|
|
153
|
+
|
|
130
154
|
/**
|
|
131
155
|
* Run a single example against a trail.
|
|
132
156
|
* Handles validation, execution, and assertions.
|
|
@@ -136,7 +160,8 @@ const runExample = async (
|
|
|
136
160
|
example: TrailExample<unknown, unknown>,
|
|
137
161
|
output: z.ZodType | undefined,
|
|
138
162
|
testCtx: TrailContext,
|
|
139
|
-
services?: ServiceOverrideMap
|
|
163
|
+
services?: ServiceOverrideMap,
|
|
164
|
+
opts?: TestExecutionOptions
|
|
140
165
|
): Promise<void> => {
|
|
141
166
|
const validated = validateInput(t.input, example.input);
|
|
142
167
|
|
|
@@ -144,8 +169,10 @@ const runExample = async (
|
|
|
144
169
|
return;
|
|
145
170
|
}
|
|
146
171
|
|
|
172
|
+
const ctx = opts ? applyAutoMint(testCtx, t, opts) : testCtx;
|
|
173
|
+
|
|
147
174
|
const result = await executeTrail(t, example.input, {
|
|
148
|
-
ctx
|
|
175
|
+
ctx,
|
|
149
176
|
services,
|
|
150
177
|
});
|
|
151
178
|
assertProgressiveMatch(result, example, output);
|
|
@@ -199,7 +226,8 @@ const runCompositionExample = async (
|
|
|
199
226
|
baseCtx: TrailContext,
|
|
200
227
|
called: Set<string>,
|
|
201
228
|
topo: Topo,
|
|
202
|
-
services?: ServiceOverrideMap
|
|
229
|
+
services?: ServiceOverrideMap,
|
|
230
|
+
opts?: TestExecutionOptions
|
|
203
231
|
): Promise<void> => {
|
|
204
232
|
const validated = validateInput(trailDef.input, example.input);
|
|
205
233
|
|
|
@@ -207,14 +235,15 @@ const runCompositionExample = async (
|
|
|
207
235
|
return;
|
|
208
236
|
}
|
|
209
237
|
|
|
238
|
+
const mintedCtx = opts ? applyAutoMint(baseCtx, trailDef, opts) : baseCtx;
|
|
210
239
|
const follow = createCoverageFollow(
|
|
211
240
|
called,
|
|
212
|
-
|
|
241
|
+
mintedCtx.follow,
|
|
213
242
|
topo,
|
|
214
|
-
|
|
243
|
+
mintedCtx,
|
|
215
244
|
services
|
|
216
245
|
);
|
|
217
|
-
const testCtx: TrailContext = { ...
|
|
246
|
+
const testCtx: TrailContext = { ...mintedCtx, follow };
|
|
218
247
|
|
|
219
248
|
const result = await executeTrail(trailDef, example.input, {
|
|
220
249
|
ctx: testCtx,
|
|
@@ -273,7 +302,7 @@ export const testExamples = (
|
|
|
273
302
|
resolved.services
|
|
274
303
|
);
|
|
275
304
|
const testCtx = mergeTestContext(resolved.ctx);
|
|
276
|
-
await runExample(t, example, output, testCtx, services);
|
|
305
|
+
await runExample(t, example, output, testCtx, services, resolved);
|
|
277
306
|
}
|
|
278
307
|
);
|
|
279
308
|
});
|
|
@@ -306,7 +335,8 @@ export const testExamples = (
|
|
|
306
335
|
baseCtx,
|
|
307
336
|
called,
|
|
308
337
|
app,
|
|
309
|
-
services
|
|
338
|
+
services,
|
|
339
|
+
resolved
|
|
310
340
|
);
|
|
311
341
|
}
|
|
312
342
|
);
|
package/src/index.ts
CHANGED
|
@@ -16,7 +16,11 @@ export {
|
|
|
16
16
|
} from './assertions.js';
|
|
17
17
|
|
|
18
18
|
// Mock factories
|
|
19
|
-
export {
|
|
19
|
+
export {
|
|
20
|
+
createFollowContext,
|
|
21
|
+
createTestContext,
|
|
22
|
+
defaultMintPermit,
|
|
23
|
+
} from './context.js';
|
|
20
24
|
export { createTestLogger } from './logger.js';
|
|
21
25
|
|
|
22
26
|
// Surface harnesses
|
|
@@ -25,7 +29,11 @@ export { createMcpHarness } from './harness-mcp.js';
|
|
|
25
29
|
|
|
26
30
|
// Types
|
|
27
31
|
export type { CreateFollowContextOptions } from './context.js';
|
|
28
|
-
export type {
|
|
32
|
+
export type {
|
|
33
|
+
MintableTrail,
|
|
34
|
+
MintedPermit,
|
|
35
|
+
TestExecutionOptions,
|
|
36
|
+
} from './context.js';
|
|
29
37
|
export type { TestFollowOptions } from './follows.js';
|
|
30
38
|
|
|
31
39
|
export type {
|