@ontrails/testing 1.0.0-beta.14 → 1.0.0-beta.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +12 -12
  3. package/package.json +15 -6
  4. package/src/all.ts +153 -16
  5. package/src/assertions.ts +253 -0
  6. package/src/context.ts +67 -38
  7. package/src/contracts.ts +15 -24
  8. package/src/crosses.ts +93 -51
  9. package/src/detours.ts +155 -18
  10. package/src/effective-examples.ts +350 -0
  11. package/src/examples.ts +139 -63
  12. package/src/harness-cli.ts +19 -11
  13. package/src/harness-mcp.ts +9 -8
  14. package/src/index.ts +14 -4
  15. package/src/logger.ts +3 -1
  16. package/src/scenario.ts +368 -0
  17. package/src/signals.ts +221 -0
  18. package/src/types.ts +64 -6
  19. package/.turbo/turbo-build.log +0 -1
  20. package/.turbo/turbo-lint.log +0 -3
  21. package/.turbo/turbo-typecheck.log +0 -1
  22. package/dist/all.d.ts +0 -31
  23. package/dist/all.d.ts.map +0 -1
  24. package/dist/all.js +0 -47
  25. package/dist/all.js.map +0 -1
  26. package/dist/assertions.d.ts +0 -49
  27. package/dist/assertions.d.ts.map +0 -1
  28. package/dist/assertions.js +0 -84
  29. package/dist/assertions.js.map +0 -1
  30. package/dist/context.d.ts +0 -75
  31. package/dist/context.d.ts.map +0 -1
  32. package/dist/context.js +0 -107
  33. package/dist/context.js.map +0 -1
  34. package/dist/contracts.d.ts +0 -17
  35. package/dist/contracts.d.ts.map +0 -1
  36. package/dist/contracts.js +0 -71
  37. package/dist/contracts.js.map +0 -1
  38. package/dist/crosses.d.ts +0 -38
  39. package/dist/crosses.d.ts.map +0 -1
  40. package/dist/crosses.js +0 -213
  41. package/dist/crosses.js.map +0 -1
  42. package/dist/detours.d.ts +0 -12
  43. package/dist/detours.d.ts.map +0 -1
  44. package/dist/detours.js +0 -30
  45. package/dist/detours.js.map +0 -1
  46. package/dist/examples.d.ts +0 -23
  47. package/dist/examples.d.ts.map +0 -1
  48. package/dist/examples.js +0 -202
  49. package/dist/examples.js.map +0 -1
  50. package/dist/follows.d.ts +0 -38
  51. package/dist/follows.d.ts.map +0 -1
  52. package/dist/follows.js +0 -212
  53. package/dist/follows.js.map +0 -1
  54. package/dist/harness-cli.d.ts +0 -21
  55. package/dist/harness-cli.d.ts.map +0 -1
  56. package/dist/harness-cli.js +0 -200
  57. package/dist/harness-cli.js.map +0 -1
  58. package/dist/harness-mcp.d.ts +0 -21
  59. package/dist/harness-mcp.d.ts.map +0 -1
  60. package/dist/harness-mcp.js +0 -53
  61. package/dist/harness-mcp.js.map +0 -1
  62. package/dist/index.d.ts +0 -16
  63. package/dist/index.d.ts.map +0 -1
  64. package/dist/index.js +0 -16
  65. package/dist/index.js.map +0 -1
  66. package/dist/logger.d.ts +0 -15
  67. package/dist/logger.d.ts.map +0 -1
  68. package/dist/logger.js +0 -87
  69. package/dist/logger.js.map +0 -1
  70. package/dist/trail.d.ts +0 -20
  71. package/dist/trail.d.ts.map +0 -1
  72. package/dist/trail.js +0 -80
  73. package/dist/trail.js.map +0 -1
  74. package/dist/types.d.ts +0 -80
  75. package/dist/types.d.ts.map +0 -1
  76. package/dist/types.js +0 -5
  77. package/dist/types.js.map +0 -1
  78. package/src/__tests__/all.test.ts +0 -135
  79. package/src/__tests__/context.test.ts +0 -150
  80. package/src/__tests__/contracts.test.ts +0 -185
  81. package/src/__tests__/crosses.test.ts +0 -587
  82. package/src/__tests__/detours.test.ts +0 -55
  83. package/src/__tests__/examples.test.ts +0 -534
  84. package/src/__tests__/harness-cli.test.ts +0 -66
  85. package/src/__tests__/logger.test.ts +0 -136
  86. package/src/__tests__/trail.test.ts +0 -99
  87. package/tsconfig.json +0 -9
  88. package/tsconfig.tsbuildinfo +0 -1
package/dist/crosses.js DELETED
@@ -1,213 +0,0 @@
1
- /**
2
- * testCrosses — crossing-aware scenario testing for trails with crossings.
3
- *
4
- * Tests the crossing graph: which trails were crossed, in what order,
5
- * and supports failure injection from crossed trail examples.
6
- */
7
- import { describe, expect, test } from 'bun:test';
8
- import { executeTrail, InternalError, Result, ValidationError, validateInput, } from '@ontrails/core';
9
- import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
10
- import { mergeProvisionOverrides, mergeTestContext } from './context.js';
11
- const collectDeclaredProvisions = (trailDef, trailsMap) => {
12
- const seenProvisionIds = new Set();
13
- const seenTrailIds = new Set();
14
- const provisions = [];
15
- const collect = (candidate) => {
16
- for (const declaredProvision of candidate.provisions) {
17
- if (seenProvisionIds.has(declaredProvision.id)) {
18
- continue;
19
- }
20
- seenProvisionIds.add(declaredProvision.id);
21
- provisions.push(declaredProvision);
22
- }
23
- };
24
- const visit = (candidate) => {
25
- if (seenTrailIds.has(candidate.id)) {
26
- return;
27
- }
28
- seenTrailIds.add(candidate.id);
29
- collect(candidate);
30
- for (const crossedId of candidate.crosses) {
31
- const crossedTrail = trailsMap?.get(crossedId);
32
- if (crossedTrail) {
33
- visit(crossedTrail);
34
- }
35
- }
36
- };
37
- visit(trailDef);
38
- return provisions;
39
- };
40
- const resolveCrossMockProvisions = async (trailDef, trailsMap) => {
41
- const provisions = {};
42
- for (const declaredProvision of collectDeclaredProvisions(trailDef, trailsMap)) {
43
- if (!declaredProvision.mock) {
44
- continue;
45
- }
46
- provisions[declaredProvision.id] = await declaredProvision.mock();
47
- }
48
- return provisions;
49
- };
50
- // ---------------------------------------------------------------------------
51
- // Injection helpers
52
- // ---------------------------------------------------------------------------
53
- /**
54
- * Find an error example on a trail by name or description substring.
55
- */
56
- const findErrorExample = (trailDef, description) => {
57
- const example = trailDef.examples?.find((ex) => ex.error !== undefined &&
58
- (ex.description?.includes(description) || ex.name.includes(description)));
59
- return example?.error;
60
- };
61
- /**
62
- * Try to inject an error from a crossed trail's example.
63
- * Returns undefined when no injection is configured for this trail ID.
64
- */
65
- const tryInjectError = (id, scenario, trailsMap) => {
66
- const injection = scenario.injectFromExample?.[id];
67
- if (injection === undefined) {
68
- return undefined;
69
- }
70
- const trailDef = trailsMap?.get(id);
71
- if (trailDef === undefined) {
72
- return Result.err(new InternalError(`Cannot inject: trail "${id}" not in topo`));
73
- }
74
- const errorName = findErrorExample(trailDef, injection);
75
- if (errorName === undefined) {
76
- return Result.err(new InternalError(`No error example matching "${injection}" on trail "${id}"`));
77
- }
78
- return Result.err(new Error(errorName));
79
- };
80
- /**
81
- * Execute a trail from the map, validating input first.
82
- */
83
- const executeFromMap = (id, input, trailsMap, ctx, provisions, cross) => {
84
- const trailDef = trailsMap?.get(id);
85
- if (trailDef === undefined) {
86
- return undefined;
87
- }
88
- const nestedCtx = cross ? { ...ctx, cross } : ctx;
89
- return executeTrail(trailDef, input, {
90
- ctx: nestedCtx,
91
- provisions,
92
- });
93
- };
94
- // ---------------------------------------------------------------------------
95
- // Cross factory
96
- // ---------------------------------------------------------------------------
97
- /**
98
- * Build a recording cross function that optionally injects errors.
99
- */
100
- const createRecordingCross = (trace, scenario, trailsMap, baseCross, ctx, provisions) => {
101
- // The generic O on CrossFn is erased at runtime; the cast is safe
102
- // because callers narrow via isOk/isErr before accessing the value.
103
- const cross = (id, input) => {
104
- trace.push({ id, input });
105
- const injected = tryInjectError(id, scenario, trailsMap);
106
- if (injected !== undefined) {
107
- return Promise.resolve(injected);
108
- }
109
- if (baseCross !== undefined) {
110
- return baseCross(id, input);
111
- }
112
- const executed = executeFromMap(id, input, trailsMap, ctx, provisions, cross);
113
- if (executed !== undefined) {
114
- return Promise.resolve(executed);
115
- }
116
- return Promise.resolve(Result.ok());
117
- };
118
- return cross;
119
- };
120
- // ---------------------------------------------------------------------------
121
- // Scenario assertions
122
- // ---------------------------------------------------------------------------
123
- const assertScenarioResult = (result, scenario, trailDef) => {
124
- if (scenario.expectValue !== undefined) {
125
- assertFullMatch(result, scenario.expectValue);
126
- }
127
- else if (scenario.expectErr !== undefined) {
128
- assertErrorMatch(result, scenario.expectErr, scenario.expectErrMessage);
129
- }
130
- else if (scenario.expectErrMessage !== undefined) {
131
- expect(result.isErr()).toBe(true);
132
- if (result.isErr()) {
133
- expect(result.error.message).toContain(scenario.expectErrMessage);
134
- }
135
- }
136
- else if (scenario.expectOk === true) {
137
- expect(result.isOk()).toBe(true);
138
- assertSchemaMatch(result, trailDef.output);
139
- }
140
- };
141
- const assertCrossTrace = (trace, scenario) => {
142
- if (scenario.expectCrossed !== undefined) {
143
- const crossedIds = trace.map((r) => r.id);
144
- expect(crossedIds).toEqual([...scenario.expectCrossed]);
145
- }
146
- if (scenario.expectCrossedCount !== undefined) {
147
- const counts = {};
148
- for (const record of trace) {
149
- counts[record.id] = (counts[record.id] ?? 0) + 1;
150
- }
151
- expect(counts).toEqual({ ...scenario.expectCrossedCount });
152
- }
153
- };
154
- const handleValidationError = (validated, scenario) => {
155
- if (!validated.isErr()) {
156
- return false;
157
- }
158
- if (scenario.expectErr === ValidationError) {
159
- expect(validated.error).toBeInstanceOf(ValidationError);
160
- if (scenario.expectErrMessage !== undefined) {
161
- expect(validated.error.message).toContain(scenario.expectErrMessage);
162
- }
163
- return true;
164
- }
165
- throw new Error(`Input validation failed unexpectedly: ${validated.error.message}`);
166
- };
167
- // ---------------------------------------------------------------------------
168
- // Scenario runner
169
- // ---------------------------------------------------------------------------
170
- const buildTestContext = (scenario, ctx, trailsMap, provisions) => {
171
- const trace = [];
172
- const baseCtx = mergeTestContext(ctx);
173
- const cross = createRecordingCross(trace, scenario, trailsMap, baseCtx.cross, baseCtx, provisions);
174
- return { testCtx: { ...baseCtx, cross }, trace };
175
- };
176
- const runScenario = async (trailDef, scenario, ctx, trailsMap, provisions) => {
177
- const validated = validateInput(trailDef.input, scenario.input);
178
- if (handleValidationError(validated, scenario)) {
179
- return;
180
- }
181
- const { trace, testCtx } = buildTestContext(scenario, ctx, trailsMap, provisions);
182
- const result = await executeTrail(trailDef, scenario.input, {
183
- ctx: testCtx,
184
- provisions,
185
- });
186
- assertCrossTrace(trace, scenario);
187
- assertScenarioResult(result, scenario, trailDef);
188
- };
189
- /**
190
- * Generate a describe block for a trail with crossings with one test per scenario.
191
- *
192
- * @example
193
- * ```ts
194
- * testCrosses(onboardTrail, [
195
- * {
196
- * description: "crosses add then relate",
197
- * input: { name: "Alpha" },
198
- * expectOk: true,
199
- * expectCrossed: ["entity.add", "entity.relate"],
200
- * },
201
- * ]);
202
- * ```
203
- */
204
- export const testCrosses = (trailDef, scenarios, options) => {
205
- const explicitProvisions = options?.provisions;
206
- describe(trailDef.id, () => {
207
- test.each([...scenarios])('$description', async (scenario) => {
208
- const provisions = mergeProvisionOverrides(await resolveCrossMockProvisions(trailDef, options?.trails), options?.ctx, explicitProvisions);
209
- await runScenario(trailDef, scenario, options?.ctx, options?.trails, provisions);
210
- });
211
- });
212
- };
213
- //# sourceMappingURL=crosses.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"crosses.js","sourceRoot":"","sources":["../src/crosses.ts"],"names":[],"mappings":"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"}
package/dist/detours.d.ts DELETED
@@ -1,12 +0,0 @@
1
- /**
2
- * testDetours — verify that all detour targets exist in the topo.
3
- *
4
- * Pure structural validation. No implementation execution needed.
5
- */
6
- import type { Topo } from '@ontrails/core';
7
- /**
8
- * Verify that every trail's detour targets reference trails that
9
- * actually exist in the app's topo.
10
- */
11
- export declare const testDetours: (app: Topo) => void;
12
- //# sourceMappingURL=detours.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detours.d.ts","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAS,MAAM,gBAAgB,CAAC;AAMlD;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAI,KAAK,IAAI,KAAG,IAyBvC,CAAC"}
package/dist/detours.js DELETED
@@ -1,30 +0,0 @@
1
- /**
2
- * testDetours — verify that all detour targets exist in the topo.
3
- *
4
- * Pure structural validation. No implementation execution needed.
5
- */
6
- import { describe, expect, test } from 'bun:test';
7
- // ---------------------------------------------------------------------------
8
- // testDetours
9
- // ---------------------------------------------------------------------------
10
- /**
11
- * Verify that every trail's detour targets reference trails that
12
- * actually exist in the app's topo.
13
- */
14
- export const testDetours = (app) => {
15
- const trailEntries = [...app.trails];
16
- describe('detours', () => {
17
- describe.each(trailEntries)('%s', (_id, trailDef) => {
18
- const t = trailDef;
19
- if (t.detours === undefined) {
20
- return;
21
- }
22
- const { detours } = t;
23
- const testCases = Object.entries(detours).flatMap(([detourName, targets]) => targets.map((targetId) => ({ detourName, targetId })));
24
- test.each(testCases)('detour "$detourName" -> "$targetId" exists', ({ targetId }) => {
25
- expect(app.has(targetId)).toBe(true);
26
- });
27
- });
28
- });
29
- };
30
- //# sourceMappingURL=detours.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"detours.js","sourceRoot":"","sources":["../src/detours.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAIlD,8EAA8E;AAC9E,cAAc;AACd,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAS,EAAQ,EAAE;IAC7C,MAAM,YAAY,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAErC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;QACvB,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;YAClD,MAAM,CAAC,GAAG,QAAmC,CAAC;YAE9C,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO;YACT,CAAC;YAED,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,CAAC;YACtB,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAC/C,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,CACxB,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CACxD,CAAC;YAEF,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAClB,4CAA4C,EAC5C,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE;gBACf,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC"}
@@ -1,23 +0,0 @@
1
- /**
2
- * testExamples — the headline one-liner.
3
- *
4
- * Iterates every trail in the app's topo. For each trail with examples,
5
- * generates describe/test blocks using bun:test. Progressive assertion
6
- * determines which check to run per example. For trails with `crosses`
7
- * declarations, checks that every declared crossing was called at least once.
8
- */
9
- import type { Topo, TrailContext } from '@ontrails/core';
10
- import type { TestExecutionOptions } from './context.js';
11
- /**
12
- * Generate describe/test blocks for every trail example in the app.
13
- *
14
- * For trails with `crosses` declarations and examples, also verifies that
15
- * every declared crossed ID was called at least once across all examples.
16
- *
17
- * One line in your test file:
18
- * ```ts
19
- * testExamples(app);
20
- * ```
21
- */
22
- export declare const testExamples: (app: Topo, ctxOrFactory?: Partial<TrailContext> | TestExecutionOptions | (() => Partial<TrailContext> | TestExecutionOptions)) => void;
23
- //# sourceMappingURL=examples.d.ts.map
@@ -1 +0,0 @@
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 DELETED
@@ -1,202 +0,0 @@
1
- /**
2
- * testExamples — the headline one-liner.
3
- *
4
- * Iterates every trail in the app's topo. For each trail with examples,
5
- * generates describe/test blocks using bun:test. Progressive assertion
6
- * determines which check to run per example. For trails with `crosses`
7
- * declarations, checks that every declared crossing was called at least once.
8
- */
9
- import { describe, expect, test } from 'bun:test';
10
- import { AlreadyExistsError, AmbiguousError, AssertionError, AuthError, CancelledError, ConflictError, InternalError, NetworkError, NotFoundError, PermissionError, RateLimitError, executeTrail, Result, TimeoutError, TrailsError, ValidationError, validateInput, } from '@ontrails/core';
11
- import { assertErrorMatch, assertFullMatch, assertSchemaMatch, } from './assertions.js';
12
- import { defaultMintPermit, mergeProvisionOverrides, mergeTestContext, normalizeTestExecutionOptions, resolveMockProvisions, } from './context.js';
13
- // ---------------------------------------------------------------------------
14
- // Error class name -> constructor map
15
- // ---------------------------------------------------------------------------
16
- const ERROR_MAP = {
17
- AlreadyExistsError: AlreadyExistsError,
18
- AmbiguousError: AmbiguousError,
19
- AssertionError: AssertionError,
20
- AuthError: AuthError,
21
- CancelledError: CancelledError,
22
- ConflictError: ConflictError,
23
- InternalError: InternalError,
24
- NetworkError: NetworkError,
25
- NotFoundError: NotFoundError,
26
- PermissionError: PermissionError,
27
- RateLimitError: RateLimitError,
28
- TimeoutError: TimeoutError,
29
- TrailsError: TrailsError,
30
- ValidationError: ValidationError,
31
- };
32
- /**
33
- * Resolve an error class name string to the actual constructor.
34
- * Falls back to generic Error if the name is not in the core taxonomy.
35
- */
36
- const resolveErrorClass = (name) => ERROR_MAP[name] ?? Error;
37
- // ---------------------------------------------------------------------------
38
- // Helpers
39
- // ---------------------------------------------------------------------------
40
- const assertProgressiveMatch = (result, example, output) => {
41
- if (example.expected !== undefined) {
42
- assertFullMatch(result, example.expected);
43
- return;
44
- }
45
- if (example.error !== undefined) {
46
- const errorClass = resolveErrorClass(example.error);
47
- assertErrorMatch(result, errorClass);
48
- return;
49
- }
50
- assertSchemaMatch(result, output);
51
- };
52
- /**
53
- * Handle input validation failure for an example.
54
- * Returns true if the validation error was expected (and assertions passed).
55
- * Throws if the validation error was unexpected.
56
- */
57
- const handleValidationError = (validated, example) => {
58
- if (!validated.isErr()) {
59
- return false;
60
- }
61
- if (example.error !== undefined) {
62
- const errorClass = resolveErrorClass(example.error);
63
- expect(validated.error).toBeInstanceOf(errorClass);
64
- return true;
65
- }
66
- throw new Error(`Example "${example.name}" has invalid input: ${validated.error.message}`);
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
- };
86
- /**
87
- * Run a single example against a trail.
88
- * Handles validation, execution, and assertions.
89
- */
90
- const runExample = async (t, example, output, testCtx, provisions, opts) => {
91
- const validated = validateInput(t.input, example.input);
92
- if (handleValidationError(validated, example)) {
93
- return;
94
- }
95
- const ctx = opts ? applyAutoMint(testCtx, t, opts) : testCtx;
96
- const result = await executeTrail(t, example.input, {
97
- ctx,
98
- provisions: provisions ?? opts?.provisions,
99
- });
100
- assertProgressiveMatch(result, example, output);
101
- };
102
- // ---------------------------------------------------------------------------
103
- // Crossing coverage for trails with crossings
104
- // ---------------------------------------------------------------------------
105
- /**
106
- * Build a recording cross function that tracks which trail IDs are called.
107
- *
108
- * Delegates to `baseCross` when available, otherwise looks up the trail
109
- * in the topo and executes it with validated input. Falls back to
110
- * `Result.ok()` when neither is available.
111
- */
112
- const createCoverageCross = (called, baseCross, topo, ctx, provisions) => {
113
- const cross = (id, input) => {
114
- called.add(id);
115
- if (baseCross !== undefined) {
116
- return baseCross(id, input);
117
- }
118
- const trailDef = topo.get(id);
119
- if (trailDef !== undefined) {
120
- return executeTrail(trailDef, input, {
121
- ctx: { ...ctx, cross },
122
- provisions,
123
- });
124
- }
125
- return Promise.resolve(Result.ok());
126
- };
127
- return cross;
128
- };
129
- /**
130
- * Run a single example against a trail with crossings, recording cross calls.
131
- */
132
- const runCompositionExample = async (trailDef, example, output, baseCtx, called, topo, provisions, opts) => {
133
- const validated = validateInput(trailDef.input, example.input);
134
- if (handleValidationError(validated, example)) {
135
- return;
136
- }
137
- const mintedCtx = opts ? applyAutoMint(baseCtx, trailDef, opts) : baseCtx;
138
- const cross = createCoverageCross(called, mintedCtx.cross, topo, mintedCtx, provisions);
139
- const testCtx = { ...mintedCtx, cross };
140
- const result = await executeTrail(trailDef, example.input, {
141
- ctx: testCtx,
142
- provisions: provisions ?? opts?.provisions,
143
- });
144
- assertProgressiveMatch(result, example, output);
145
- };
146
- // ---------------------------------------------------------------------------
147
- // testExamples
148
- // ---------------------------------------------------------------------------
149
- /**
150
- * Generate describe/test blocks for every trail example in the app.
151
- *
152
- * For trails with `crosses` declarations and examples, also verifies that
153
- * every declared crossed ID was called at least once across all examples.
154
- *
155
- * One line in your test file:
156
- * ```ts
157
- * testExamples(app);
158
- * ```
159
- */
160
- export const testExamples = (app, ctxOrFactory) => {
161
- const resolveInput = typeof ctxOrFactory === 'function' ? ctxOrFactory : () => ctxOrFactory;
162
- const allTrails = app.list();
163
- const withExamples = allTrails.filter((t) => t.examples !== undefined && t.examples.length > 0);
164
- const simpleTrails = withExamples.filter((t) => t.crosses.length === 0);
165
- const compositionTrails = withExamples.filter((t) => t.crosses.length > 0);
166
- // Simple trails: run examples directly
167
- if (simpleTrails.length > 0) {
168
- describe.each(simpleTrails)('$id', (t) => {
169
- const { examples, output } = t;
170
- if (!examples) {
171
- return;
172
- }
173
- test.each([...examples])('example: $name', async (example) => {
174
- const resolved = normalizeTestExecutionOptions(resolveInput());
175
- const provisions = mergeProvisionOverrides(await resolveMockProvisions(app), resolved.ctx, resolved.provisions);
176
- const testCtx = mergeTestContext(resolved.ctx);
177
- await runExample(t, example, output, testCtx, provisions, resolved);
178
- });
179
- });
180
- }
181
- // Composition trails: use recording cross and check coverage
182
- if (compositionTrails.length > 0) {
183
- describe.each(compositionTrails)('$id', (t) => {
184
- const { examples, output } = t;
185
- if (!examples) {
186
- return;
187
- }
188
- const called = new Set();
189
- test.each([...examples])('example: $name', async (example) => {
190
- const resolved = normalizeTestExecutionOptions(resolveInput());
191
- const provisions = mergeProvisionOverrides(await resolveMockProvisions(app), resolved.ctx, resolved.provisions);
192
- const baseCtx = mergeTestContext(resolved.ctx);
193
- await runCompositionExample(t, example, output, baseCtx, called, app, provisions, resolved);
194
- });
195
- test('crossing coverage', () => {
196
- const uncovered = t.crosses.filter((id) => !called.has(id));
197
- expect(uncovered).toEqual([]);
198
- });
199
- });
200
- }
201
- };
202
- //# sourceMappingURL=examples.js.map
@@ -1 +0,0 @@
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,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,6BAA6B,EAC7B,qBAAqB,GACtB,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,aAAa,GAAG,CACpB,GAAiB,EACjB,QAAuB,EACvB,IAA0B,EACZ,EAAE;IAChB,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC7B,OAAO,GAAG,CAAC;IACb,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAClD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,EAAE,GAAG,GAAG,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,GAAG,KAAK,EACtB,CAA0B,EAC1B,OAAuC,EACvC,MAA6B,EAC7B,OAAqB,EACrB,UAAiC,EACjC,IAA2B,EACZ,EAAE;IACjB,MAAM,SAAS,GAAG,aAAa,CAAC,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAExD,IAAI,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAE7D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,EAAE;QAClD,GAAG;QACH,UAAU,EAAE,UAAU,IAAI,IAAI,EAAE,UAAU;KAC3C,CAAC,CAAC;IACH,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,CAC1B,MAAmB,EACnB,SAA8B,EAC9B,IAAU,EACV,GAAiB,EACjB,UAAiC,EACxB,EAAE;IACX,MAAM,KAAK,GAAG,CAAC,EAAU,EAAE,KAAc,EAAE,EAAE;QAC3C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEf,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,SAAS,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,YAAY,CAAC,QAAQ,EAAE,KAAK,EAAE;gBACnC,GAAG,EAAE,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE;gBACtB,UAAU;aACX,CAAC,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC;IACF,OAAO,KAAgB,CAAC;AAC1B,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,qBAAqB,GAAG,KAAK,EACjC,QAAiC,EACjC,OAAuC,EACvC,MAA6B,EAC7B,OAAqB,EACrB,MAAmB,EACnB,IAAU,EACV,UAAiC,EACjC,IAA2B,EACZ,EAAE;IACjB,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE/D,IAAI,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1E,MAAM,KAAK,GAAG,mBAAmB,CAC/B,MAAM,EACN,SAAS,CAAC,KAAK,EACf,IAAI,EACJ,SAAS,EACT,UAAU,CACX,CAAC;IACF,MAAM,OAAO,GAAiB,EAAE,GAAG,SAAS,EAAE,KAAK,EAAE,CAAC;IAEtD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,KAAK,EAAE;QACzD,GAAG,EAAE,OAAO;QACZ,UAAU,EAAE,UAAU,IAAI,IAAI,EAAE,UAAU;KAC3C,CAAC,CAAC;IACH,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAS,EACT,YAGwD,EAClD,EAAE;IACR,MAAM,YAAY,GAChB,OAAO,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;IACzE,MAAM,SAAS,GAAG,GAAG,CAAC,IAAI,EAA+B,CAAC;IAE1D,MAAM,YAAY,GAAG,SAAS,CAAC,MAAM,CACnC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CACzD,CAAC;IACF,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC;IACxE,MAAM,iBAAiB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE3E,uCAAuC;IACvC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE;YACvC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CACtB,gBAAgB,EAChB,KAAK,EAAE,OAAuC,EAAE,EAAE;gBAChD,MAAM,QAAQ,GAAG,6BAA6B,CAAC,YAAY,EAAE,CAAC,CAAC;gBAC/D,MAAM,UAAU,GAAG,uBAAuB,CACxC,MAAM,qBAAqB,CAAC,GAAG,CAAC,EAChC,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,UAAU,CACpB,CAAC;gBACF,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC/C,MAAM,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;YACtE,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,6DAA6D;IAC7D,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,QAAQ,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE;YAC5C,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;YAEjC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CACtB,gBAAgB,EAChB,KAAK,EAAE,OAAuC,EAAE,EAAE;gBAChD,MAAM,QAAQ,GAAG,6BAA6B,CAAC,YAAY,EAAE,CAAC,CAAC;gBAC/D,MAAM,UAAU,GAAG,uBAAuB,CACxC,MAAM,qBAAqB,CAAC,GAAG,CAAC,EAChC,QAAQ,CAAC,GAAG,EACZ,QAAQ,CAAC,UAAU,CACpB,CAAC;gBACF,MAAM,OAAO,GAAG,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC/C,MAAM,qBAAqB,CACzB,CAAC,EACD,OAAO,EACP,MAAM,EACN,OAAO,EACP,MAAM,EACN,GAAG,EACH,UAAU,EACV,QAAQ,CACT,CAAC;YACJ,CAAC,CACF,CAAC;YAEF,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE;gBAC7B,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAC5D,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
package/dist/follows.d.ts DELETED
@@ -1,38 +0,0 @@
1
- /**
2
- * testFollows — composition-aware scenario testing for trails with follow.
3
- *
4
- * Tests the follow graph: which trails were followed, in what order,
5
- * and supports failure injection from followed trail examples.
6
- */
7
- import type { AnyTrail, ServiceOverrideMap, TrailContext } from '@ontrails/core';
8
- import type { FollowScenario } from './types.js';
9
- /** Options for testFollows that provide trail definitions for injection. */
10
- export interface TestFollowOptions {
11
- /** Partial context overrides. */
12
- readonly ctx?: Partial<TrailContext> | undefined;
13
- /**
14
- * Explicit service overrides merged on top of auto-resolved mocks for every
15
- * scenario. Values are passed by reference — provide immutable objects, or
16
- * use `mock()` on the service definition to get a fresh instance per run.
17
- */
18
- readonly services?: ServiceOverrideMap | undefined;
19
- /** Map of trail ID to trail definition, used for injectFromExample. */
20
- readonly trails?: ReadonlyMap<string, AnyTrail> | undefined;
21
- }
22
- /**
23
- * Generate a describe block for a composition trail with one test per scenario.
24
- *
25
- * @example
26
- * ```ts
27
- * testFollows(onboardTrail, [
28
- * {
29
- * description: "follows add then relate",
30
- * input: { name: "Alpha" },
31
- * expectOk: true,
32
- * expectFollowed: ["entity.add", "entity.relate"],
33
- * },
34
- * ]);
35
- * ```
36
- */
37
- export declare const testFollows: (trailDef: AnyTrail, scenarios: readonly FollowScenario[], options?: TestFollowOptions) => void;
38
- //# sourceMappingURL=follows.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"follows.d.ts","sourceRoot":"","sources":["../src/follows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EACV,QAAQ,EAER,kBAAkB,EAClB,YAAY,EACb,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAuSjD,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACnD,uEAAuE;IACvE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAC;CAC7D;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,QAAQ,EAClB,WAAW,SAAS,cAAc,EAAE,EACpC,UAAU,iBAAiB,KAC1B,IAoBF,CAAC"}