@ontrails/testing 1.0.0-beta.42 → 1.0.0-beta.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/README.md +2 -2
- package/package.json +8 -8
- package/src/all-established.ts +4 -4
- package/src/effective-examples.ts +6 -6
- package/src/harness-cli.ts +11 -11
- package/src/harness-http.ts +7 -7
- package/src/logger.ts +1 -1
- package/src/types.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @ontrails/testing
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.43
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`88a6a62`](https://github.com/outfitter-dev/trails/commit/88a6a62a9e9e230ca6d368fa78dc3ece6c816204): Complete the v1 classification-first cutover from projection/project vocabulary
|
|
8
|
+
to derive/derived for contract-owned fact production and render/rendered for
|
|
9
|
+
surface presentation. Public type, helper, rule, relation, and report names move
|
|
10
|
+
without compatibility aliases; ordinary repository/project nouns remain
|
|
11
|
+
explicit preserves or structured review inventory.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`113aed6`](https://github.com/outfitter-dev/trails/commit/113aed62d20041e35b0cf9d6c1b1a18df4b88f57): Rename the dependency-light observability owner from `@ontrails/observe` to
|
|
16
|
+
`@ontrails/observability` as a pre-v1 hard cut. Update dependent packages,
|
|
17
|
+
documentation, package discovery, and the governed Regrade route; no
|
|
18
|
+
compatibility package or old import route is retained.
|
|
19
|
+
|
|
3
20
|
## 1.0.0-beta.42
|
|
4
21
|
|
|
5
22
|
## 1.0.0-beta.41
|
package/README.md
CHANGED
|
@@ -91,7 +91,7 @@ Calls to unregistered trail IDs return `Result.err` with a descriptive message,
|
|
|
91
91
|
|
|
92
92
|
## Surface Harnesses
|
|
93
93
|
|
|
94
|
-
Surface harnesses live on explicit subpaths so
|
|
94
|
+
Surface harnesses live on explicit subpaths so renders that only import contract helpers from `@ontrails/testing` do not need CLI, MCP, or HTTP peers. Install the peer package for the subpath you use:
|
|
95
95
|
|
|
96
96
|
- `@ontrails/testing/cli` requires `@ontrails/cli`
|
|
97
97
|
- `@ontrails/testing/mcp` requires `@ontrails/mcp`
|
|
@@ -120,7 +120,7 @@ const response = await http.get('/entity/show', { name: 'Alpha' });
|
|
|
120
120
|
expect(response.status).toBe(200);
|
|
121
121
|
```
|
|
122
122
|
|
|
123
|
-
Use `testAllEstablished()` from `@ontrails/testing/established` when an established app should run the root contract suite and validate CLI, MCP, and HTTP
|
|
123
|
+
Use `testAllEstablished()` from `@ontrails/testing/established` when an established app should run the root contract suite and validate CLI, MCP, and HTTP renderings in one call.
|
|
124
124
|
|
|
125
125
|
## Surface Parity
|
|
126
126
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/testing",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.43",
|
|
4
4
|
"files": [
|
|
5
5
|
"src/**/*.ts",
|
|
6
6
|
"!src/**/__tests__/**",
|
|
@@ -27,15 +27,15 @@
|
|
|
27
27
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@ontrails/drizzle": "^1.0.0-beta.
|
|
31
|
-
"@ontrails/store": "^1.0.0-beta.
|
|
30
|
+
"@ontrails/drizzle": "^1.0.0-beta.43",
|
|
31
|
+
"@ontrails/store": "^1.0.0-beta.43"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
|
-
"@ontrails/cli": "^1.0.0-beta.
|
|
35
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
36
|
-
"@ontrails/http": "^1.0.0-beta.
|
|
37
|
-
"@ontrails/mcp": "^1.0.0-beta.
|
|
38
|
-
"@ontrails/
|
|
34
|
+
"@ontrails/cli": "^1.0.0-beta.43",
|
|
35
|
+
"@ontrails/core": "^1.0.0-beta.43",
|
|
36
|
+
"@ontrails/http": "^1.0.0-beta.43",
|
|
37
|
+
"@ontrails/mcp": "^1.0.0-beta.43",
|
|
38
|
+
"@ontrails/observability": "^1.0.0-beta.43",
|
|
39
39
|
"zod": "^4.3.5"
|
|
40
40
|
},
|
|
41
41
|
"peerDependenciesMeta": {
|
package/src/all-established.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* testAllEstablished - contract suite plus shipped surface
|
|
2
|
+
* testAllEstablished - contract suite plus shipped surface rendering checks.
|
|
3
3
|
*
|
|
4
4
|
* This helper intentionally lives behind a surface subpath so root
|
|
5
5
|
* `@ontrails/testing` imports do not pull CLI, MCP, or HTTP peers into
|
|
@@ -125,21 +125,21 @@ const registerEstablishedSurfaceSuite = (
|
|
|
125
125
|
| undefined
|
|
126
126
|
): void => {
|
|
127
127
|
describe('surfaces', () => {
|
|
128
|
-
test('CLI
|
|
128
|
+
test('CLI rendering validates established topo', () => {
|
|
129
129
|
const options = normalizeEstablishedOptions(resolveInput());
|
|
130
130
|
expect(() =>
|
|
131
131
|
createCliHarness(toCliHarnessOptions(topo, options))
|
|
132
132
|
).not.toThrow();
|
|
133
133
|
});
|
|
134
134
|
|
|
135
|
-
test('MCP
|
|
135
|
+
test('MCP rendering validates established topo', () => {
|
|
136
136
|
const options = normalizeEstablishedOptions(resolveInput());
|
|
137
137
|
expect(() =>
|
|
138
138
|
createMcpHarness(toMcpHarnessOptions(topo, options))
|
|
139
139
|
).not.toThrow();
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
-
test('HTTP
|
|
142
|
+
test('HTTP rendering validates established topo', () => {
|
|
143
143
|
const options = normalizeEstablishedOptions(resolveInput());
|
|
144
144
|
expect(() =>
|
|
145
145
|
createHttpHarness(toHttpHarnessOptions(topo, options))
|
|
@@ -216,7 +216,7 @@ const buildDerivedInput = (
|
|
|
216
216
|
};
|
|
217
217
|
|
|
218
218
|
/**
|
|
219
|
-
*
|
|
219
|
+
* Derive the merged candidate input down to keys the trail's input schema
|
|
220
220
|
* knows about.
|
|
221
221
|
*
|
|
222
222
|
* `buildDerivedInput` emits synthesized prefixed aliases (e.g. `userEmail`)
|
|
@@ -227,7 +227,7 @@ const buildDerivedInput = (
|
|
|
227
227
|
* before validation. Non-object inputs pass through unchanged — they are
|
|
228
228
|
* validated as-is and can decide for themselves.
|
|
229
229
|
*/
|
|
230
|
-
const
|
|
230
|
+
const deriveInputForSchema = (
|
|
231
231
|
inputSchema: Trail<unknown, unknown, unknown>['input'],
|
|
232
232
|
candidate: Record<string, unknown>
|
|
233
233
|
): Record<string, unknown> => {
|
|
@@ -236,13 +236,13 @@ const projectInputForSchema = (
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
const known = Object.keys(inputSchema.shape);
|
|
239
|
-
const
|
|
239
|
+
const derived: Record<string, unknown> = {};
|
|
240
240
|
for (const key of known) {
|
|
241
241
|
if (Object.hasOwn(candidate, key)) {
|
|
242
|
-
|
|
242
|
+
derived[key] = candidate[key];
|
|
243
243
|
}
|
|
244
244
|
}
|
|
245
|
-
return
|
|
245
|
+
return derived;
|
|
246
246
|
};
|
|
247
247
|
|
|
248
248
|
/**
|
|
@@ -344,7 +344,7 @@ export const deriveTrailExamples = (
|
|
|
344
344
|
|
|
345
345
|
return fixtureSets.flatMap((fixtures, index) => {
|
|
346
346
|
const merged = buildDerivedInput(fixtures);
|
|
347
|
-
const input =
|
|
347
|
+
const input = deriveInputForSchema(trail.input, merged);
|
|
348
348
|
const validated = trail.input.safeParse(input);
|
|
349
349
|
if (!validated.success) {
|
|
350
350
|
return [];
|
package/src/harness-cli.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { deriveCliCommands } from '@ontrails/cli';
|
|
9
9
|
import type { CliCommand, DeriveCliCommandsOptions } from '@ontrails/cli';
|
|
10
10
|
import type { Topo, TrailContext } from '@ontrails/core';
|
|
11
|
-
import {
|
|
11
|
+
import { renderPublicSurfaceError } from '@ontrails/core';
|
|
12
12
|
|
|
13
13
|
import { mergeTestContext } from './context.js';
|
|
14
14
|
|
|
@@ -235,15 +235,15 @@ const buildErrorResult = (
|
|
|
235
235
|
): CliHarnessResult => {
|
|
236
236
|
streams.restore();
|
|
237
237
|
const actualError = error instanceof Error ? error : new Error(String(error));
|
|
238
|
-
const
|
|
238
|
+
const rendering = renderPublicSurfaceError('cli', actualError);
|
|
239
239
|
return {
|
|
240
240
|
error: {
|
|
241
|
-
category:
|
|
242
|
-
code:
|
|
243
|
-
message:
|
|
241
|
+
category: rendering.category,
|
|
242
|
+
code: rendering.name,
|
|
243
|
+
message: rendering.message,
|
|
244
244
|
},
|
|
245
245
|
exitCode: 1,
|
|
246
|
-
stderr: streams.getStderr() ||
|
|
246
|
+
stderr: streams.getStderr() || rendering.message,
|
|
247
247
|
stdout: streams.getStdout(),
|
|
248
248
|
};
|
|
249
249
|
};
|
|
@@ -260,15 +260,15 @@ const executeCommand = async (
|
|
|
260
260
|
streams.restore();
|
|
261
261
|
|
|
262
262
|
if (result.isErr()) {
|
|
263
|
-
const
|
|
263
|
+
const rendering = renderPublicSurfaceError('cli', result.error);
|
|
264
264
|
return {
|
|
265
265
|
error: {
|
|
266
|
-
category:
|
|
267
|
-
code:
|
|
268
|
-
message:
|
|
266
|
+
category: rendering.category,
|
|
267
|
+
code: rendering.name,
|
|
268
|
+
message: rendering.message,
|
|
269
269
|
},
|
|
270
270
|
exitCode: 1,
|
|
271
|
-
stderr: streams.getStderr() ||
|
|
271
|
+
stderr: streams.getStderr() || rendering.message,
|
|
272
272
|
stdout: streams.getStdout(),
|
|
273
273
|
};
|
|
274
274
|
}
|
package/src/harness-http.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type {
|
|
|
13
13
|
HttpRouteDefinition,
|
|
14
14
|
} from '@ontrails/http';
|
|
15
15
|
import type { Topo, TrailContext, TrailContextInit } from '@ontrails/core';
|
|
16
|
-
import { NotFoundError,
|
|
16
|
+
import { NotFoundError, renderPublicSurfaceError } from '@ontrails/core';
|
|
17
17
|
|
|
18
18
|
import { mergeTestContext } from './context.js';
|
|
19
19
|
|
|
@@ -40,7 +40,7 @@ export interface HttpHarnessRequestOptions extends Omit<
|
|
|
40
40
|
readonly query?: Record<string, unknown> | undefined;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
/** A test harness for HTTP route
|
|
43
|
+
/** A test harness for HTTP route renderings. */
|
|
44
44
|
export interface HttpHarness {
|
|
45
45
|
/** Execute a raw HTTP-style harness request. */
|
|
46
46
|
request(request: HttpHarnessRequest): Promise<HttpHarnessResult>;
|
|
@@ -126,19 +126,19 @@ const findRoute = (
|
|
|
126
126
|
routes.find((route) => route.method === method && route.path === path);
|
|
127
127
|
|
|
128
128
|
const mapError = (error: Error): HttpHarnessResult => {
|
|
129
|
-
const
|
|
129
|
+
const rendering = renderPublicSurfaceError('http', error);
|
|
130
130
|
const body = {
|
|
131
131
|
error: {
|
|
132
|
-
category:
|
|
133
|
-
code:
|
|
134
|
-
message:
|
|
132
|
+
category: rendering.category,
|
|
133
|
+
code: rendering.name,
|
|
134
|
+
message: rendering.message,
|
|
135
135
|
},
|
|
136
136
|
};
|
|
137
137
|
return {
|
|
138
138
|
body,
|
|
139
139
|
error: body.error,
|
|
140
140
|
ok: false,
|
|
141
|
-
status:
|
|
141
|
+
status: rendering.code,
|
|
142
142
|
};
|
|
143
143
|
};
|
|
144
144
|
|
package/src/logger.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import type { AnyTrail, Logger, TraceFn } from '@ontrails/core';
|
|
6
|
-
import type { LogLevel, LogRecord } from '@ontrails/
|
|
6
|
+
import type { LogLevel, LogRecord } from '@ontrails/observability';
|
|
7
7
|
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
// Test Scenario (for testTrail)
|