@ontrails/testing 1.0.0-beta.15 → 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 (91) hide show
  1. package/CHANGELOG.md +56 -1
  2. package/README.md +2 -2
  3. package/package.json +15 -7
  4. package/src/all.ts +7 -7
  5. package/src/context.ts +3 -0
  6. package/src/contracts.ts +1 -16
  7. package/src/examples.ts +19 -11
  8. package/src/index.ts +1 -1
  9. package/src/logger.ts +3 -1
  10. package/src/scenario.ts +3 -5
  11. package/src/signals.ts +221 -0
  12. package/src/types.ts +1 -1
  13. package/.turbo/turbo-build.log +0 -1
  14. package/.turbo/turbo-lint.log +0 -3
  15. package/.turbo/turbo-typecheck.log +0 -1
  16. package/dist/all.d.ts +0 -36
  17. package/dist/all.d.ts.map +0 -1
  18. package/dist/all.js +0 -99
  19. package/dist/all.js.map +0 -1
  20. package/dist/assertions.d.ts +0 -72
  21. package/dist/assertions.d.ts.map +0 -1
  22. package/dist/assertions.js +0 -238
  23. package/dist/assertions.js.map +0 -1
  24. package/dist/context.d.ts +0 -76
  25. package/dist/context.d.ts.map +0 -1
  26. package/dist/context.js +0 -118
  27. package/dist/context.js.map +0 -1
  28. package/dist/contracts.d.ts +0 -17
  29. package/dist/contracts.d.ts.map +0 -1
  30. package/dist/contracts.js +0 -75
  31. package/dist/contracts.js.map +0 -1
  32. package/dist/crosses.d.ts +0 -38
  33. package/dist/crosses.d.ts.map +0 -1
  34. package/dist/crosses.js +0 -223
  35. package/dist/crosses.js.map +0 -1
  36. package/dist/detours.d.ts +0 -13
  37. package/dist/detours.d.ts.map +0 -1
  38. package/dist/detours.js +0 -109
  39. package/dist/detours.js.map +0 -1
  40. package/dist/effective-examples.d.ts +0 -30
  41. package/dist/effective-examples.d.ts.map +0 -1
  42. package/dist/effective-examples.js +0 -227
  43. package/dist/effective-examples.js.map +0 -1
  44. package/dist/examples.d.ts +0 -23
  45. package/dist/examples.d.ts.map +0 -1
  46. package/dist/examples.js +0 -240
  47. package/dist/examples.js.map +0 -1
  48. package/dist/harness-cli.d.ts +0 -21
  49. package/dist/harness-cli.d.ts.map +0 -1
  50. package/dist/harness-cli.js +0 -205
  51. package/dist/harness-cli.js.map +0 -1
  52. package/dist/harness-mcp.d.ts +0 -21
  53. package/dist/harness-mcp.d.ts.map +0 -1
  54. package/dist/harness-mcp.js +0 -54
  55. package/dist/harness-mcp.js.map +0 -1
  56. package/dist/index.d.ts +0 -18
  57. package/dist/index.d.ts.map +0 -1
  58. package/dist/index.js +0 -19
  59. package/dist/index.js.map +0 -1
  60. package/dist/logger.d.ts +0 -15
  61. package/dist/logger.d.ts.map +0 -1
  62. package/dist/logger.js +0 -87
  63. package/dist/logger.js.map +0 -1
  64. package/dist/scenario.d.ts +0 -37
  65. package/dist/scenario.d.ts.map +0 -1
  66. package/dist/scenario.js +0 -235
  67. package/dist/scenario.js.map +0 -1
  68. package/dist/trail.d.ts +0 -20
  69. package/dist/trail.d.ts.map +0 -1
  70. package/dist/trail.js +0 -80
  71. package/dist/trail.js.map +0 -1
  72. package/dist/types.d.ts +0 -113
  73. package/dist/types.d.ts.map +0 -1
  74. package/dist/types.js +0 -5
  75. package/dist/types.js.map +0 -1
  76. package/src/__tests__/all.test.ts +0 -254
  77. package/src/__tests__/context.test.ts +0 -170
  78. package/src/__tests__/contracts.test.ts +0 -239
  79. package/src/__tests__/crosses.test.ts +0 -587
  80. package/src/__tests__/detours.test.ts +0 -212
  81. package/src/__tests__/effective-examples.test.ts +0 -203
  82. package/src/__tests__/examples.test.ts +0 -636
  83. package/src/__tests__/harness-cli.test.ts +0 -90
  84. package/src/__tests__/harness-mcp.test.ts +0 -37
  85. package/src/__tests__/logger.test.ts +0 -136
  86. package/src/__tests__/partial-match.test.ts +0 -126
  87. package/src/__tests__/scenario.test.ts +0 -381
  88. package/src/__tests__/trail.test.ts +0 -99
  89. package/tsconfig.json +0 -9
  90. package/tsconfig.tests.json +0 -10
  91. package/tsconfig.tsbuildinfo +0 -1
package/dist/all.js DELETED
@@ -1,99 +0,0 @@
1
- /**
2
- * testAll — single-line governance suite for any Topo.
3
- *
4
- * Wraps topo validation, example execution, contract checks, and detour
5
- * contract validation into one describe block.
6
- */
7
- import { describe, expect, test } from 'bun:test';
8
- import { validateEstablishedTopo, validateTopo } from '@ontrails/core';
9
- import { createCliHarness } from './harness-cli.js';
10
- import { createMcpHarness } from './harness-mcp.js';
11
- import { testContracts } from './contracts.js';
12
- import { testDetours } from './detours.js';
13
- import { testExamples } from './examples.js';
14
- const formatValidationFailure = (error) => {
15
- const issues = error.context?.issues;
16
- if (issues === undefined || issues.length === 0) {
17
- return error.message;
18
- }
19
- const details = issues.map((issue) => {
20
- const id = typeof issue['id'] === 'string' ? issue['id'] : undefined;
21
- const message = typeof issue['message'] === 'string' ? issue['message'] : undefined;
22
- const rule = typeof issue['rule'] === 'string' ? issue['rule'] : undefined;
23
- return [rule, id, message].filter(Boolean).join(': ');
24
- });
25
- return [error.message, ...details].join('\n');
26
- };
27
- const assertValidTopo = (result) => {
28
- if (result.isErr()) {
29
- throw new Error(formatValidationFailure(result.error));
30
- }
31
- };
32
- const registerGovernanceSuite = (topo, ctxOrFactory, validate) => {
33
- describe('governance', () => {
34
- test('topo validates', () => {
35
- expect(() => assertValidTopo(validate(topo))).not.toThrow();
36
- });
37
- // oxlint-disable-next-line jest/require-hook -- these generate describe/test blocks, not setup code
38
- testExamples(topo, ctxOrFactory);
39
- // oxlint-disable-next-line jest/require-hook -- these generate describe/test blocks, not setup code
40
- testContracts(topo, ctxOrFactory);
41
- // oxlint-disable-next-line jest/require-hook -- these generate describe/test blocks, not setup code
42
- testDetours(topo);
43
- });
44
- };
45
- export const testAll = (topo, ctxOrFactory) => {
46
- registerGovernanceSuite(topo, ctxOrFactory, validateTopo);
47
- };
48
- const isEstablishedOptions = (input) => input !== undefined &&
49
- (Object.hasOwn(input, 'cli') ||
50
- Object.hasOwn(input, 'createPermit') ||
51
- Object.hasOwn(input, 'ctx') ||
52
- Object.hasOwn(input, 'mcp') ||
53
- Object.hasOwn(input, 'resources') ||
54
- Object.hasOwn(input, 'strictPermits'));
55
- const normalizeEstablishedOptions = (input) => isEstablishedOptions(input) ? input : { ctx: input };
56
- const toExecutionOptions = (options) => ({
57
- ...(options.createPermit === undefined
58
- ? {}
59
- : { createPermit: options.createPermit }),
60
- ...(options.ctx === undefined ? {} : { ctx: options.ctx }),
61
- ...(options.resources === undefined ? {} : { resources: options.resources }),
62
- ...(options.strictPermits === undefined
63
- ? {}
64
- : { strictPermits: options.strictPermits }),
65
- });
66
- const toCliHarnessOptions = (topo, options) => {
67
- const cliOptions = {
68
- graph: topo,
69
- ...options.cli,
70
- };
71
- if (options.ctx !== undefined) {
72
- cliOptions.ctx = options.ctx;
73
- }
74
- return cliOptions;
75
- };
76
- const toMcpHarnessOptions = (topo, options) => ({
77
- graph: topo,
78
- ...options.mcp,
79
- });
80
- const registerEstablishedSurfaceSuite = (topo, resolveInput) => {
81
- describe('surfaces', () => {
82
- test('CLI projection validates established topo', () => {
83
- const options = normalizeEstablishedOptions(resolveInput());
84
- expect(() => createCliHarness(toCliHarnessOptions(topo, options))).not.toThrow();
85
- });
86
- test('MCP projection validates established topo', () => {
87
- const options = normalizeEstablishedOptions(resolveInput());
88
- expect(() => createMcpHarness(toMcpHarnessOptions(topo, options))).not.toThrow();
89
- });
90
- });
91
- };
92
- export const testAllEstablished = (topo, optionsOrFactory) => {
93
- const resolveInput = typeof optionsOrFactory === 'function'
94
- ? optionsOrFactory
95
- : () => optionsOrFactory;
96
- registerGovernanceSuite(topo, () => toExecutionOptions(normalizeEstablishedOptions(resolveInput())), validateEstablishedTopo);
97
- registerEstablishedSurfaceSuite(topo, resolveInput);
98
- };
99
- //# sourceMappingURL=all.js.map
package/dist/all.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"all.js","sourceRoot":"","sources":["../src/all.ts"],"names":[],"mappings":"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"}
@@ -1,72 +0,0 @@
1
- /**
2
- * Progressive assertion logic for example-driven testing.
3
- *
4
- * Three tiers:
5
- * 1. Full match — example has `expected` output
6
- * 2. Schema-only — no expected output, no error
7
- * 3. Error match — example declares an error class name
8
- */
9
- import type { Result } from '@ontrails/core';
10
- import type { z } from 'zod';
11
- /**
12
- * Assert that a Result is Ok and return its value.
13
- *
14
- * Eliminates the `if (result.isOk())` / `as unknown as` dance in tests.
15
- *
16
- * @example
17
- * ```typescript
18
- * const value = expectOk(result);
19
- * expect(value.name).toBe('Alice');
20
- * ```
21
- */
22
- export declare const expectOk: <T, E>(result: Result<T, E>) => T;
23
- /**
24
- * Assert that a Result is Err and return its error.
25
- *
26
- * Eliminates the `if (result.isErr())` / `as unknown as` dance in tests.
27
- *
28
- * @example
29
- * ```typescript
30
- * const error = expectErr(result);
31
- * expect(error).toBeInstanceOf(ValidationError);
32
- * ```
33
- */
34
- export declare const expectErr: <T, E>(result: Result<T, E>) => E;
35
- export interface OkResultMatch {
36
- readonly __resultMatch: 'ok';
37
- readonly value?: unknown | undefined;
38
- }
39
- export interface ErrResultMatch {
40
- readonly __resultMatch: 'err';
41
- readonly error?: unknown | undefined;
42
- }
43
- /**
44
- * Create a partial-match token for `Result.ok(...)` values nested inside
45
- * arrays or objects, such as the `Result[]` returned by batch `ctx.cross()`.
46
- */
47
- export declare const okResultMatch: (value?: unknown) => OkResultMatch;
48
- /**
49
- * Create a partial-match token for `Result.err(...)` values nested inside
50
- * arrays or objects, such as mixed-success batch `ctx.cross()`.
51
- */
52
- export declare const errResultMatch: (error?: unknown) => ErrResultMatch;
53
- /**
54
- * Assert that the result is ok and its value deep-equals the expected output.
55
- */
56
- export declare const assertFullMatch: (result: Result<unknown, Error>, expected: unknown) => void;
57
- /**
58
- * Assert that the result is ok and, if an output schema is provided,
59
- * the value parses against it.
60
- */
61
- export declare const assertSchemaMatch: (result: Result<unknown, Error>, outputSchema: z.ZodType | undefined) => void;
62
- /**
63
- * Assert that the result is ok and its value is a superset of the expected
64
- * partial output. Declared fields must match; extra fields are ignored.
65
- */
66
- export declare const assertPartialMatch: (result: Result<unknown, Error>, expectedMatch: unknown) => void;
67
- /**
68
- * Assert that the result is an error of the specified type, with optional
69
- * message substring matching.
70
- */
71
- export declare const assertErrorMatch: (result: Result<unknown, Error>, expectedError: new (...args: never[]) => Error, expectedMessage?: string) => void;
72
- //# sourceMappingURL=assertions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assertions.d.ts","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAM7B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAGrD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,EAAE,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,CAGtD,CAAC;AAMF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,aAAa,EAAE,IAAI,CAAC;IAC7B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACtC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,aAAa,EAAE,KAAK,CAAC;IAC9B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CACtC;AAID;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,QAAQ,OAAO,KAAG,aAG9C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,OAAO,KAAG,cAG/C,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,QAAQ,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9B,UAAU,OAAO,KAChB,IAGF,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9B,cAAc,CAAC,CAAC,OAAO,GAAG,SAAS,KAClC,IAUF,CAAC;AAiNF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9B,eAAe,OAAO,KACrB,IAGF,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9B,eAAe,KAAK,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,KAAK,EAC9C,kBAAkB,MAAM,KACvB,IAMF,CAAC"}
@@ -1,238 +0,0 @@
1
- /**
2
- * Progressive assertion logic for example-driven testing.
3
- *
4
- * Three tiers:
5
- * 1. Full match — example has `expected` output
6
- * 2. Schema-only — no expected output, no error
7
- * 3. Error match — example declares an error class name
8
- */
9
- import { expect } from 'bun:test';
10
- import { formatZodIssues } from '@ontrails/core';
11
- // ---------------------------------------------------------------------------
12
- // Result narrowing helpers
13
- // ---------------------------------------------------------------------------
14
- /**
15
- * Assert that a Result is Ok and return its value.
16
- *
17
- * Eliminates the `if (result.isOk())` / `as unknown as` dance in tests.
18
- *
19
- * @example
20
- * ```typescript
21
- * const value = expectOk(result);
22
- * expect(value.name).toBe('Alice');
23
- * ```
24
- */
25
- export const expectOk = (result) => {
26
- expect(result.isOk()).toBe(true);
27
- return result.value;
28
- };
29
- /**
30
- * Assert that a Result is Err and return its error.
31
- *
32
- * Eliminates the `if (result.isErr())` / `as unknown as` dance in tests.
33
- *
34
- * @example
35
- * ```typescript
36
- * const error = expectErr(result);
37
- * expect(error).toBeInstanceOf(ValidationError);
38
- * ```
39
- */
40
- export const expectErr = (result) => {
41
- expect(result.isErr()).toBe(true);
42
- return result.error;
43
- };
44
- /**
45
- * Create a partial-match token for `Result.ok(...)` values nested inside
46
- * arrays or objects, such as the `Result[]` returned by batch `ctx.cross()`.
47
- */
48
- export const okResultMatch = (value) => ({
49
- __resultMatch: 'ok',
50
- value,
51
- });
52
- /**
53
- * Create a partial-match token for `Result.err(...)` values nested inside
54
- * arrays or objects, such as mixed-success batch `ctx.cross()`.
55
- */
56
- export const errResultMatch = (error) => ({
57
- __resultMatch: 'err',
58
- error,
59
- });
60
- // ---------------------------------------------------------------------------
61
- // Full Match
62
- // ---------------------------------------------------------------------------
63
- /**
64
- * Assert that the result is ok and its value deep-equals the expected output.
65
- */
66
- export const assertFullMatch = (result, expected) => {
67
- const value = expectOk(result);
68
- expect(value).toEqual(expected);
69
- };
70
- // ---------------------------------------------------------------------------
71
- // Schema-Only Match
72
- // ---------------------------------------------------------------------------
73
- /**
74
- * Assert that the result is ok and, if an output schema is provided,
75
- * the value parses against it.
76
- */
77
- export const assertSchemaMatch = (result, outputSchema) => {
78
- const value = expectOk(result);
79
- if (outputSchema !== undefined) {
80
- const parsed = outputSchema.safeParse(value);
81
- if (!parsed.success) {
82
- throw new Error(`Output does not match schema: ${formatZodIssues(parsed.error.issues).join('; ')}`);
83
- }
84
- }
85
- };
86
- // ---------------------------------------------------------------------------
87
- // Partial Match
88
- // ---------------------------------------------------------------------------
89
- /** Format a path for error messages. */
90
- const formatLoc = (path) => path.length > 0 ? path.join('.') : 'root';
91
- const isResultMatchToken = (value) => typeof value === 'object' &&
92
- value !== null &&
93
- '__resultMatch' in value &&
94
- (value['__resultMatch'] === 'ok' ||
95
- value['__resultMatch'] === 'err');
96
- const isResultLike = (value) => typeof value === 'object' &&
97
- value !== null &&
98
- 'isOk' in value &&
99
- typeof value['isOk'] === 'function' &&
100
- 'isErr' in value &&
101
- typeof value['isErr'] === 'function';
102
- /** Find an unconsumed actual element that deep-matches the expected object. */
103
- const findObjectMatch = (actual, elem, consumed, path, index) => actual.findIndex((a, idx) => {
104
- if (consumed.has(idx)) {
105
- return false;
106
- }
107
- try {
108
- // oxlint-disable-next-line no-use-before-define -- mutual recursion with assertSubset
109
- assertSubset(a, elem, [...path, `[${String(index)}]`]);
110
- return true;
111
- }
112
- catch {
113
- return false;
114
- }
115
- });
116
- /**
117
- * Assert that every element in `expected` exists in `actual` (order-independent).
118
- *
119
- * Tracks consumed indices so that duplicate expected elements each require a
120
- * distinct actual element — `['a', 'a']` does not match `['a']`.
121
- */
122
- const assertArraySubset = (actual, expected, path, loc) => {
123
- const consumed = new Set();
124
- for (let i = 0; i < expected.length; i += 1) {
125
- const elem = expected[i];
126
- const matchIndex = typeof elem === 'object' && elem !== null
127
- ? findObjectMatch(actual, elem, consumed, path, i)
128
- : actual.findIndex((a, idx) => !consumed.has(idx) && a === elem);
129
- if (matchIndex === -1) {
130
- throw new Error(`at ${loc}[${String(i)}]: expected array to contain ${JSON.stringify(elem)}`);
131
- }
132
- consumed.add(matchIndex);
133
- }
134
- };
135
- /** Assert that every key in `expected` exists in `actual` with a matching value. */
136
- const assertObjectSubset = (actual, expected, path) => {
137
- for (const key of Object.keys(expected)) {
138
- if (!(key in actual)) {
139
- throw new Error(`at ${[...path, key].join('.')}: key not found in actual`);
140
- }
141
- // oxlint-disable-next-line no-use-before-define -- mutual recursion with assertSubset
142
- assertSubset(actual[key], expected[key], [...path, key]);
143
- }
144
- };
145
- /**
146
- * Recursively assert that `actual` is a superset of `expected`.
147
- *
148
- * - **Scalars:** strict equality.
149
- * - **Objects:** every key in `expected` must exist in `actual` with a matching
150
- * value. Extra keys in `actual` are ignored.
151
- * - **Arrays:** every element in `expected` must exist in `actual`
152
- * (order-independent subset check).
153
- * - **Nested objects:** recursive subset matching.
154
- */
155
- // oxlint-disable-next-line max-statements -- recursive dispatch across four type branches
156
- const assertSubset = (actual, expected, path) => {
157
- const loc = formatLoc(path);
158
- if (expected === null || expected === undefined) {
159
- if (actual !== expected) {
160
- throw new Error(`at ${loc}: expected ${String(expected)}, got ${String(actual)}`);
161
- }
162
- return;
163
- }
164
- if (isResultMatchToken(expected)) {
165
- // oxlint-disable-next-line no-use-before-define -- result token matching delegates back into assertSubset
166
- assertResultTokenMatch(actual, expected, path);
167
- return;
168
- }
169
- if (Array.isArray(expected)) {
170
- if (!Array.isArray(actual)) {
171
- throw new TypeError(`at ${loc}: expected an array, got ${typeof actual}`);
172
- }
173
- assertArraySubset(actual, expected, path, loc);
174
- return;
175
- }
176
- if (typeof expected === 'object') {
177
- if (typeof actual !== 'object' ||
178
- actual === null ||
179
- Array.isArray(actual)) {
180
- throw new Error(`at ${loc}: expected an object, got ${typeof actual}`);
181
- }
182
- assertObjectSubset(actual, expected, path);
183
- return;
184
- }
185
- if (actual !== expected) {
186
- throw new Error(`at ${loc}: expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`);
187
- }
188
- };
189
- const assertOkResultTokenMatch = (actual, expected, loc, path) => {
190
- if (!actual.isOk()) {
191
- throw new Error(`at ${loc}: expected Result.ok(...), got Result.err(...)`);
192
- }
193
- if (expected.value !== undefined) {
194
- assertSubset(actual.value, expected.value, [...path, 'value']);
195
- }
196
- };
197
- const assertErrResultTokenMatch = (actual, expected, loc, path) => {
198
- if (!actual.isErr()) {
199
- throw new Error(`at ${loc}: expected Result.err(...), got Result.ok(...)`);
200
- }
201
- if (expected.error !== undefined) {
202
- assertSubset(actual.error, expected.error, [...path, 'error']);
203
- }
204
- };
205
- const assertResultTokenMatch = (actual, expected, path) => {
206
- const loc = formatLoc(path);
207
- if (!isResultLike(actual)) {
208
- throw new TypeError(`at ${loc}: expected a Result-like value`);
209
- }
210
- if (expected.__resultMatch === 'ok') {
211
- assertOkResultTokenMatch(actual, expected, loc, path);
212
- return;
213
- }
214
- assertErrResultTokenMatch(actual, expected, loc, path);
215
- };
216
- /**
217
- * Assert that the result is ok and its value is a superset of the expected
218
- * partial output. Declared fields must match; extra fields are ignored.
219
- */
220
- export const assertPartialMatch = (result, expectedMatch) => {
221
- const value = expectOk(result);
222
- assertSubset(value, expectedMatch, []);
223
- };
224
- // ---------------------------------------------------------------------------
225
- // Error Match
226
- // ---------------------------------------------------------------------------
227
- /**
228
- * Assert that the result is an error of the specified type, with optional
229
- * message substring matching.
230
- */
231
- export const assertErrorMatch = (result, expectedError, expectedMessage) => {
232
- const error = expectErr(result);
233
- expect(error).toBeInstanceOf(expectedError);
234
- if (expectedMessage !== undefined) {
235
- expect(error.message).toContain(expectedMessage);
236
- }
237
- };
238
- //# sourceMappingURL=assertions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"assertions.js","sourceRoot":"","sources":["../src/assertions.ts"],"names":[],"mappings":"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"}
package/dist/context.d.ts DELETED
@@ -1,76 +0,0 @@
1
- /**
2
- * Test context factory for creating TrailContext instances suitable for testing.
3
- */
4
- import type { CrossFn, ResourceOverrideMap, Topo, TrailContext } from '@ontrails/core';
5
- import { Result, buildCrossValidationSchema } from '@ontrails/core';
6
- import type { TestTrailContextOptions } from './types.js';
7
- /**
8
- * Create a TrailContext with deterministic, test-friendly defaults.
9
- *
10
- * - `requestId`: `"test-request-001"` (deterministic)
11
- * - `logger`: a `TestLogger` that captures entries
12
- * - `abortSignal`: a non-aborted AbortController signal
13
- */
14
- export declare const createTestContext: (overrides?: TestTrailContextOptions) => TrailContext;
15
- export interface CreateCrossContextOptions {
16
- readonly responses?: Record<string, Result<unknown, Error>> | undefined;
17
- }
18
- /** Minimal permit shape returned by the create function. */
19
- export interface MinimalPermit {
20
- readonly id: string;
21
- readonly scopes: readonly string[];
22
- }
23
- /** Trail shape consumed by the create function — avoids importing permits. */
24
- export interface PermittedTrail {
25
- readonly permit?: {
26
- readonly scopes: readonly string[];
27
- } | 'public' | undefined;
28
- }
29
- export interface TestExecutionOptions {
30
- readonly ctx?: Partial<TrailContext> | undefined;
31
- readonly resources?: ResourceOverrideMap | undefined;
32
- /**
33
- * When true, disables automatic permit creation. Tests must provide
34
- * explicit permits.
35
- */
36
- readonly strictPermits?: boolean | undefined;
37
- /**
38
- * Optional function to create a test permit for a trail. When provided,
39
- * called for each trail with a non-public `permit` requirement.
40
- * Returning `undefined` skips creation for that trail.
41
- *
42
- * A default inline implementation is used when this is not provided,
43
- * keeping the testing package free of a hard dependency on `@ontrails/permits`.
44
- */
45
- readonly createPermit?: (trail: PermittedTrail) => MinimalPermit | undefined;
46
- }
47
- /**
48
- * Create a mock `CrossFn` for testing composite trails.
49
- *
50
- * Returns preconfigured `Result` values keyed by trail ID. Calls to
51
- * unregistered IDs return `Result.err` with a descriptive message.
52
- *
53
- * @example
54
- * ```ts
55
- * const cross = createCrossContext({
56
- * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
57
- * });
58
- * const ctx = { ...createTestContext(), cross };
59
- * ```
60
- */
61
- export declare const createCrossContext: (options?: CreateCrossContextOptions) => CrossFn;
62
- /**
63
- * Default permit creator — reads `trail.permit.scopes` and produces a
64
- * minimal permit object. No dependency on `@ontrails/permits`.
65
- */
66
- export declare const defaultCreatePermit: (trail: PermittedTrail) => MinimalPermit | undefined;
67
- export declare const normalizeTestExecutionOptions: (input?: Partial<TrailContext> | TestExecutionOptions) => TestExecutionOptions;
68
- export declare const mergeResourceOverrides: (autoResolved: ResourceOverrideMap, ctx: Partial<TrailContext> | undefined, explicit: ResourceOverrideMap | undefined) => ResourceOverrideMap;
69
- export declare const createMockResources: (app: Topo) => Promise<ResourceOverrideMap>;
70
- export { buildCrossValidationSchema };
71
- /**
72
- * Merge a Partial<TrailContext> into a test context.
73
- * Used internally when the public API accepts Partial<TrailContext>.
74
- */
75
- export declare const mergeTestContext: (ctx?: Partial<TrailContext>, resources?: ResourceOverrideMap) => TrailContext;
76
- //# sourceMappingURL=context.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,OAAO,EACP,mBAAmB,EACnB,IAAI,EACJ,YAAY,EACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,MAAM,EACN,0BAA0B,EAG3B,MAAM,gBAAgB,CAAC;AAGxB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAU1D;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,uBAAuB,KAClC,YAeF,CAAC;AAMF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC;CACzE;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,CAAC,EACZ;QAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GACtC,QAAQ,GACR,SAAS,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,SAAS,CAAC,EAAE,mBAAmB,GAAG,SAAS,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7C;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,aAAa,GAAG,SAAS,CAAC;CAC9E;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,yBAAyB,KAClC,OAiCF,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAC9B,OAAO,cAAc,KACpB,aAAa,GAAG,SAKlB,CAAC;AAWF,eAAO,MAAM,6BAA6B,GACxC,QAAQ,OAAO,CAAC,YAAY,CAAC,GAAG,oBAAoB,KACnD,oBACqD,CAAC;AAEzD,eAAO,MAAM,sBAAsB,GACjC,cAAc,mBAAmB,EACjC,KAAK,OAAO,CAAC,YAAY,CAAC,GAAG,SAAS,EACtC,UAAU,mBAAmB,GAAG,SAAS,KACxC,mBAID,CAAC;AAaH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,IAAI,KACR,OAAO,CAAC,mBAAmB,CAAkC,CAAC;AAGjE,OAAO,EAAE,0BAA0B,EAAE,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAM,OAAO,CAAC,YAAY,CAAC,EAC3B,YAAY,mBAAmB,KAC9B,YAeF,CAAC"}
package/dist/context.js DELETED
@@ -1,118 +0,0 @@
1
- /**
2
- * Test context factory for creating TrailContext instances suitable for testing.
3
- */
4
- import { Result, buildCrossValidationSchema, createResourceLookup, passthroughTrace, } from '@ontrails/core';
5
- import { createTestLogger } from './logger.js';
6
- // ---------------------------------------------------------------------------
7
- // createTestContext
8
- // ---------------------------------------------------------------------------
9
- /**
10
- * Create a TrailContext with deterministic, test-friendly defaults.
11
- *
12
- * - `requestId`: `"test-request-001"` (deterministic)
13
- * - `logger`: a `TestLogger` that captures entries
14
- * - `abortSignal`: a non-aborted AbortController signal
15
- */
16
- export const createTestContext = (overrides) => {
17
- const cwd = overrides?.cwd ?? process.cwd();
18
- const ctx = {
19
- abortSignal: overrides?.abortSignal ?? new AbortController().signal,
20
- cwd,
21
- env: overrides?.env ?? { TRAILS_ENV: 'test' },
22
- extensions: undefined,
23
- logger: overrides?.logger ?? createTestLogger(),
24
- requestId: overrides?.requestId ?? 'test-request-001',
25
- trace: overrides?.trace ?? passthroughTrace,
26
- workspaceRoot: cwd,
27
- };
28
- const lookup = createResourceLookup(() => ctx);
29
- ctx.resource = lookup;
30
- return ctx;
31
- };
32
- /**
33
- * Create a mock `CrossFn` for testing composite trails.
34
- *
35
- * Returns preconfigured `Result` values keyed by trail ID. Calls to
36
- * unregistered IDs return `Result.err` with a descriptive message.
37
- *
38
- * @example
39
- * ```ts
40
- * const cross = createCrossContext({
41
- * responses: { 'entity.add': Result.ok({ id: '1', name: 'Alpha' }) },
42
- * });
43
- * const ctx = { ...createTestContext(), cross };
44
- * ```
45
- */
46
- export const createCrossContext = (options) => {
47
- const responses = options?.responses ?? {};
48
- const respondToCross = (idOrTrail) => {
49
- const id = typeof idOrTrail === 'string' ? idOrTrail : idOrTrail.id;
50
- const response = responses[id];
51
- if (response === undefined) {
52
- return Promise.resolve(Result.err(new Error(`No mock response for cross("${id}")`)));
53
- }
54
- return Promise.resolve(response);
55
- };
56
- const cross = (async (idOrTrail, _input) => {
57
- if (Array.isArray(idOrTrail)) {
58
- return await Promise.all(idOrTrail.map(([target]) => respondToCross(target)));
59
- }
60
- return await respondToCross(idOrTrail);
61
- });
62
- return cross;
63
- };
64
- /**
65
- * Default permit creator — reads `trail.permit.scopes` and produces a
66
- * minimal permit object. No dependency on `@ontrails/permits`.
67
- */
68
- export const defaultCreatePermit = (trail) => {
69
- if (!trail.permit || trail.permit === 'public') {
70
- return undefined;
71
- }
72
- return { id: 'test-permit', scopes: trail.permit.scopes };
73
- };
74
- const isTestExecutionOptions = (input) => input !== undefined &&
75
- (Object.hasOwn(input, 'ctx') ||
76
- Object.hasOwn(input, 'resources') ||
77
- Object.hasOwn(input, 'strictPermits') ||
78
- Object.hasOwn(input, 'createPermit'));
79
- export const normalizeTestExecutionOptions = (input) => isTestExecutionOptions(input) ? input : { ctx: input };
80
- export const mergeResourceOverrides = (autoResolved, ctx, explicit) => ({
81
- ...autoResolved,
82
- ...ctx?.extensions,
83
- ...explicit,
84
- });
85
- const buildMockResources = async (app) => {
86
- const resources = {};
87
- for (const declaredResource of app.listResources()) {
88
- if (!declaredResource.mock) {
89
- continue;
90
- }
91
- resources[declaredResource.id] = await declaredResource.mock();
92
- }
93
- return resources;
94
- };
95
- export const createMockResources = async (app) => await buildMockResources(app);
96
- // Re-export from core so existing consumers of this module continue to work.
97
- export { buildCrossValidationSchema };
98
- /**
99
- * Merge a Partial<TrailContext> into a test context.
100
- * Used internally when the public API accepts Partial<TrailContext>.
101
- */
102
- export const mergeTestContext = (ctx, resources) => {
103
- const base = createTestContext();
104
- const extensions = {
105
- ...base.extensions,
106
- ...ctx?.extensions,
107
- ...resources,
108
- };
109
- const merged = {
110
- ...base,
111
- ...ctx,
112
- extensions: Object.keys(extensions).length === 0 ? undefined : extensions,
113
- };
114
- const lookup = createResourceLookup(() => merged);
115
- merged.resource = lookup;
116
- return merged;
117
- };
118
- //# sourceMappingURL=context.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
@@ -1,17 +0,0 @@
1
- /**
2
- * testContracts — output schema verification.
3
- *
4
- * For every trail that has both examples and an output schema,
5
- * run each example and validate the implementation output against
6
- * the declared schema.
7
- */
8
- import type { Topo, TrailContext } from '@ontrails/core';
9
- import type { TestExecutionOptions } from './context.js';
10
- /**
11
- * Verify that every trail implementation output matches its declared
12
- * output schema. Catches implementation-schema drift.
13
- *
14
- * Trails without output schemas or examples are skipped.
15
- */
16
- export declare const testContracts: (app: Topo, ctxOrFactory?: Partial<TrailContext> | TestExecutionOptions | (() => Partial<TrailContext> | TestExecutionOptions)) => void;
17
- //# sourceMappingURL=contracts.d.ts.map