@ontrails/testing 1.0.0-beta.13 → 1.0.0-beta.15

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 (83) hide show
  1. package/.turbo/turbo-lint.log +1 -1
  2. package/CHANGELOG.md +28 -0
  3. package/README.md +11 -11
  4. package/dist/all.d.ts +10 -5
  5. package/dist/all.d.ts.map +1 -1
  6. package/dist/all.js +78 -26
  7. package/dist/all.js.map +1 -1
  8. package/dist/assertions.d.ts +23 -0
  9. package/dist/assertions.d.ts.map +1 -1
  10. package/dist/assertions.js +154 -0
  11. package/dist/assertions.js.map +1 -1
  12. package/dist/context.d.ts +17 -16
  13. package/dist/context.d.ts.map +1 -1
  14. package/dist/context.js +31 -20
  15. package/dist/context.js.map +1 -1
  16. package/dist/contracts.d.ts.map +1 -1
  17. package/dist/contracts.js +9 -5
  18. package/dist/contracts.js.map +1 -1
  19. package/dist/crosses.d.ts +4 -4
  20. package/dist/crosses.d.ts.map +1 -1
  21. package/dist/crosses.js +49 -39
  22. package/dist/crosses.js.map +1 -1
  23. package/dist/detours.d.ts +5 -4
  24. package/dist/detours.d.ts.map +1 -1
  25. package/dist/detours.js +93 -14
  26. package/dist/detours.js.map +1 -1
  27. package/dist/effective-examples.d.ts +30 -0
  28. package/dist/effective-examples.d.ts.map +1 -0
  29. package/dist/effective-examples.js +227 -0
  30. package/dist/effective-examples.js.map +1 -0
  31. package/dist/examples.d.ts +1 -1
  32. package/dist/examples.d.ts.map +1 -1
  33. package/dist/examples.js +79 -41
  34. package/dist/examples.js.map +1 -1
  35. package/dist/harness-cli.d.ts +3 -3
  36. package/dist/harness-cli.d.ts.map +1 -1
  37. package/dist/harness-cli.js +25 -33
  38. package/dist/harness-cli.js.map +1 -1
  39. package/dist/harness-mcp.d.ts +3 -3
  40. package/dist/harness-mcp.d.ts.map +1 -1
  41. package/dist/harness-mcp.js +9 -8
  42. package/dist/harness-mcp.js.map +1 -1
  43. package/dist/index.d.ts +6 -4
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +5 -2
  46. package/dist/index.js.map +1 -1
  47. package/dist/scenario.d.ts +37 -0
  48. package/dist/scenario.d.ts.map +1 -0
  49. package/dist/scenario.js +235 -0
  50. package/dist/scenario.js.map +1 -0
  51. package/dist/types.d.ts +38 -5
  52. package/dist/types.d.ts.map +1 -1
  53. package/package.json +9 -5
  54. package/src/__tests__/all.test.ts +217 -29
  55. package/src/__tests__/context.test.ts +32 -12
  56. package/src/__tests__/contracts.test.ts +72 -18
  57. package/src/__tests__/crosses.test.ts +78 -78
  58. package/src/__tests__/detours.test.ts +176 -19
  59. package/src/__tests__/effective-examples.test.ts +203 -0
  60. package/src/__tests__/examples.test.ts +152 -50
  61. package/src/__tests__/harness-cli.test.ts +90 -0
  62. package/src/__tests__/harness-mcp.test.ts +37 -0
  63. package/src/__tests__/partial-match.test.ts +126 -0
  64. package/src/__tests__/scenario.test.ts +381 -0
  65. package/src/all.ts +149 -12
  66. package/src/assertions.ts +253 -0
  67. package/src/context.ts +64 -38
  68. package/src/contracts.ts +14 -8
  69. package/src/crosses.ts +93 -51
  70. package/src/detours.ts +155 -18
  71. package/src/effective-examples.ts +350 -0
  72. package/src/examples.ts +127 -59
  73. package/src/harness-cli.ts +33 -49
  74. package/src/harness-mcp.ts +9 -8
  75. package/src/index.ts +13 -3
  76. package/src/scenario.ts +370 -0
  77. package/src/types.ts +63 -5
  78. package/tsconfig.tests.json +10 -0
  79. package/tsconfig.tsbuildinfo +1 -1
  80. package/dist/follows.d.ts +0 -38
  81. package/dist/follows.d.ts.map +0 -1
  82. package/dist/follows.js +0 -212
  83. package/dist/follows.js.map +0 -1
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * CLI integration test harness.
3
3
  *
4
- * Builds CLI commands from an App, executes them in-process,
4
+ * Builds CLI commands from a graph, executes them in-process,
5
5
  * and captures stdout/stderr.
6
6
  */
7
- import { buildCliCommands } from '@ontrails/cli';
8
- import { createTestContext } from './context.js';
7
+ import { deriveCliCommands } from '@ontrails/cli';
8
+ import { mergeTestContext } from './context.js';
9
9
  // ---------------------------------------------------------------------------
10
10
  // Tokenizer
11
11
  // ---------------------------------------------------------------------------
@@ -17,33 +17,20 @@ const parseCommandString = (input) => input
17
17
  // ---------------------------------------------------------------------------
18
18
  // Command resolution
19
19
  // ---------------------------------------------------------------------------
20
- /** Try to match group + name from tokens. */
21
- const tryGroupMatch = (commands, firstToken, secondToken, tokens) => {
22
- if (secondToken === undefined || secondToken.startsWith('-')) {
23
- return undefined;
24
- }
25
- const match = commands.find((c) => c.group === firstToken && c.name === secondToken);
26
- if (match === undefined) {
20
+ const matchesPath = (path, tokens) => path.length <= tokens.length &&
21
+ path.every((segment, index) => tokens[index] === segment);
22
+ /** Resolve a command from tokens using the longest matching command path. */
23
+ const resolveCommand = (commands, tokens) => {
24
+ if (tokens.length === 0) {
27
25
  return undefined;
28
26
  }
29
- return { command: match, flagTokens: tokens.slice(2) };
30
- };
31
- /** Try to match a direct name from the first token. */
32
- const tryDirectMatch = (commands, firstToken, tokens) => {
33
- const match = commands.find((c) => c.name === firstToken && c.group === undefined);
27
+ const [match] = commands
28
+ .filter((command) => matchesPath(command.path, tokens))
29
+ .toSorted((a, b) => b.path.length - a.path.length);
34
30
  if (match === undefined) {
35
31
  return undefined;
36
32
  }
37
- return { command: match, flagTokens: tokens.slice(1) };
38
- };
39
- /** Resolve a command from tokens, handling group.name patterns. */
40
- const resolveCommand = (commands, tokens) => {
41
- const [firstToken, secondToken] = tokens;
42
- if (firstToken === undefined) {
43
- return undefined;
44
- }
45
- return (tryGroupMatch(commands, firstToken, secondToken, tokens) ??
46
- tryDirectMatch(commands, firstToken, tokens));
33
+ return { command: match, flagTokens: tokens.slice(match.path.length) };
47
34
  };
48
35
  // ---------------------------------------------------------------------------
49
36
  // Flag parsing
@@ -155,8 +142,8 @@ const buildErrorResult = (error, streams) => {
155
142
  };
156
143
  };
157
144
  /** Execute a resolved command and return the result. */
158
- const executeCommand = async (command, flags, streams) => {
159
- const ctx = createTestContext();
145
+ const executeCommand = async (command, flags, streams, ctxOverrides) => {
146
+ const ctx = mergeTestContext(ctxOverrides);
160
147
  const result = await command.execute({}, flags, ctx);
161
148
  streams.restore();
162
149
  if (result.isErr()) {
@@ -169,7 +156,7 @@ const executeCommand = async (command, flags, streams) => {
169
156
  return formatSuccessResult(result.value, flags, streams);
170
157
  };
171
158
  /** Run the full command pipeline: resolve, parse, execute. */
172
- const runCommand = async (commands, commandString) => {
159
+ const runCommand = async (commands, commandString, ctxOverrides) => {
173
160
  const parts = parseCommandString(commandString);
174
161
  const resolved = resolveCommand(commands, parts);
175
162
  if (resolved === undefined) {
@@ -183,7 +170,7 @@ const runCommand = async (commands, commandString) => {
183
170
  const flags = parseFlagTokens(flagTokens);
184
171
  const streams = captureStreams();
185
172
  try {
186
- return await executeCommand(command, flags, streams);
173
+ return await executeCommand(command, flags, streams, ctxOverrides);
187
174
  }
188
175
  catch (error) {
189
176
  return buildErrorResult(error, streams);
@@ -195,19 +182,24 @@ const runCommand = async (commands, commandString) => {
195
182
  /**
196
183
  * Create a CLI harness for integration testing.
197
184
  *
198
- * Builds commands from the app's topo and provides a `run()` method
185
+ * Builds commands from the graph's topo and provides a `run()` method
199
186
  * that parses command strings and executes them in-process.
200
187
  *
201
188
  * ```ts
202
- * const harness = createCliHarness({ app });
189
+ * const harness = createCliHarness({ graph });
203
190
  * const result = await harness.run("entity show --name Alpha --output json");
204
191
  * expect(result.exitCode).toBe(0);
205
192
  * ```
206
193
  */
207
194
  export const createCliHarness = (options) => {
208
- const commands = buildCliCommands(options.app);
195
+ const { ctx, graph, ...deriveOptions } = options;
196
+ const commandsResult = deriveCliCommands(graph, deriveOptions);
197
+ if (commandsResult.isErr()) {
198
+ throw commandsResult.error;
199
+ }
200
+ const commands = commandsResult.value;
209
201
  return {
210
- run: (commandString) => runCommand(commands, commandString),
202
+ run: (commandString) => runCommand(commands, commandString, ctx),
211
203
  };
212
204
  };
213
205
  //# sourceMappingURL=harness-cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"harness-cli.js","sourceRoot":"","sources":["../src/harness-cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness-cli.js","sourceRoot":"","sources":["../src/harness-cli.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * MCP integration test harness.
3
3
  *
4
- * Builds MCP tools from an App, invokes them directly (no transport),
4
+ * Builds MCP tools from a graph, invokes them directly (no transport),
5
5
  * and returns the MCP tool response.
6
6
  */
7
7
  import type { McpHarness, McpHarnessOptions } from './types.js';
8
8
  /**
9
9
  * Create an MCP harness for integration testing.
10
10
  *
11
- * Builds MCP tools from the app's topo and provides a `callTool()` method
11
+ * Builds MCP tools from the graph's topo and provides a `callTool()` method
12
12
  * that invokes tools directly without any transport boundary.
13
13
  *
14
14
  * ```ts
15
- * const harness = createMcpHarness({ app });
15
+ * const harness = createMcpHarness({ graph });
16
16
  * const result = await harness.callTool("myapp_entity_show", { name: "Alpha" });
17
17
  * expect(result.isError).toBe(false);
18
18
  * ```
@@ -1 +1 @@
1
- {"version":3,"file":"harness-mcp.d.ts","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,iBAAiB,KAAG,UAmC7D,CAAC"}
1
+ {"version":3,"file":"harness-mcp.d.ts","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EAElB,MAAM,YAAY,CAAC;AAMpB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,GAAI,SAAS,iBAAiB,KAAG,UAoC7D,CAAC"}
@@ -1,27 +1,28 @@
1
1
  /**
2
2
  * MCP integration test harness.
3
3
  *
4
- * Builds MCP tools from an App, invokes them directly (no transport),
4
+ * Builds MCP tools from a graph, invokes them directly (no transport),
5
5
  * and returns the MCP tool response.
6
6
  */
7
- import { buildMcpTools } from '@ontrails/mcp';
7
+ import { deriveMcpTools } from '@ontrails/mcp';
8
8
  // ---------------------------------------------------------------------------
9
9
  // createMcpHarness
10
10
  // ---------------------------------------------------------------------------
11
11
  /**
12
12
  * Create an MCP harness for integration testing.
13
13
  *
14
- * Builds MCP tools from the app's topo and provides a `callTool()` method
14
+ * Builds MCP tools from the graph's topo and provides a `callTool()` method
15
15
  * that invokes tools directly without any transport boundary.
16
16
  *
17
17
  * ```ts
18
- * const harness = createMcpHarness({ app });
18
+ * const harness = createMcpHarness({ graph });
19
19
  * const result = await harness.callTool("myapp_entity_show", { name: "Alpha" });
20
20
  * expect(result.isError).toBe(false);
21
21
  * ```
22
22
  */
23
23
  export const createMcpHarness = (options) => {
24
- const toolsResult = buildMcpTools(options.app);
24
+ const { extra, graph, ...deriveOptions } = options;
25
+ const toolsResult = deriveMcpTools(graph, deriveOptions);
25
26
  if (toolsResult.isErr()) {
26
27
  throw toolsResult.error;
27
28
  }
@@ -39,9 +40,9 @@ export const createMcpHarness = (options) => {
39
40
  };
40
41
  }
41
42
  const result = await tool.handler(args, {
42
- abortSignal: undefined,
43
- progressToken: undefined,
44
- sendProgress: undefined,
43
+ abortSignal: extra?.abortSignal,
44
+ progressToken: extra?.progressToken,
45
+ sendProgress: extra?.sendProgress,
45
46
  });
46
47
  return {
47
48
  content: result.content,
@@ -1 +1 @@
1
- {"version":3,"file":"harness-mcp.js","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAS9C,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA0B,EAAc,EAAE;IACzE,MAAM,WAAW,GAAG,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,WAAW,CAAC,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,IAA6B;YAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oBAC1D,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;gBACtC,WAAW,EAAE,SAAS;gBACtB,aAAa,EAAE,SAAS;gBACxB,YAAY,EAAE,SAAS;aACxB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;aACjC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"harness-mcp.js","sourceRoot":"","sources":["../src/harness-mcp.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAS/C,8EAA8E;AAC9E,mBAAmB;AACnB,8EAA8E;AAE9E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAA0B,EAAc,EAAE;IACzE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,aAAa,EAAE,GAAG,OAAO,CAAC;IACnD,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;IACzD,IAAI,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,MAAM,WAAW,CAAC,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA6B,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO;QACL,KAAK,CAAC,QAAQ,CACZ,IAAY,EACZ,IAA6B;YAE7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;oBAC1D,OAAO,EAAE,IAAI;iBACd,CAAC;YACJ,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;gBACtC,WAAW,EAAE,KAAK,EAAE,WAAW;gBAC/B,aAAa,EAAE,KAAK,EAAE,aAAa;gBACnC,YAAY,EAAE,KAAK,EAAE,YAAY;aAClC,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,KAAK;aACjC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,16 +1,18 @@
1
1
  export { testAll } from './all.js';
2
+ export { testAllEstablished } from './all.js';
2
3
  export { testExamples } from './examples.js';
3
4
  export { testCrosses } from './crosses.js';
4
5
  export { testTrail } from './trail.js';
5
6
  export { testContracts } from './contracts.js';
6
7
  export { testDetours } from './detours.js';
7
- export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
8
- export { createCrossContext, createTestContext, defaultMintPermit, } from './context.js';
8
+ export { assertErrorMatch, assertFullMatch, assertPartialMatch, assertSchemaMatch, errResultMatch, expectErr, expectOk, okResultMatch, } from './assertions.js';
9
+ export { executeScenarioSteps, ref, scenario } from './scenario.js';
10
+ export { createCrossContext, createTestContext, defaultCreatePermit, } from './context.js';
9
11
  export { createTestLogger } from './logger.js';
10
12
  export { createCliHarness } from './harness-cli.js';
11
13
  export { createMcpHarness } from './harness-mcp.js';
12
14
  export type { CreateCrossContextOptions } from './context.js';
13
- export type { MintableTrail, MintedPermit, TestExecutionOptions, } from './context.js';
15
+ export type { PermittedTrail, MinimalPermit, TestExecutionOptions, } from './context.js';
14
16
  export type { TestCrossOptions } from './crosses.js';
15
- export type { CrossScenario, TestScenario, TestLogger, TestTrailContextOptions, CliHarness, CliHarnessOptions, CliHarnessResult, McpHarness, McpHarnessOptions, McpHarnessResult, } from './types.js';
17
+ export type { CrossScenario, RefToken, ScenarioStep, TestAllEstablishedOptions, TestScenario, TestLogger, TestTrailContextOptions, CliHarness, CliHarnessOptions, CliHarnessResult, McpHarness, McpHarnessOptions, McpHarnessResult, } from './types.js';
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -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,EACL,kBAAkB,EAClB,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,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EACV,aAAa,EACb,YAAY,EACZ,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,YAAY,EACV,aAAa,EACb,YAAY,EACZ,UAAU,EACV,uBAAuB,EACvB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
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,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,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,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,QAAQ,EACR,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,oBAAoB,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpE,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACpB,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,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAC9D,YAAY,EACV,cAAc,EACd,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,YAAY,EACV,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,yBAAyB,EACzB,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
@@ -1,14 +1,17 @@
1
1
  // Contract-driven testing
2
2
  export { testAll } from './all.js';
3
+ export { testAllEstablished } from './all.js';
3
4
  export { testExamples } from './examples.js';
4
5
  export { testCrosses } from './crosses.js';
5
6
  export { testTrail } from './trail.js';
6
7
  export { testContracts } from './contracts.js';
7
8
  export { testDetours } from './detours.js';
8
9
  // Assertions
9
- export { assertErrorMatch, assertFullMatch, assertSchemaMatch, expectErr, expectOk, } from './assertions.js';
10
+ export { assertErrorMatch, assertFullMatch, assertPartialMatch, assertSchemaMatch, errResultMatch, expectErr, expectOk, okResultMatch, } from './assertions.js';
11
+ // Scenario testing
12
+ export { executeScenarioSteps, ref, scenario } from './scenario.js';
10
13
  // Mock factories
11
- export { createCrossContext, createTestContext, defaultMintPermit, } from './context.js';
14
+ export { createCrossContext, createTestContext, defaultCreatePermit, } from './context.js';
12
15
  export { createTestLogger } from './logger.js';
13
16
  // Trailhead harnesses
14
17
  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,EACL,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,sBAAsB;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
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,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,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,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,QAAQ,EACR,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,mBAAmB;AACnB,OAAO,EAAE,oBAAoB,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpE,iBAAiB;AACjB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,sBAAsB;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Multi-step scenario runner for composition testing.
3
+ *
4
+ * Scenarios express multi-trail flows as structured data — arrays of steps
5
+ * with cross-step references via `ref()`. Each step invokes a trail through
6
+ * the normal execution pipeline (validation, layers, blaze, Result).
7
+ */
8
+ import type { Topo } from '@ontrails/core';
9
+ import type { RefToken, ScenarioStep } from './types.js';
10
+ /**
11
+ * Create a reference marker for cross-step data in scenario inputs.
12
+ *
13
+ * `ref('create.id')` resolves to the `id` field of the step aliased as
14
+ * `create`. Dot-paths are supported for nested access.
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * scenario('Fork flow', app, [
19
+ * { cross: createGist, input: { name: 'Hello' }, as: 'original' },
20
+ * { cross: forkGist, input: { id: ref('original.id') } },
21
+ * ]);
22
+ * ```
23
+ */
24
+ export declare const ref: (path: string) => RefToken;
25
+ /**
26
+ * Recursively walk a value, replacing RefToken instances with resolved values.
27
+ */
28
+ export declare const deriveRefs: (value: unknown, outputs: Map<string, unknown>) => unknown;
29
+ /**
30
+ * Execute scenario steps sequentially, resolving mock resources once upfront.
31
+ *
32
+ * Exported for direct use in tests that need to assert on step execution
33
+ * without the describe/test wrapper that `scenario()` provides.
34
+ */
35
+ export declare const executeScenarioSteps: (app: Topo, steps: readonly ScenarioStep[]) => Promise<void>;
36
+ export declare const scenario: (name: string, app: Topo, steps: readonly ScenarioStep[]) => void;
37
+ //# sourceMappingURL=scenario.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAMV,IAAI,EACL,MAAM,gBAAgB,CAAC;AAexB,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AASzD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,GAAG,GAAI,MAAM,MAAM,KAAG,QAAmC,CAAC;AA6DvE;;GAEG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,OAAO,EACd,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAkBF,CAAC;AAyMF;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,KAAK,IAAI,EACT,OAAO,SAAS,YAAY,EAAE,KAC7B,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,eAAO,MAAM,QAAQ,GACnB,MAAM,MAAM,EACZ,KAAK,IAAI,EACT,OAAO,SAAS,YAAY,EAAE,KAC7B,IAMF,CAAC"}
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Multi-step scenario runner for composition testing.
3
+ *
4
+ * Scenarios express multi-trail flows as structured data — arrays of steps
5
+ * with cross-step references via `ref()`. Each step invokes a trail through
6
+ * the normal execution pipeline (validation, layers, blaze, Result).
7
+ */
8
+ import { describe, test } from 'bun:test';
9
+ import { buildCrossValidationSchema, executeTrail, InternalError, Result as R, } from '@ontrails/core';
10
+ import { claimNextCrossBatchIndex, createCrossBatchValidationResults, normalizeCrossBatchConcurrency, } from '@ontrails/core/internal/cross-batch';
11
+ import { assertPartialMatch, expectOk } from './assertions.js';
12
+ import { createTestContext, createMockResources } from './context.js';
13
+ // ---------------------------------------------------------------------------
14
+ // ref() — cross-step reference marker
15
+ // ---------------------------------------------------------------------------
16
+ /**
17
+ * Create a reference marker for cross-step data in scenario inputs.
18
+ *
19
+ * `ref('create.id')` resolves to the `id` field of the step aliased as
20
+ * `create`. Dot-paths are supported for nested access.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * scenario('Fork flow', app, [
25
+ * { cross: createGist, input: { name: 'Hello' }, as: 'original' },
26
+ * { cross: forkGist, input: { id: ref('original.id') } },
27
+ * ]);
28
+ * ```
29
+ */
30
+ export const ref = (path) => ({ __ref: true, path });
31
+ // ---------------------------------------------------------------------------
32
+ // Internals
33
+ // ---------------------------------------------------------------------------
34
+ /** Type guard for RefToken. */
35
+ const isRef = (value) => typeof value === 'object' &&
36
+ value !== null &&
37
+ '__ref' in value &&
38
+ value['__ref'] === true &&
39
+ 'path' in value;
40
+ /**
41
+ * Resolve a dot-path against the outputs map.
42
+ *
43
+ * `ref('create.id')` splits into step name `create` and field path `id`.
44
+ * The first segment is the step alias; remaining segments are property lookups.
45
+ */
46
+ /**
47
+ * Walk remaining segments of a dot-path, drilling into the step output.
48
+ */
49
+ const drillPath = (path, segments, start) => {
50
+ let current = start;
51
+ for (let i = 1; i < segments.length; i += 1) {
52
+ const segment = segments[i];
53
+ if (segment === undefined) {
54
+ break;
55
+ }
56
+ if (typeof current !== 'object' || current === null) {
57
+ throw new Error(`ref('${path}'): cannot access '${segment}' on ${typeof current}`);
58
+ }
59
+ current = current[segment];
60
+ }
61
+ return current;
62
+ };
63
+ const resolvePath = (path, outputs) => {
64
+ const segments = path.split('.');
65
+ const [stepName] = segments;
66
+ if (stepName === undefined) {
67
+ throw new Error(`ref(): empty path`);
68
+ }
69
+ const stepOutput = outputs.get(stepName);
70
+ if (stepOutput === undefined) {
71
+ throw new Error(`ref('${path}'): no step output found for alias '${stepName}'`);
72
+ }
73
+ return drillPath(path, segments, stepOutput);
74
+ };
75
+ /**
76
+ * Recursively walk a value, replacing RefToken instances with resolved values.
77
+ */
78
+ export const deriveRefs = (value, outputs) => {
79
+ if (isRef(value)) {
80
+ return resolvePath(value.path, outputs);
81
+ }
82
+ if (Array.isArray(value)) {
83
+ return value.map((item) => deriveRefs(item, outputs));
84
+ }
85
+ if (typeof value === 'object' && value !== null) {
86
+ const result = {};
87
+ for (const [key, val] of Object.entries(value)) {
88
+ result[key] = deriveRefs(val, outputs);
89
+ }
90
+ return result;
91
+ }
92
+ return value;
93
+ };
94
+ // ---------------------------------------------------------------------------
95
+ // scenario() — the public API
96
+ // ---------------------------------------------------------------------------
97
+ /**
98
+ * Define a multi-step scenario test for composition flows.
99
+ *
100
+ * Each step invokes a trail through the normal execution pipeline.
101
+ * Steps can reference prior step outputs via `ref()`. If any step
102
+ * fails, the scenario stops and reports which step failed.
103
+ *
104
+ * @example
105
+ * ```typescript
106
+ * scenario('Create and show', app, [
107
+ * { cross: createItem, input: { name: 'Test' }, as: 'created' },
108
+ * { cross: showItem, input: { id: ref('created.id') },
109
+ * expectedMatch: { found: true } },
110
+ * ]);
111
+ * ```
112
+ */
113
+ /** Assert the result of a step against its expectations and record output. */
114
+ const assertStepExpectations = async (step, result, outputs) => {
115
+ const value = expectOk(result);
116
+ if (step.expected !== undefined) {
117
+ const { expect } = await import('bun:test');
118
+ expect(value).toEqual(deriveRefs(step.expected, outputs));
119
+ }
120
+ else if (step.expectedMatch !== undefined) {
121
+ assertPartialMatch(result, deriveRefs(step.expectedMatch, outputs));
122
+ }
123
+ if (step.as !== undefined) {
124
+ outputs.set(step.as, value);
125
+ }
126
+ };
127
+ const executeUnlimitedCrossBatch = async (calls, runCall) => await Promise.all(calls.map((call, branchIndex) => runCall(call, branchIndex)));
128
+ const executeLimitedCrossBatch = async (calls, runCall, limit) => {
129
+ const results = Array.from({ length: calls.length });
130
+ const nextIndex = { value: 0 };
131
+ const runWorker = async () => {
132
+ while (true) {
133
+ const branchIndex = claimNextCrossBatchIndex(nextIndex, calls);
134
+ if (branchIndex === undefined) {
135
+ return;
136
+ }
137
+ const call = calls[branchIndex];
138
+ if (call === undefined) {
139
+ // Defensive: `claimNextCrossBatchIndex` only returns indices within
140
+ // bounds, so this slot should always be populated. If it ever isn't,
141
+ // surface a clear InternalError in place of the missing slot and keep
142
+ // the worker loop running so sibling branches still get processed.
143
+ results[branchIndex] = R.err(new InternalError(`unreachable: concurrent cross batch call missing at index ${branchIndex}`));
144
+ continue;
145
+ }
146
+ results[branchIndex] = await runCall(call, branchIndex);
147
+ }
148
+ };
149
+ await Promise.all(Array.from({ length: limit }, runWorker));
150
+ return results;
151
+ };
152
+ /**
153
+ * Build a cross function that resolves trails from the topo and executes
154
+ * them through the standard pipeline. Mirrors the pattern in crosses.ts
155
+ * `executeFromMap` but without recording or injection.
156
+ */
157
+ const createScenarioCross = (app, resources) => {
158
+ const invokeCross = async (idOrTrail, input, self) => {
159
+ const id = typeof idOrTrail === 'string' ? idOrTrail : idOrTrail.id;
160
+ const trailDef = app.get(id);
161
+ if (trailDef === undefined) {
162
+ return R.err(new InternalError(`cross: trail "${id}" not found in topo`));
163
+ }
164
+ const baseCtx = createTestContext();
165
+ return await executeTrail(trailDef, input, {
166
+ ctx: { ...baseCtx, cross: self },
167
+ resources,
168
+ topo: app,
169
+ validationSchema: buildCrossValidationSchema(trailDef),
170
+ });
171
+ };
172
+ const executeCrossBatch = async (calls, self, options) => {
173
+ if (calls.length === 0) {
174
+ return [];
175
+ }
176
+ const concurrency = normalizeCrossBatchConcurrency(options);
177
+ if (concurrency.isErr()) {
178
+ return createCrossBatchValidationResults(calls, concurrency.error);
179
+ }
180
+ const runCall = async ([target, batchInput], _branchIndex) => await invokeCross(target, batchInput, self);
181
+ const limit = concurrency.value ?? calls.length;
182
+ return limit >= calls.length
183
+ ? await executeUnlimitedCrossBatch(calls, runCall)
184
+ : await executeLimitedCrossBatch(calls, runCall, limit);
185
+ };
186
+ const cross = async function cross(idOrTrail, inputOrOptions) {
187
+ if (Array.isArray(idOrTrail)) {
188
+ return await executeCrossBatch(idOrTrail, cross, inputOrOptions);
189
+ }
190
+ return await invokeCross(idOrTrail, inputOrOptions, cross);
191
+ };
192
+ return cross;
193
+ };
194
+ /**
195
+ * Execute a single scenario step: run the trail, assert expectations,
196
+ * and record outputs.
197
+ */
198
+ const executeStep = async (step, index, app, outputs, resources) => {
199
+ if (step.as !== undefined && outputs.has(step.as)) {
200
+ throw new Error(`scenario: duplicate step alias "${step.as}" — each alias must be unique`);
201
+ }
202
+ const scenarioCross = createScenarioCross(app, resources);
203
+ const baseCtx = createTestContext();
204
+ const resolvedInput = deriveRefs(step.input, outputs);
205
+ const result = await executeTrail(step.cross, resolvedInput, {
206
+ ctx: { ...baseCtx, cross: scenarioCross },
207
+ resources,
208
+ topo: app,
209
+ });
210
+ if (result.isErr()) {
211
+ throw new Error(`Step ${String(index + 1)} ("${step.as ?? step.cross.id}") failed: ${result.error.message}`);
212
+ }
213
+ await assertStepExpectations(step, result, outputs);
214
+ };
215
+ /**
216
+ * Execute scenario steps sequentially, resolving mock resources once upfront.
217
+ *
218
+ * Exported for direct use in tests that need to assert on step execution
219
+ * without the describe/test wrapper that `scenario()` provides.
220
+ */
221
+ export const executeScenarioSteps = async (app, steps) => {
222
+ const outputs = new Map();
223
+ const resources = await createMockResources(app);
224
+ for (const [index, step] of steps.entries()) {
225
+ await executeStep(step, index, app, outputs, resources);
226
+ }
227
+ };
228
+ export const scenario = (name, app, steps) => {
229
+ describe(name, () => {
230
+ test('executes all steps', async () => {
231
+ await executeScenarioSteps(app, steps);
232
+ });
233
+ });
234
+ };
235
+ //# sourceMappingURL=scenario.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../src/scenario.ts"],"names":[],"mappings":"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"}