@ontrails/testing 1.0.0-beta.1 → 1.0.0-beta.10

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 (49) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +138 -0
  3. package/README.md +25 -7
  4. package/dist/context.d.ts +20 -1
  5. package/dist/context.d.ts.map +1 -1
  6. package/dist/context.js +25 -0
  7. package/dist/context.js.map +1 -1
  8. package/dist/contracts.d.ts +1 -1
  9. package/dist/contracts.d.ts.map +1 -1
  10. package/dist/contracts.js +15 -5
  11. package/dist/contracts.js.map +1 -1
  12. package/dist/examples.d.ts +2 -2
  13. package/dist/examples.d.ts.map +1 -1
  14. package/dist/examples.js +43 -55
  15. package/dist/examples.js.map +1 -1
  16. package/dist/follows.d.ts +32 -0
  17. package/dist/follows.d.ts.map +1 -0
  18. package/dist/{hike.js → follows.js} +15 -15
  19. package/dist/follows.js.map +1 -0
  20. package/dist/harness-mcp.d.ts.map +1 -1
  21. package/dist/harness-mcp.js +5 -2
  22. package/dist/harness-mcp.js.map +1 -1
  23. package/dist/index.d.ts +5 -4
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/index.js +2 -2
  26. package/dist/index.js.map +1 -1
  27. package/dist/trail.js +1 -1
  28. package/dist/trail.js.map +1 -1
  29. package/dist/types.d.ts +2 -2
  30. package/dist/types.d.ts.map +1 -1
  31. package/package.json +6 -6
  32. package/src/__tests__/context.test.ts +36 -1
  33. package/src/__tests__/contracts.test.ts +30 -4
  34. package/src/__tests__/detours.test.ts +3 -3
  35. package/src/__tests__/examples.test.ts +21 -22
  36. package/src/__tests__/{hike.test.ts → follows.test.ts} +27 -28
  37. package/src/__tests__/trail.test.ts +4 -4
  38. package/src/context.ts +42 -1
  39. package/src/contracts.ts +19 -6
  40. package/src/examples.ts +55 -91
  41. package/src/{hike.ts → follows.ts} +30 -30
  42. package/src/harness-mcp.ts +5 -2
  43. package/src/index.ts +5 -4
  44. package/src/trail.ts +1 -1
  45. package/src/types.ts +3 -3
  46. package/tsconfig.tsbuildinfo +1 -1
  47. package/dist/hike.d.ts +0 -32
  48. package/dist/hike.d.ts.map +0 -1
  49. package/dist/hike.js.map +0 -1
@@ -1,3 +1,3 @@
1
1
  $ oxlint ./src
2
2
  Found 0 warnings and 0 errors.
3
- Finished in 27ms on 20 files with 93 rules using 24 threads.
3
+ Finished in 75ms on 20 files with 93 rules using 24 threads.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,143 @@
1
1
  # @ontrails/testing
2
2
 
3
+ ## 1.0.0-beta.10
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @ontrails/core@1.0.0-beta.10
9
+ - @ontrails/cli@1.0.0-beta.10
10
+ - @ontrails/mcp@1.0.0-beta.10
11
+ - @ontrails/logging@1.0.0-beta.10
12
+
13
+ ## 1.0.0-beta.9
14
+
15
+ ### Minor Changes
16
+
17
+ - Consolidated improvements across all surface packages.
18
+
19
+ **core**: Add `TrailResult<T>` utility type, `topo.ids()` and `topo.count` accessors, `dispatch()` for headless trail execution, and extract shared `executeTrail` pipeline used by CLI/MCP/HTTP.
20
+
21
+ **http**: Detect route path collisions and return `Result` from `buildHttpRoutes()`, wire request `AbortSignal` through to trail context, and make write → POST mapping explicit in intent-to-method lookup.
22
+
23
+ **mcp**: Return `Result` from `buildMcpTools()` on collision instead of throwing.
24
+
25
+ **cli**: Verify exception catching via centralized `executeTrail`.
26
+
27
+ **testing**: Follow context awareness improvements.
28
+
29
+ **warden**: Refactor rules as composable trails with examples.
30
+
31
+ **schema**: Error code and empty body fixes.
32
+
33
+ ### Patch Changes
34
+
35
+ - Updated dependencies
36
+ - @ontrails/core@1.0.0-beta.9
37
+ - @ontrails/cli@1.0.0-beta.9
38
+ - @ontrails/mcp@1.0.0-beta.9
39
+ - @ontrails/logging@1.0.0-beta.9
40
+
41
+ ## 1.0.0-beta.8
42
+
43
+ ### Patch Changes
44
+
45
+ - @ontrails/cli@1.0.0-beta.8
46
+ - @ontrails/core@1.0.0-beta.8
47
+ - @ontrails/logging@1.0.0-beta.8
48
+ - @ontrails/mcp@1.0.0-beta.8
49
+
50
+ ## 1.0.0-beta.7
51
+
52
+ ### Patch Changes
53
+
54
+ - @ontrails/cli@1.0.0-beta.7
55
+ - @ontrails/core@1.0.0-beta.7
56
+ - @ontrails/logging@1.0.0-beta.7
57
+ - @ontrails/mcp@1.0.0-beta.7
58
+
59
+ ## 1.0.0-beta.6
60
+
61
+ ### Patch Changes
62
+
63
+ - Updated dependencies
64
+ - @ontrails/core@1.0.0-beta.6
65
+ - @ontrails/cli@1.0.0-beta.6
66
+ - @ontrails/logging@1.0.0-beta.6
67
+ - @ontrails/mcp@1.0.0-beta.6
68
+
69
+ ## 1.0.0-beta.5
70
+
71
+ ### Patch Changes
72
+
73
+ - Updated dependencies
74
+ - @ontrails/core@1.0.0-beta.5
75
+ - @ontrails/logging@1.0.0-beta.5
76
+ - @ontrails/cli@1.0.0-beta.5
77
+ - @ontrails/mcp@1.0.0-beta.5
78
+
79
+ ## 1.0.0-beta.4
80
+
81
+ ### Major Changes
82
+
83
+ - API simplification: unified trail model, intent enum, run, metadata.
84
+
85
+ **BREAKING CHANGES:**
86
+
87
+ - `hike()` removed — use `trail()` with optional `follow: [...]` field
88
+ - `follows` renamed to `follow` (singular, matching `ctx.follow()`)
89
+ - `topo.hikes` removed — single `topo.trails` map
90
+ - `kind: 'hike'` removed — everything is `kind: 'trail'`
91
+ - `readOnly`/`destructive` booleans replaced by `intent: 'read' | 'write' | 'destroy'`
92
+ - `implementation` field renamed to `run`
93
+ - `markers` field renamed to `metadata`
94
+ - `testHike` renamed to `testFollows`, `HikeScenario` to `FollowScenario`
95
+ - `blaze()` now returns the surface handle (`Command` for CLI, `Server` for MCP)
96
+
97
+ ### Patch Changes
98
+
99
+ - Updated dependencies
100
+ - @ontrails/core@1.0.0-beta.4
101
+ - @ontrails/cli@1.0.0-beta.4
102
+ - @ontrails/mcp@1.0.0-beta.4
103
+ - @ontrails/logging@1.0.0-beta.4
104
+
105
+ ## 1.0.0-beta.3
106
+
107
+ ### Minor Changes
108
+
109
+ - Bug fixes across all surface packages found via parallel Codex review.
110
+
111
+ **core**: Fix Result.toJson false circular detection on DAGs, deserializeError subclass round-trip, topo cross-kind ID collisions, validateTopo multi-node cycle detection, error example input validation bypass, and deriveFields array type collapse.
112
+
113
+ **cli**: Switch blaze to parseAsync for proper async error handling, add boolean flag negation (--no-flag), and strict number parsing that rejects partial input.
114
+
115
+ **mcp**: Align BlobRef with core (including ReadableStream support) and detect tool-name collisions after normalization.
116
+
117
+ **testing**: Include hikes in testContracts validation, with follow-context awareness.
118
+
119
+ **warden**: Collect hike detour targets, validate detour refs in hike specs, and stop implementation-returns-result from walking into nested function bodies.
120
+
121
+ ### Patch Changes
122
+
123
+ - Updated dependencies
124
+ - @ontrails/core@1.0.0-beta.3
125
+ - @ontrails/cli@1.0.0-beta.3
126
+ - @ontrails/mcp@1.0.0-beta.3
127
+ - @ontrails/logging@1.0.0-beta.3
128
+
129
+ ## 1.0.0-beta.2
130
+
131
+ ### Patch Changes
132
+
133
+ - Fix workspace dependency resolution in published packages. Now using bun publish
134
+ which correctly replaces workspace:^ with actual version numbers.
135
+ - Updated dependencies
136
+ - @ontrails/core@1.0.0-beta.2
137
+ - @ontrails/cli@1.0.0-beta.2
138
+ - @ontrails/mcp@1.0.0-beta.2
139
+ - @ontrails/logging@1.0.0-beta.2
140
+
3
141
  ## 1.0.0-beta.1
4
142
 
5
143
  ### Patch Changes
package/README.md CHANGED
@@ -29,10 +29,10 @@ testDetours(app); // Verify detour targets exist
29
29
  | --- | --- |
30
30
  | `testAll(topo, ctx?)` | Single-line governance suite: validation + examples + contracts + detours |
31
31
  | `testExamples(topo, ctx?)` | Run trail examples as `describe`/`test` blocks |
32
- | `testTrail(trail, scenarios)` | Custom scenarios for edge cases and error paths |
33
- | `testHike(hike, scenarios)` | Test composition graphs -- follow chains, failure injection |
34
- | `testContracts(topo, ctx?)` | Validate implementation output against declared schemas |
32
+ | `testTrail(trail, scenarios)` | Custom scenarios for edge cases, error paths, and follow chains |
33
+ | `testContracts(topo, ctx?)` | Validate output against declared schemas |
35
34
  | `testDetours(topo)` | Verify every detour target exists in the topo |
35
+ | `createFollowContext(options?)` | Mock `FollowFn` for testing composite trails; returns preconfigured `Result` values keyed by trail ID |
36
36
  | `createTestContext(options?)` | `TrailContext` with sensible test defaults |
37
37
  | `createTestLogger()` | Logger that captures entries in memory for assertions |
38
38
  | `createCliHarness(options)` | Execute CLI commands in-process, capture stdout/stderr |
@@ -55,19 +55,37 @@ testTrail(showTrail, [
55
55
  ]);
56
56
  ```
57
57
 
58
- ## testHike
58
+ ## Testing composition (trails with follow)
59
59
 
60
- Where `testTrail` exercises a single trail, `testHike` exercises the follow graph:
60
+ `testTrail` works the same for trails with `follow` -- it exercises the follow graph:
61
61
 
62
62
  ```typescript
63
- import { testHike } from '@ontrails/testing';
63
+ import { testTrail } from '@ontrails/testing';
64
64
 
65
- testHike(onboardHike, [
65
+ testTrail(onboardTrail, [
66
66
  { description: 'happy path', input: { name: 'Delta', type: 'tool' }, expectOk: true },
67
67
  { description: 'add fails', input: { name: 'Alpha' }, expectErr: AlreadyExistsError },
68
68
  ]);
69
69
  ```
70
70
 
71
+ When you need to isolate a composite trail and stub out its dependencies, use `createFollowContext`:
72
+
73
+ ```typescript
74
+ import { createFollowContext, createTestContext } from '@ontrails/testing';
75
+ import { Result } from '@ontrails/core';
76
+
77
+ const follow = createFollowContext({
78
+ responses: {
79
+ 'entity.add': Result.ok({ id: '1', name: 'Delta', type: 'tool' }),
80
+ 'search': Result.ok({ results: [] }),
81
+ },
82
+ });
83
+ const ctx = { ...createTestContext(), follow };
84
+ const result = await onboardTrail.run({ name: 'Delta', type: 'tool' }, ctx);
85
+ ```
86
+
87
+ Calls to unregistered trail IDs return `Result.err` with a descriptive message, so missing stubs fail loudly.
88
+
71
89
  ## Surface harnesses
72
90
 
73
91
  ```typescript
package/dist/context.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * Test context factory for creating TrailContext instances suitable for testing.
3
3
  */
4
- import type { TrailContext } from '@ontrails/core';
4
+ import type { FollowFn, TrailContext } from '@ontrails/core';
5
+ import { Result } from '@ontrails/core';
5
6
  import type { TestTrailContextOptions } from './types.js';
6
7
  /**
7
8
  * Create a TrailContext with deterministic, test-friendly defaults.
@@ -11,6 +12,24 @@ import type { TestTrailContextOptions } from './types.js';
11
12
  * - `signal`: a non-aborted AbortController signal
12
13
  */
13
14
  export declare const createTestContext: (overrides?: TestTrailContextOptions) => TrailContext;
15
+ export interface CreateFollowContextOptions {
16
+ readonly responses?: Record<string, Result<unknown, Error>> | undefined;
17
+ }
18
+ /**
19
+ * Create a mock `FollowFn` for testing composite trails.
20
+ *
21
+ * Returns preconfigured `Result` values keyed by trail ID. Calls to
22
+ * unregistered IDs return `Result.err` with a descriptive message.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * const follow = createFollowContext({
27
+ * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
28
+ * });
29
+ * const ctx = { ...createTestContext(), follow };
30
+ * ```
31
+ */
32
+ export declare const createFollowContext: (options?: CreateFollowContextOptions) => FollowFn;
14
33
  /**
15
34
  * Merge a Partial<TrailContext> into a test context.
16
35
  * Used internally when the public API accepts Partial<TrailContext>.
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAM1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAMD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,OAAO,CAAC,YAAY,CAAC,KAAG,YAO9D,CAAC"}
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAGxC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAM1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAMD,CAAC;AAMH,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;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,mBAAmB,GAC9B,UAAU,0BAA0B,KACnC,QAcF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,OAAO,CAAC,YAAY,CAAC,KAAG,YAO9D,CAAC"}
package/dist/context.js CHANGED
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Test context factory for creating TrailContext instances suitable for testing.
3
3
  */
4
+ import { Result } from '@ontrails/core';
4
5
  import { createTestLogger } from './logger.js';
5
6
  // ---------------------------------------------------------------------------
6
7
  // createTestContext
@@ -19,6 +20,30 @@ export const createTestContext = (overrides) => ({
19
20
  signal: overrides?.signal ?? new AbortController().signal,
20
21
  workspaceRoot: overrides?.cwd ?? process.cwd(),
21
22
  });
23
+ /**
24
+ * Create a mock `FollowFn` for testing composite trails.
25
+ *
26
+ * Returns preconfigured `Result` values keyed by trail ID. Calls to
27
+ * unregistered IDs return `Result.err` with a descriptive message.
28
+ *
29
+ * @example
30
+ * ```ts
31
+ * const follow = createFollowContext({
32
+ * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
33
+ * });
34
+ * const ctx = { ...createTestContext(), follow };
35
+ * ```
36
+ */
37
+ export const createFollowContext = (options) => {
38
+ const responses = options?.responses ?? {};
39
+ return (id, _input) => {
40
+ const response = responses[id];
41
+ if (response === undefined) {
42
+ return Promise.resolve(Result.err(new Error(`No mock response for follow("${id}")`)));
43
+ }
44
+ return Promise.resolve(response);
45
+ };
46
+ };
22
47
  /**
23
48
  * Merge a Partial<TrailContext> into a test context.
24
49
  * Used internally when the public API accepts Partial<TrailContext>.
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAmC,EACrB,EAAE,CAAC,CAAC;IAClB,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE;IAC7C,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,gBAAgB,EAAE;IAC/C,SAAS,EAAE,SAAS,EAAE,SAAS,IAAI,kBAAkB;IACrD,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,MAAM;IACzD,aAAa,EAAE,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;CAC/C,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAA2B,EAAgB,EAAE;IAC5E,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC;AAC7B,CAAC,CAAC"}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,SAAmC,EACrB,EAAE,CAAC,CAAC;IAClB,GAAG,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE;IAC7C,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,gBAAgB,EAAE;IAC/C,SAAS,EAAE,SAAS,EAAE,SAAS,IAAI,kBAAkB;IACrD,MAAM,EAAE,SAAS,EAAE,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC,MAAM;IACzD,aAAa,EAAE,SAAS,EAAE,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE;CAC/C,CAAC,CAAC;AAUH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,OAAoC,EAC1B,EAAE;IACZ,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,EAAE,CAAC;IAC3C,OAAO,CAAI,EAAU,EAAE,MAAe,EAA6B,EAAE;QACnE,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,OAAO,CAAC,OAAO,CACpB,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,gCAAgC,EAAE,IAAI,CAAC,CAG3D,CACF,CAAC;QACJ,CAAC;QACD,OAAO,OAAO,CAAC,OAAO,CAAC,QAA4B,CAAC,CAAC;IACvD,CAAC,CAAC;AACJ,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAA2B,EAAgB,EAAE;IAC5E,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QACtB,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACjC,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,EAAE,CAAC;AAC7B,CAAC,CAAC"}
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import type { Topo, TrailContext } from '@ontrails/core';
9
9
  /**
10
- * Verify that every trail's implementation output matches its declared
10
+ * Verify that every trail implementation output matches its declared
11
11
  * output schema. Catches implementation-schema drift.
12
12
  *
13
13
  * Trails without output schemas or examples are skipped.
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAuB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA8B9E;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,IAAI,EACT,eAAe,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,KACnE,IAmCF,CAAC"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,IAAI,EAAuB,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA0C9E;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,KAAK,IAAI,EACT,eAAe,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,KACnE,IAoCF,CAAC"}
package/dist/contracts.js CHANGED
@@ -12,6 +12,14 @@ import { mergeTestContext } from './context.js';
12
12
  // ---------------------------------------------------------------------------
13
13
  // Helpers
14
14
  // ---------------------------------------------------------------------------
15
+ /** Check if a trail requires follow() but the context doesn't provide it. */
16
+ const needsFollowContext = (t, resolveCtx) => {
17
+ const spec = t;
18
+ if (!spec.follow || spec.follow.length === 0) {
19
+ return false;
20
+ }
21
+ return !resolveCtx()?.follow;
22
+ };
15
23
  const validateOutputSchema = (outputSchema, value, trailId, exampleName) => {
16
24
  const parsed = outputSchema.safeParse(value);
17
25
  if (!parsed.success) {
@@ -23,30 +31,32 @@ const validateOutputSchema = (outputSchema, value, trailId, exampleName) => {
23
31
  // testContracts
24
32
  // ---------------------------------------------------------------------------
25
33
  /**
26
- * Verify that every trail's implementation output matches its declared
34
+ * Verify that every trail implementation output matches its declared
27
35
  * output schema. Catches implementation-schema drift.
28
36
  *
29
37
  * Trails without output schemas or examples are skipped.
30
38
  */
31
39
  export const testContracts = (app, ctxOrFactory) => {
32
40
  const resolveCtx = typeof ctxOrFactory === 'function' ? ctxOrFactory : () => ctxOrFactory;
33
- const trailEntries = [...app.trails];
41
+ const allEntries = app.list();
34
42
  describe('contracts', () => {
35
- describe.each(trailEntries)('%s', (_id, trailDef) => {
36
- const t = trailDef;
43
+ describe.each(allEntries)('$id', (t) => {
37
44
  if (t.output === undefined) {
38
45
  return;
39
46
  }
40
47
  if (t.examples === undefined || t.examples.length === 0) {
41
48
  return;
42
49
  }
50
+ if (needsFollowContext(t, resolveCtx)) {
51
+ return;
52
+ }
43
53
  const { examples, output: outputSchema } = t;
44
54
  const successExamples = examples.filter((e) => e.error === undefined);
45
55
  test.each(successExamples)('contract: $name', async (example) => {
46
56
  const testCtx = mergeTestContext(resolveCtx());
47
57
  const validated = validateInput(t.input, example.input);
48
58
  const validatedInput = expectOk(validated);
49
- const result = await t.implementation(validatedInput, testCtx);
59
+ const result = await t.run(validatedInput, testCtx);
50
60
  const resultValue = expectOk(result);
51
61
  validateOutputSchema(outputSchema, resultValue, t.id, example.name);
52
62
  });
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
@@ -3,14 +3,14 @@
3
3
  *
4
4
  * Iterates every trail in the app's topo. For each trail with examples,
5
5
  * generates describe/test blocks using bun:test. Progressive assertion
6
- * determines which check to run per example. For hikes with `follows`
6
+ * determines which check to run per example. For trails with `follow`
7
7
  * declarations, checks that every declared follow was called at least once.
8
8
  */
9
9
  import type { Topo, TrailContext } from '@ontrails/core';
10
10
  /**
11
11
  * Generate describe/test blocks for every trail example in the app.
12
12
  *
13
- * For hikes with `follows` declarations and examples, also verifies that
13
+ * For trails with `follow` declarations and examples, also verifies that
14
14
  * every declared follow ID was called at least once across all examples.
15
15
  *
16
16
  * One line in your test file:
@@ -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;AAkQxB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,IAAI,EACT,eAAe,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,KACnE,IAuBF,CAAC"}
1
+ {"version":3,"file":"examples.d.ts","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAEV,IAAI,EAGJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AAiMxB;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,IAAI,EACT,eAAe,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC,KACnE,IAqDF,CAAC"}
package/dist/examples.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Iterates every trail in the app's topo. For each trail with examples,
5
5
  * generates describe/test blocks using bun:test. Progressive assertion
6
- * determines which check to run per example. For hikes with `follows`
6
+ * determines which check to run per example. For trails with `follow`
7
7
  * declarations, checks that every declared follow was called at least once.
8
8
  */
9
9
  import { describe, expect, test } from 'bun:test';
@@ -75,11 +75,11 @@ const runExample = async (t, example, output, testCtx) => {
75
75
  return;
76
76
  }
77
77
  const validatedInput = expectOk(validated);
78
- const result = await t.implementation(validatedInput, testCtx);
78
+ const result = await t.run(validatedInput, testCtx);
79
79
  assertProgressiveMatch(result, example, output);
80
80
  };
81
81
  // ---------------------------------------------------------------------------
82
- // Follows coverage for hikes
82
+ // Follow coverage for composition trails
83
83
  // ---------------------------------------------------------------------------
84
84
  /**
85
85
  * Build a recording follow function that tracks which trail IDs are called.
@@ -100,67 +100,33 @@ const createCoverageFollow = (called, baseFollow, topo, ctx) => {
100
100
  if (validated.isErr()) {
101
101
  return Promise.resolve(validated);
102
102
  }
103
- return Promise.resolve(trailDef.implementation(validated.value, ctx));
103
+ return Promise.resolve(trailDef.run(validated.value, ctx));
104
104
  }
105
105
  return Promise.resolve(Result.ok());
106
106
  };
107
107
  return follow;
108
108
  };
109
109
  /**
110
- * Run a single example against a hike, recording follow calls.
110
+ * Run a single example against a composition trail, recording follow calls.
111
111
  */
112
- const runHikeExample = async (hikeDef, example, output, baseCtx, called, topo) => {
113
- const validated = validateInput(hikeDef.input, example.input);
112
+ const runCompositionExample = async (trailDef, example, output, baseCtx, called, topo) => {
113
+ const validated = validateInput(trailDef.input, example.input);
114
114
  if (handleValidationError(validated, example)) {
115
115
  return;
116
116
  }
117
117
  const validatedInput = expectOk(validated);
118
118
  const follow = createCoverageFollow(called, baseCtx.follow, topo, baseCtx);
119
119
  const testCtx = { ...baseCtx, follow };
120
- const result = await hikeDef.implementation(validatedInput, testCtx);
120
+ const result = await trailDef.run(validatedInput, testCtx);
121
121
  assertProgressiveMatch(result, example, output);
122
122
  };
123
- const collectHikesWithExamples = (app) => [...app.hikes]
124
- .filter(([, h]) => h.examples !== undefined && h.examples.length > 0)
125
- .map(([hikeId, hikeDef]) => ({
126
- examples: hikeDef.examples,
127
- hikeDef,
128
- hikeId,
129
- }));
130
- // ---------------------------------------------------------------------------
131
- // Hike example describe blocks
132
- // ---------------------------------------------------------------------------
133
- /**
134
- * Generate describe/test blocks for hikes with follows coverage.
135
- *
136
- * Always uses a recording follow so that follows coverage can be checked.
137
- * Hikes without `follows` still run their examples but skip the coverage test.
138
- */
139
- const describeHikeExamples = (hikesWithExamples, resolveCtx, topo) => {
140
- if (hikesWithExamples.length === 0) {
141
- return;
142
- }
143
- describe.each([...hikesWithExamples])('$hikeId', ({ hikeDef, examples }) => {
144
- const called = new Set();
145
- test.each([...examples])('example: $name', async (example) => {
146
- const baseCtx = mergeTestContext(resolveCtx());
147
- await runHikeExample(hikeDef, example, hikeDef.output, baseCtx, called, topo);
148
- });
149
- if (hikeDef.follows.length > 0) {
150
- test('follows coverage', () => {
151
- const uncovered = hikeDef.follows.filter((id) => !called.has(id));
152
- expect(uncovered).toEqual([]);
153
- });
154
- }
155
- });
156
- };
157
123
  // ---------------------------------------------------------------------------
158
124
  // testExamples
159
125
  // ---------------------------------------------------------------------------
160
126
  /**
161
127
  * Generate describe/test blocks for every trail example in the app.
162
128
  *
163
- * For hikes with `follows` declarations and examples, also verifies that
129
+ * For trails with `follow` declarations and examples, also verifies that
164
130
  * every declared follow ID was called at least once across all examples.
165
131
  *
166
132
  * One line in your test file:
@@ -170,18 +136,40 @@ const describeHikeExamples = (hikesWithExamples, resolveCtx, topo) => {
170
136
  */
171
137
  export const testExamples = (app, ctxOrFactory) => {
172
138
  const resolveCtx = typeof ctxOrFactory === 'function' ? ctxOrFactory : () => ctxOrFactory;
173
- const trailEntries = [...app.trails];
174
- describe.each(trailEntries)('%s', (_id, trailDef) => {
175
- const t = trailDef;
176
- if (t.examples === undefined || t.examples.length === 0) {
177
- return;
178
- }
179
- const { examples, output } = t;
180
- test.each([...examples])('example: $name', async (example) => {
181
- const testCtx = mergeTestContext(resolveCtx());
182
- await runExample(t, example, output, testCtx);
139
+ const allTrails = app.list();
140
+ const withExamples = allTrails.filter((t) => t.examples !== undefined && t.examples.length > 0);
141
+ const simpleTrails = withExamples.filter((t) => t.follow.length === 0);
142
+ const compositionTrails = withExamples.filter((t) => t.follow.length > 0);
143
+ // Simple trails: run examples directly
144
+ if (simpleTrails.length > 0) {
145
+ describe.each(simpleTrails)('$id', (t) => {
146
+ const { examples, output } = t;
147
+ if (!examples) {
148
+ return;
149
+ }
150
+ test.each([...examples])('example: $name', async (example) => {
151
+ const testCtx = mergeTestContext(resolveCtx());
152
+ await runExample(t, example, output, testCtx);
153
+ });
183
154
  });
184
- });
185
- describeHikeExamples(collectHikesWithExamples(app), resolveCtx, app);
155
+ }
156
+ // Composition trails: use recording follow and check coverage
157
+ if (compositionTrails.length > 0) {
158
+ describe.each(compositionTrails)('$id', (t) => {
159
+ const { examples, output } = t;
160
+ if (!examples) {
161
+ return;
162
+ }
163
+ const called = new Set();
164
+ test.each([...examples])('example: $name', async (example) => {
165
+ const baseCtx = mergeTestContext(resolveCtx());
166
+ await runCompositionExample(t, example, output, baseCtx, called, app);
167
+ });
168
+ test('follow coverage', () => {
169
+ const uncovered = t.follow.filter((id) => !called.has(id));
170
+ expect(uncovered).toEqual([]);
171
+ });
172
+ });
173
+ }
186
174
  };
187
175
  //# sourceMappingURL=examples.js.map
@@ -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,MAAM,EACN,YAAY,EACZ,WAAW,EACX,eAAe,EACf,aAAa,GACd,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,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,EACN,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;IACD,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,cAAc,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IAC/D,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC,CAAC;AAEF,8EAA8E;AAC9E,6BAA6B;AAC7B,8EAA8E;AAE9E;;;;;;GAMG;AACH,MAAM,oBAAoB,GAAG,CAC3B,MAAmB,EACnB,UAAgC,EAChC,IAAU,EACV,GAAiB,EACP,EAAE;IACZ,MAAM,MAAM,GAAG,CAAC,EAAU,EAAE,KAAc,EAAE,EAAE;QAC5C,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEf,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,OAAO,UAAU,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,MAAM,SAAS,GAAG,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACvD,IAAI,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;gBACtB,OAAO,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACpC,CAAC;YACD,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC;IACF,OAAO,MAAkB,CAAC;AAC5B,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,cAAc,GAAG,KAAK,EAC1B,OAAgB,EAChB,OAAuC,EACvC,MAA6B,EAC7B,OAAqB,EACrB,MAAmB,EACnB,IAAU,EACK,EAAE;IACjB,MAAM,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAE9D,IAAI,qBAAqB,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IACD,MAAM,cAAc,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAE3C,MAAM,MAAM,GAAG,oBAAoB,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,OAAO,GAAiB,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,CAAC;IAErD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;IACrE,sBAAsB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAClD,CAAC,CAAC;AAYF,MAAM,wBAAwB,GAAG,CAAC,GAAS,EAA+B,EAAE,CAC1E,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;KACX,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;KACpE,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC,QAAqD;IACvE,OAAO;IACP,MAAM;CACP,CAAC,CAAC,CAAC;AAER,8EAA8E;AAC9E,+BAA+B;AAC/B,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,oBAAoB,GAAG,CAC3B,iBAA8C,EAC9C,UAAmD,EACnD,IAAU,EACJ,EAAE;IACR,IAAI,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO;IACT,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;QACzE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAU,CAAC;QAEjC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CACtB,gBAAgB,EAChB,KAAK,EAAE,OAAuC,EAAE,EAAE;YAChD,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/C,MAAM,cAAc,CAClB,OAAO,EACP,OAAO,EACP,OAAO,CAAC,MAAM,EACd,OAAO,EACP,MAAM,EACN,IAAI,CACL,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE;gBAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;gBAClE,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,8EAA8E;AAC9E,eAAe;AACf,8EAA8E;AAE9E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,GAAS,EACT,YAAoE,EAC9D,EAAE;IACR,MAAM,UAAU,GACd,OAAO,YAAY,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC;IACzE,MAAM,YAAY,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IAErC,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE;QAClD,MAAM,CAAC,GAAG,QAAmC,CAAC;QAC9C,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO;QACT,CAAC;QAED,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QAE/B,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CACtB,gBAAgB,EAChB,KAAK,EAAE,OAAuC,EAAE,EAAE;YAChD,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/C,MAAM,UAAU,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAChD,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,oBAAoB,CAAC,wBAAwB,CAAC,GAAG,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;AACvE,CAAC,CAAC"}
1
+ {"version":3,"file":"examples.js","sourceRoot":"","sources":["../src/examples.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
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, 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
+ /** Map of trail ID to trail definition, used for injectFromExample. */
14
+ readonly trails?: ReadonlyMap<string, AnyTrail> | undefined;
15
+ }
16
+ /**
17
+ * Generate a describe block for a composition trail with one test per scenario.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * testFollows(onboardTrail, [
22
+ * {
23
+ * description: "follows add then relate",
24
+ * input: { name: "Alpha" },
25
+ * expectOk: true,
26
+ * expectFollowed: ["entity.add", "entity.relate"],
27
+ * },
28
+ * ]);
29
+ * ```
30
+ */
31
+ export declare const testFollows: (trailDef: AnyTrail, scenarios: readonly FollowScenario[], options?: TestFollowOptions) => void;
32
+ //# sourceMappingURL=follows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"follows.d.ts","sourceRoot":"","sources":["../src/follows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAY,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAevE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA8NjD,4EAA4E;AAC5E,MAAM,WAAW,iBAAiB;IAChC,iCAAiC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,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,IASF,CAAC"}