@nifrajs/testing 3.3.0 → 4.0.0
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/README.md +26 -0
- package/dist/adversarial.d.ts +14 -1
- package/dist/adversarial.d.ts.map +1 -1
- package/dist/adversarial.js +113 -25
- package/dist/adversarial.js.map +1 -1
- package/dist/agent-eval.d.ts.map +1 -1
- package/dist/agent-eval.js +3 -1
- package/dist/agent-eval.js.map +1 -1
- package/dist/certification.d.ts +28 -1
- package/dist/certification.d.ts.map +1 -1
- package/dist/certification.js +119 -51
- package/dist/certification.js.map +1 -1
- package/dist/contract-lab.js +1 -1
- package/dist/contract-lab.js.map +1 -1
- package/dist/data-conformance.d.ts +72 -0
- package/dist/data-conformance.d.ts.map +1 -0
- package/dist/data-conformance.js +198 -0
- package/dist/data-conformance.js.map +1 -0
- package/dist/e2e.d.ts +63 -0
- package/dist/e2e.d.ts.map +1 -0
- package/dist/e2e.js +56 -0
- package/dist/e2e.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/prediction-lab.d.ts +65 -0
- package/dist/prediction-lab.d.ts.map +1 -0
- package/dist/prediction-lab.js +530 -0
- package/dist/prediction-lab.js.map +1 -0
- package/package.json +20 -7
- package/src/adversarial.ts +144 -28
- package/src/agent-eval.ts +4 -3
- package/src/certification.ts +138 -45
- package/src/contract-lab.ts +1 -1
- package/src/data-conformance.ts +297 -0
- package/src/e2e.ts +112 -0
- package/src/index.ts +28 -0
- package/src/prediction-lab.ts +692 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavioral conformance checks for durable data adapters.
|
|
3
|
+
*
|
|
4
|
+
* The framework does not own a SQL dialect or a tenant model. This harness therefore accepts a
|
|
5
|
+
* small adapter-specific operation map and verifies the guarantees that are portable across
|
|
6
|
+
* Postgres, SQLite, D1, Durable Objects, and other implementations.
|
|
7
|
+
*/
|
|
8
|
+
export interface DataConformanceScope {
|
|
9
|
+
readonly token: string;
|
|
10
|
+
}
|
|
11
|
+
export interface DataConformancePage<Row, Cursor = string> {
|
|
12
|
+
readonly items: readonly Row[];
|
|
13
|
+
readonly cursor?: Cursor;
|
|
14
|
+
}
|
|
15
|
+
export interface DataConformanceTransaction<Row> {
|
|
16
|
+
write(row: Row): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export interface DataAdapterConformanceTarget<Adapter, Row, Snapshot, Cursor = string> {
|
|
19
|
+
/** Return a fresh adapter handle. Two handles must observe shared durable state. */
|
|
20
|
+
readonly createAdapter: (instance: string) => Adapter | Promise<Adapter>;
|
|
21
|
+
/** Insert a fixture row under the adapter's tenant/RLS boundary. */
|
|
22
|
+
readonly seed: (adapter: Adapter, scope: DataConformanceScope, row: Row) => Promise<void>;
|
|
23
|
+
/** Read rows visible to one scope. */
|
|
24
|
+
readonly read: (adapter: Adapter, scope: DataConformanceScope) => Promise<readonly Row[]>;
|
|
25
|
+
/** Perform one cancellable write. */
|
|
26
|
+
readonly write: (adapter: Adapter, scope: DataConformanceScope, row: Row, signal: AbortSignal) => Promise<void>;
|
|
27
|
+
/** Execute writes atomically; a rejected callback must roll back all writes. */
|
|
28
|
+
readonly transaction: <T>(adapter: Adapter, scope: DataConformanceScope, run: (transaction: DataConformanceTransaction<Row>) => Promise<T>) => Promise<T>;
|
|
29
|
+
/** Return one cursor page. The cursor is adapter-owned and must be treated as opaque. */
|
|
30
|
+
readonly page: (adapter: Adapter, scope: DataConformanceScope, cursor?: Cursor) => Promise<DataConformancePage<Row, Cursor>>;
|
|
31
|
+
/** Capture and restore a durable snapshot for backup/restore testing. */
|
|
32
|
+
readonly snapshot: (adapter: Adapter) => Promise<Snapshot>;
|
|
33
|
+
readonly restore: (adapter: Adapter, snapshot: Snapshot) => Promise<void>;
|
|
34
|
+
/** Stable row identity used to detect cross-tenant leaks and pagination duplicates. */
|
|
35
|
+
readonly rowKey: (row: Row) => string;
|
|
36
|
+
/** Optional cleanup for an adapter handle. */
|
|
37
|
+
readonly close?: (adapter: Adapter) => Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
export type DataConformanceCheck = "rls-isolation" | "transaction-rollback" | "cancellation" | "pagination" | "backup-restore" | "multi-instance";
|
|
40
|
+
export interface DataConformanceFailure {
|
|
41
|
+
readonly check: DataConformanceCheck;
|
|
42
|
+
readonly message: string;
|
|
43
|
+
}
|
|
44
|
+
export interface DataAdapterConformanceReport {
|
|
45
|
+
readonly ok: boolean;
|
|
46
|
+
readonly checks: Readonly<Record<DataConformanceCheck, "pass" | "fail">>;
|
|
47
|
+
readonly failures: readonly DataConformanceFailure[];
|
|
48
|
+
}
|
|
49
|
+
export declare class DataAdapterConformanceError extends Error {
|
|
50
|
+
readonly report: DataAdapterConformanceReport;
|
|
51
|
+
constructor(report: DataAdapterConformanceReport);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Run the portable data-adapter contract and return machine-readable evidence.
|
|
55
|
+
*
|
|
56
|
+
* The harness intentionally uses fresh handles and opaque scope tokens. It does not inspect SQL,
|
|
57
|
+
* tenant columns, transaction objects, provider errors, or credentials.
|
|
58
|
+
*/
|
|
59
|
+
export declare function runDataAdapterConformance<Adapter, Row, Snapshot, Cursor = string>(target: DataAdapterConformanceTarget<Adapter, Row, Snapshot, Cursor>, options?: {
|
|
60
|
+
readonly scopes?: {
|
|
61
|
+
readonly left: DataConformanceScope;
|
|
62
|
+
readonly right: DataConformanceScope;
|
|
63
|
+
};
|
|
64
|
+
readonly rows?: {
|
|
65
|
+
readonly left: Row;
|
|
66
|
+
readonly right: Row;
|
|
67
|
+
readonly rollback: Row;
|
|
68
|
+
readonly shared: Row;
|
|
69
|
+
};
|
|
70
|
+
}): Promise<DataAdapterConformanceReport>;
|
|
71
|
+
export declare function assertDataAdapterConformance<Adapter, Row, Snapshot, Cursor = string>(target: DataAdapterConformanceTarget<Adapter, Row, Snapshot, Cursor>, options?: Parameters<typeof runDataAdapterConformance<Adapter, Row, Snapshot, Cursor>>[1]): Promise<void>;
|
|
72
|
+
//# sourceMappingURL=data-conformance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-conformance.d.ts","sourceRoot":"","sources":["../src/data-conformance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Behavioral conformance checks for durable data adapters.
|
|
3
|
+
*
|
|
4
|
+
* The framework does not own a SQL dialect or a tenant model. This harness therefore accepts a
|
|
5
|
+
* small adapter-specific operation map and verifies the guarantees that are portable across
|
|
6
|
+
* Postgres, SQLite, D1, Durable Objects, and other implementations.
|
|
7
|
+
*/
|
|
8
|
+
export class DataAdapterConformanceError extends Error {
|
|
9
|
+
report;
|
|
10
|
+
constructor(report) {
|
|
11
|
+
super(`data adapter conformance failed: ${report.failures
|
|
12
|
+
.map((failure) => `${failure.check}: ${failure.message}`)
|
|
13
|
+
.join("; ")}`);
|
|
14
|
+
this.name = "DataAdapterConformanceError";
|
|
15
|
+
this.report = report;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const CHECKS = [
|
|
19
|
+
"rls-isolation",
|
|
20
|
+
"transaction-rollback",
|
|
21
|
+
"cancellation",
|
|
22
|
+
"pagination",
|
|
23
|
+
"backup-restore",
|
|
24
|
+
"multi-instance",
|
|
25
|
+
];
|
|
26
|
+
const defaultScopes = Object.freeze({
|
|
27
|
+
left: Object.freeze({ token: "nifra-conformance/tenant-left" }),
|
|
28
|
+
right: Object.freeze({ token: "nifra-conformance/tenant-right" }),
|
|
29
|
+
});
|
|
30
|
+
const defaultRows = Object.freeze({
|
|
31
|
+
left: Object.freeze({ id: "left" }),
|
|
32
|
+
right: Object.freeze({ id: "right" }),
|
|
33
|
+
rollback: Object.freeze({ id: "rollback" }),
|
|
34
|
+
shared: Object.freeze({ id: "shared" }),
|
|
35
|
+
});
|
|
36
|
+
function isAbortLike(error) {
|
|
37
|
+
return ((typeof DOMException !== "undefined" &&
|
|
38
|
+
error instanceof DOMException &&
|
|
39
|
+
error.name === "AbortError") ||
|
|
40
|
+
(error instanceof Error && /abort|cancel/i.test(`${error.name} ${error.message}`)));
|
|
41
|
+
}
|
|
42
|
+
async function closeAll(target, adapters) {
|
|
43
|
+
if (target.close === undefined)
|
|
44
|
+
return;
|
|
45
|
+
await Promise.all(adapters.map((adapter) => target.close(adapter)));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Run the portable data-adapter contract and return machine-readable evidence.
|
|
49
|
+
*
|
|
50
|
+
* The harness intentionally uses fresh handles and opaque scope tokens. It does not inspect SQL,
|
|
51
|
+
* tenant columns, transaction objects, provider errors, or credentials.
|
|
52
|
+
*/
|
|
53
|
+
export async function runDataAdapterConformance(target, options = {}) {
|
|
54
|
+
const scopes = options.scopes ?? defaultScopes;
|
|
55
|
+
const rows = options.rows ??
|
|
56
|
+
defaultRows;
|
|
57
|
+
const adapters = [];
|
|
58
|
+
const failures = [];
|
|
59
|
+
const checks = {
|
|
60
|
+
"rls-isolation": "fail",
|
|
61
|
+
"transaction-rollback": "fail",
|
|
62
|
+
cancellation: "fail",
|
|
63
|
+
pagination: "fail",
|
|
64
|
+
"backup-restore": "fail",
|
|
65
|
+
"multi-instance": "fail",
|
|
66
|
+
};
|
|
67
|
+
const run = async (check, action) => {
|
|
68
|
+
try {
|
|
69
|
+
await action();
|
|
70
|
+
checks[check] = "pass";
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
failures.push({
|
|
74
|
+
check,
|
|
75
|
+
// Provider errors can contain credentials, SQL, tenant identifiers, or request values.
|
|
76
|
+
// The portable report is safe to serialize and log, so retain only the stable check name.
|
|
77
|
+
message: `${check} conformance check failed`,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
try {
|
|
82
|
+
const primary = await target.createAdapter("primary");
|
|
83
|
+
const secondary = await target.createAdapter("secondary");
|
|
84
|
+
adapters.push(primary, secondary);
|
|
85
|
+
await run("rls-isolation", async () => {
|
|
86
|
+
await target.seed(primary, scopes.left, rows.left);
|
|
87
|
+
await target.seed(primary, scopes.right, rows.right);
|
|
88
|
+
const left = await target.read(primary, scopes.left);
|
|
89
|
+
const right = await target.read(primary, scopes.right);
|
|
90
|
+
const leftKeys = new Set(left.map(target.rowKey));
|
|
91
|
+
const rightKeys = new Set(right.map(target.rowKey));
|
|
92
|
+
if (!leftKeys.has(target.rowKey(rows.left)) || leftKeys.has(target.rowKey(rows.right))) {
|
|
93
|
+
throw new Error("left scope can read another scope's row");
|
|
94
|
+
}
|
|
95
|
+
if (!rightKeys.has(target.rowKey(rows.right)) || rightKeys.has(target.rowKey(rows.left))) {
|
|
96
|
+
throw new Error("right scope can read another scope's row");
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
await run("transaction-rollback", async () => {
|
|
100
|
+
const before = new Set((await target.read(primary, scopes.left)).map(target.rowKey));
|
|
101
|
+
let rejectedCallback = false;
|
|
102
|
+
try {
|
|
103
|
+
await target.transaction(primary, scopes.left, async (transaction) => {
|
|
104
|
+
await transaction.write(rows.rollback);
|
|
105
|
+
throw new Error("conformance rollback");
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
rejectedCallback = true;
|
|
110
|
+
}
|
|
111
|
+
if (!rejectedCallback)
|
|
112
|
+
throw new Error("transaction accepted a rejected callback");
|
|
113
|
+
const after = new Set((await target.read(primary, scopes.left)).map(target.rowKey));
|
|
114
|
+
if (after.has(target.rowKey(rows.rollback)) || [...after].some((key) => !before.has(key))) {
|
|
115
|
+
throw new Error("rejected transaction changed durable state");
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
await run("cancellation", async () => {
|
|
119
|
+
const controller = new AbortController();
|
|
120
|
+
controller.abort();
|
|
121
|
+
try {
|
|
122
|
+
await target.write(primary, scopes.left, rows.rollback, controller.signal);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
if (isAbortLike(error) || controller.signal.aborted)
|
|
126
|
+
return;
|
|
127
|
+
throw error;
|
|
128
|
+
}
|
|
129
|
+
throw new Error("cancelled write resolved successfully");
|
|
130
|
+
});
|
|
131
|
+
await run("pagination", async () => {
|
|
132
|
+
const seen = [];
|
|
133
|
+
const cursors = new Set();
|
|
134
|
+
let cursor;
|
|
135
|
+
for (let pageNumber = 0; pageNumber < 100; pageNumber++) {
|
|
136
|
+
const page = await target.page(primary, scopes.left, cursor);
|
|
137
|
+
seen.push(...page.items.map(target.rowKey));
|
|
138
|
+
if (page.cursor === undefined)
|
|
139
|
+
break;
|
|
140
|
+
const next = String(page.cursor);
|
|
141
|
+
if (cursors.has(next))
|
|
142
|
+
throw new Error("pagination cursor repeated");
|
|
143
|
+
cursors.add(next);
|
|
144
|
+
cursor = page.cursor;
|
|
145
|
+
if (pageNumber === 99)
|
|
146
|
+
throw new Error("pagination did not terminate");
|
|
147
|
+
}
|
|
148
|
+
if (new Set(seen).size !== seen.length)
|
|
149
|
+
throw new Error("pagination returned a duplicate row");
|
|
150
|
+
});
|
|
151
|
+
await run("backup-restore", async () => {
|
|
152
|
+
const snapshot = await target.snapshot(primary);
|
|
153
|
+
await target.seed(primary, scopes.left, rows.rollback);
|
|
154
|
+
await target.restore(primary, snapshot);
|
|
155
|
+
const restored = new Set((await target.read(primary, scopes.left)).map(target.rowKey));
|
|
156
|
+
if (restored.has(target.rowKey(rows.rollback))) {
|
|
157
|
+
throw new Error("restore did not remove post-backup data");
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
await run("multi-instance", async () => {
|
|
161
|
+
await target.seed(primary, scopes.left, rows.shared);
|
|
162
|
+
const visible = new Set((await target.read(secondary, scopes.left)).map(target.rowKey));
|
|
163
|
+
if (!visible.has(target.rowKey(rows.shared))) {
|
|
164
|
+
throw new Error("a second adapter instance cannot observe committed durable state");
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
failures.push({
|
|
170
|
+
check: "multi-instance",
|
|
171
|
+
message: "multi-instance conformance check failed",
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
try {
|
|
176
|
+
await closeAll(target, adapters);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
failures.push({ check: "multi-instance", message: "adapter cleanup failed" });
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
const failed = new Set(failures.map((failure) => failure.check));
|
|
183
|
+
for (const check of CHECKS) {
|
|
184
|
+
if (failed.has(check))
|
|
185
|
+
checks[check] = "fail";
|
|
186
|
+
}
|
|
187
|
+
return Object.freeze({
|
|
188
|
+
ok: failures.length === 0,
|
|
189
|
+
checks: Object.freeze({ ...checks }),
|
|
190
|
+
failures: Object.freeze([...failures]),
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
export async function assertDataAdapterConformance(target, options = {}) {
|
|
194
|
+
const report = await runDataAdapterConformance(target, options);
|
|
195
|
+
if (!report.ok)
|
|
196
|
+
throw new DataAdapterConformanceError(report);
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=data-conformance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-conformance.js","sourceRoot":"","sources":["../src/data-conformance.ts"],"names":[],"mappings":"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"}
|
package/dist/e2e.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-test glue: an ephemeral server plus typed URLs plus the session handoff - everything
|
|
3
|
+
* nifra-specific about driving a real browser, and nothing else. This is deliberately NOT a test
|
|
4
|
+
* runner (bring Playwright or Vitest Browser for the browser itself): API flows already run faster
|
|
5
|
+
* in-process through {@link testSession}, so this module covers only what in-process cannot - a
|
|
6
|
+
* real socket, real navigation, real rendering.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { chromium } from "@playwright/test"
|
|
10
|
+
* import { e2eUrl, serveTestApp } from "@nifrajs/testing/e2e"
|
|
11
|
+
* import { testSession } from "@nifrajs/testing"
|
|
12
|
+
* import { app } from "../src/app"
|
|
13
|
+
*
|
|
14
|
+
* const { cookies } = testSession<typeof app>(app)
|
|
15
|
+
* await api.auth.login.post(credentials) // in-process login; jar captures the session
|
|
16
|
+
*
|
|
17
|
+
* const www = await serveTestApp(app)
|
|
18
|
+
* const browser = await chromium.launch()
|
|
19
|
+
* const page = await browser.newPage({
|
|
20
|
+
* extraHTTPHeaders: { Cookie: cookies.header() }, // the session crosses into the browser
|
|
21
|
+
* })
|
|
22
|
+
* await page.goto(e2eUrl<typeof app>(www.baseUrl, "/dashboard")) // typo'd path won't compile
|
|
23
|
+
* await www.stop()
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import type { Server } from "@nifrajs/core/server";
|
|
27
|
+
/** The minimal shape a nifra `server()` app satisfies - its own `fetch`. */
|
|
28
|
+
export interface E2EApp {
|
|
29
|
+
fetch(request: Request): Response | Promise<Response>;
|
|
30
|
+
}
|
|
31
|
+
/** Every route path the app declares - constrains `e2eUrl`, so a wrong path is a type error. */
|
|
32
|
+
export type E2EPaths<App> = App extends Server<infer R, infer _Ctx> ? keyof R & string : never;
|
|
33
|
+
export interface ServeTestAppOptions {
|
|
34
|
+
/** Port to bind. Default `0` (ephemeral - read the real one off {@link ServedTestApp.baseUrl}). */
|
|
35
|
+
readonly port?: number;
|
|
36
|
+
/** Interface to bind. Default `"127.0.0.1"`. */
|
|
37
|
+
readonly hostname?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ServedTestApp {
|
|
40
|
+
/** Origin serving the app, e.g. `"http://127.0.0.1:43127"`. Hand it to {@link e2eUrl}. */
|
|
41
|
+
readonly baseUrl: string;
|
|
42
|
+
/** Stop accepting connections and drain in-flight requests. Idempotent. */
|
|
43
|
+
readonly stop: () => Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Serve an app on an ephemeral port for one browser test. The server is `@nifrajs/node`
|
|
47
|
+
* (an optional peer - install it in devDependencies); when it is absent this throws a plain
|
|
48
|
+
* error naming the missing package instead of a module-resolution crash.
|
|
49
|
+
*/
|
|
50
|
+
export declare function serveTestApp(app: E2EApp, options?: ServeTestAppOptions): Promise<ServedTestApp>;
|
|
51
|
+
/**
|
|
52
|
+
* Join `baseUrl` and a declared route path. The path is checked against the app's registry, so
|
|
53
|
+
* `page.goto(e2eUrl<typeof app>(www.baseUrl, "/dashbord"))` fails typecheck instead of 404ing
|
|
54
|
+
* mid-suite - the same guarantee `formFor` gives form fields.
|
|
55
|
+
*/
|
|
56
|
+
export declare function e2eUrl<App>(baseUrl: string, path: E2EPaths<App>): string;
|
|
57
|
+
/**
|
|
58
|
+
* Build a real WebSocket URL for an adapter-backed test server. The path uses the same-origin guard as
|
|
59
|
+
* {@link e2eUrl}; `http`/`https` are translated to `ws`/`wss` so callers cannot accidentally dial an
|
|
60
|
+
* HTTP URL with a WebSocket client or escape the test server origin.
|
|
61
|
+
*/
|
|
62
|
+
export declare function e2eWebSocket<App>(baseUrl: string, path: E2EPaths<App>): string;
|
|
63
|
+
//# sourceMappingURL=e2e.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.d.ts","sourceRoot":"","sources":["../src/e2e.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAA;AAIlD,4EAA4E;AAC5E,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;CACtD;AAED,gGAAgG;AAChG,MAAM,MAAM,QAAQ,CAAC,GAAG,IAAI,GAAG,SAAS,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,MAAM,GAAG,KAAK,CAAA;AAE9F,MAAM,WAAW,mBAAmB;IAClC,mGAAmG;IACnG,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,2EAA2E;IAC3E,QAAQ,CAAC,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACnC;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CAexB;AAaD;;;;GAIG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,MAAM,CAExE;AAID;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,GAAG,MAAM,CAQ9E"}
|
package/dist/e2e.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { isSameOriginPath } from "@nifrajs/core/server";
|
|
2
|
+
/**
|
|
3
|
+
* Serve an app on an ephemeral port for one browser test. The server is `@nifrajs/node`
|
|
4
|
+
* (an optional peer - install it in devDependencies); when it is absent this throws a plain
|
|
5
|
+
* error naming the missing package instead of a module-resolution crash.
|
|
6
|
+
*/
|
|
7
|
+
export async function serveTestApp(app, options = {}) {
|
|
8
|
+
let serve;
|
|
9
|
+
try {
|
|
10
|
+
;
|
|
11
|
+
({ serve } = await import("@nifrajs/node"));
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
throw new Error("@nifrajs/testing/e2e: serveTestApp needs the @nifrajs/node package - add it to devDependencies");
|
|
15
|
+
}
|
|
16
|
+
const hostname = options.hostname ?? "127.0.0.1";
|
|
17
|
+
const running = await serve(app, { port: options.port ?? 0, hostname });
|
|
18
|
+
return {
|
|
19
|
+
baseUrl: `http://${hostname}:${running.port}`,
|
|
20
|
+
stop: () => running.stop(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** `path` on the test app's origin, refused unless it is a same-origin absolute path. */
|
|
24
|
+
function onTestAppOrigin(baseUrl, path, label) {
|
|
25
|
+
const base = new URL(baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`);
|
|
26
|
+
const resolved = new URL(path, base);
|
|
27
|
+
// The origin compare also holds if the path rule ever admits a form the URL parser re-reads.
|
|
28
|
+
if (!isSameOriginPath(path) || resolved.origin !== base.origin) {
|
|
29
|
+
throw new TypeError(`@nifrajs/testing/e2e: ${label} must be a same-origin absolute path`);
|
|
30
|
+
}
|
|
31
|
+
return resolved;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Join `baseUrl` and a declared route path. The path is checked against the app's registry, so
|
|
35
|
+
* `page.goto(e2eUrl<typeof app>(www.baseUrl, "/dashbord"))` fails typecheck instead of 404ing
|
|
36
|
+
* mid-suite - the same guarantee `formFor` gives form fields.
|
|
37
|
+
*/
|
|
38
|
+
export function e2eUrl(baseUrl, path) {
|
|
39
|
+
return onTestAppOrigin(baseUrl, path, "path").href;
|
|
40
|
+
}
|
|
41
|
+
const WEB_SOCKET_BASES = new Set(["http:", "https:", "ws:", "wss:"]);
|
|
42
|
+
/**
|
|
43
|
+
* Build a real WebSocket URL for an adapter-backed test server. The path uses the same-origin guard as
|
|
44
|
+
* {@link e2eUrl}; `http`/`https` are translated to `ws`/`wss` so callers cannot accidentally dial an
|
|
45
|
+
* HTTP URL with a WebSocket client or escape the test server origin.
|
|
46
|
+
*/
|
|
47
|
+
export function e2eWebSocket(baseUrl, path) {
|
|
48
|
+
const resolved = onTestAppOrigin(baseUrl, path, "WebSocket path");
|
|
49
|
+
if (!WEB_SOCKET_BASES.has(resolved.protocol)) {
|
|
50
|
+
throw new TypeError("@nifrajs/testing/e2e: unsupported WebSocket base URL protocol");
|
|
51
|
+
}
|
|
52
|
+
resolved.protocol =
|
|
53
|
+
resolved.protocol === "https:" || resolved.protocol === "wss:" ? "wss:" : "ws:";
|
|
54
|
+
return resolved.href;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=e2e.js.map
|
package/dist/e2e.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2e.js","sourceRoot":"","sources":["../src/e2e.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAyBvD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,UAA+B,EAAE;IAEjC,IAAI,KAAkE,CAAA;IACtE,IAAI,CAAC;QACH,CAAC;QAAA,CAAC,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC,CAAA;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,gGAAgG,CACjG,CAAA;IACH,CAAC;IACD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,WAAW,CAAA;IAChD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAA;IACvE,OAAO;QACL,OAAO,EAAE,UAAU,QAAQ,IAAI,OAAO,CAAC,IAAI,EAAE;QAC7C,IAAI,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE;KAC3B,CAAA;AACH,CAAC;AAED,yFAAyF;AACzF,SAAS,eAAe,CAAC,OAAe,EAAE,IAAY,EAAE,KAAa;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,GAAG,CAAC,CAAA;IACrE,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACpC,6FAA6F;IAC7F,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/D,MAAM,IAAI,SAAS,CAAC,yBAAyB,KAAK,sCAAsC,CAAC,CAAA;IAC3F,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,MAAM,CAAM,OAAe,EAAE,IAAmB;IAC9D,OAAO,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,CAAA;AACpD,CAAC;AAED,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAA;AAEzF;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAM,OAAe,EAAE,IAAmB;IACpE,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,EAAE,gBAAgB,CAAC,CAAA;IACjE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,SAAS,CAAC,+DAA+D,CAAC,CAAA;IACtF,CAAC;IACD,QAAQ,CAAC,QAAQ;QACf,QAAQ,CAAC,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAA;IACjF,OAAO,QAAQ,CAAC,IAAI,CAAA;AACtB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,16 +7,18 @@
|
|
|
7
7
|
* import { testSession } from "@nifrajs/testing"
|
|
8
8
|
* const { client, cookies } = testSession<typeof app>(app)
|
|
9
9
|
*/
|
|
10
|
-
export { AdversarialContractError, type AdversarialContractOptions, type AdversarialContractReport, type AdversarialContractResult, assertAdversarialContract, type ContractCaseContext, type ContractCaseKind, type ContractCoverageGap, type ContractCoverageGapCode, type ContractReplay, type ContractRuntime, type ContractTarget, type ContractTestApp, type ContractWitness, runAdversarialContract, } from "./adversarial.js";
|
|
10
|
+
export { AdversarialContractError, type AdversarialContractOptions, type AdversarialContractReport, type AdversarialContractResult, assertAdversarialContract, type ContractAuthContext, type ContractCaseContext, type ContractCaseKind, type ContractCoverageGap, type ContractCoverageGapCode, type ContractExpectedResponse, type ContractReplay, type ContractRuntime, type ContractTarget, type ContractTestApp, type ContractWitness, runAdversarialContract, } from "./adversarial.js";
|
|
11
11
|
export { type CertifiableDeploymentAdapter, type CertifiableDescriptorAdapter, type CertifiableModelGateway, deploymentAdapterCertificationProfile, deploymentCertificationProfile, gatewayCertificationProfile, modelGatewayCertificationProfile, registryCertificationProfile, } from "./agent-certification.js";
|
|
12
12
|
export { type AgentEvalCase, type AgentEvalComponentEvidence, type AgentEvalCompositionOptions, type AgentEvalCompositionReport, AgentEvalRegressionError, type AgentEvalReport, type AgentEvalSuite, type AgentEvalSuiteSpec, type AgentFailureMatrixCase, AgentFailureMatrixError, type AgentFailureMatrixKind, type AgentFailureMatrixReport, assertAgentEval, assertAgentEvalBaseline, assertAgentFailureMatrix, type BaselineComparison, type BaselineOptions, type CaseComparison, type CaseResult, type ComparisonCode, compareAgentEvalBaseline, defineAgentEvalSuite, parseRubricVerdict, type RubricShape, type RubricSpec, type RubricVerdict, runAgentEvalComposition, runAgentFailureMatrix, type ScoreTolerance, } from "./agent-eval.js";
|
|
13
|
-
export { AdapterCertificationError, type AdapterCertificationProfile, type AdapterCertificationReport, assertAdapterCertification, type CertifiableCacheEntry, type CertifiableCacheStore, type CertifiableDomainEvent, type CertifiableEventDeliveryAdapter, type CertifiableEventRecord, type CertifiableJobStore, type CertifiableRuntimeAdapter, type CertifiableRuntimeServer, type CertifiableStorageAdapter, type CertificationCapabilityEvidence, type CertificationCheck, type CertificationCheckEvidence, cacheStoreCertificationProfile, certifyAdapter, defineCertificationProfile, eventDeliveryCertificationProfile, jobStoreCertificationProfile, runtimeAdapterCertificationProfile, storageAdapterCertificationProfile, verifyAdapterCertification, } from "./certification.js";
|
|
13
|
+
export { AdapterCertificationError, type AdapterCertificationProfile, type AdapterCertificationReport, assertAdapterCertification, type CertifiableCacheEntry, type CertifiableCacheStore, type CertifiableDomainEvent, type CertifiableEventDeliveryAdapter, type CertifiableEventRecord, type CertifiableJobStore, type CertifiableRuntimeAdapter, type CertifiableRuntimeServer, type CertifiableStorageAdapter, type CertificationCapabilityEvidence, type CertificationCheck, type CertificationCheckEvidence, type CertificationTarget, cacheStoreCertificationProfile, certifyAdapter, defineCertificationProfile, eventDeliveryCertificationProfile, jobStoreCertificationProfile, runtimeAdapterCertificationProfile, storageAdapterCertificationProfile, verifyAdapterCertification, } from "./certification.js";
|
|
14
14
|
export { type ContractLabHandler, type ContractLabRuntimeAdapter, type ContractLabServer, type ContractLabWitness, contractLabWitnesses, createReferenceContractLabHandler, runContractLab, runContractLabOverHttp, runContractLabThroughAdapter, } from "./contract-lab.js";
|
|
15
15
|
export { type CookieJar, cookieJar } from "./cookies.js";
|
|
16
|
+
export { assertDataAdapterConformance, DataAdapterConformanceError, type DataAdapterConformanceReport, type DataAdapterConformanceTarget, type DataConformanceCheck, type DataConformanceFailure, type DataConformancePage, type DataConformanceScope, type DataConformanceTransaction, runDataAdapterConformance, } from "./data-conformance.js";
|
|
16
17
|
export { createFailureLab, type FailureDirective, type FailureEvidence, FailureInjectedError, type FailureKind, type FailureLab, type FailureLabOptions, type FailureReplay, type FailureScenario, type FailureScenarioReport, runFailureScenario, } from "./failure-lab.js";
|
|
17
18
|
export { defineFaultProfile, type FaultProfile, type FaultProfileFault, type FaultProfileFaultKind, type FaultProfileReport, type FaultProfileScenario, type FaultProfileScenarioReport, type RunFaultProfileOptions, referenceFaultProfile, runFaultProfile, } from "./fault-profile.js";
|
|
18
19
|
export { type EffectLedger, type IdempotencyDivergence, type IdempotencyProof, proveIdempotency, } from "./idempotency.js";
|
|
19
20
|
export { assertIncidentReplays, type CapturedRequest, type CapturedRequestInput, type CaptureIncidentOptions, captureIncident, type GenerateRegressionTestOptions, generateRegressionTest, type IncidentCapsule, IncidentReplayError, type IncidentReplayResult, type ReplayIncidentOptions, redactForEmission, replayIncident, shapeOf, } from "./incident.js";
|
|
21
|
+
export { assertPredictionLab, PREDICTION_LAB_SEED, type PredictionLabContext, type PredictionLabOptions, type PredictionLabReplay, type PredictionLabReport, type PredictionLabResult, type PredictionLabTarget, predictionLabCaseIds, runPredictionLab, toPredictionLabContext, } from "./prediction-lab.js";
|
|
20
22
|
export { type AppLike, type TestSession, type TestSessionOptions, testSession } from "./session.js";
|
|
21
23
|
export { httpToolAdapter, inProcessToolAdapter, mcpToolAdapter, testToolAdapter, } from "./tool-contract.js";
|
|
22
24
|
export { assertTrajectoryInvariants, type CreateTrajectoryTranscriptOptions, checkTrajectoryInvariants, createTrajectoryTranscript, type ReplayTrajectoryOptions, recordTrajectory, replayTrajectory, runTrajectory, type TrajectoryInvariantId, type TrajectoryInvariantOptions, type TrajectoryInvariantResult, type TrajectoryReplayResult, type TrajectoryRun, type TrajectoryTranscript, trajectoryRegressionId, } from "./trajectory.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -13,10 +13,12 @@ export { AgentEvalRegressionError, AgentFailureMatrixError, assertAgentEval, ass
|
|
|
13
13
|
export { AdapterCertificationError, assertAdapterCertification, cacheStoreCertificationProfile, certifyAdapter, defineCertificationProfile, eventDeliveryCertificationProfile, jobStoreCertificationProfile, runtimeAdapterCertificationProfile, storageAdapterCertificationProfile, verifyAdapterCertification, } from "./certification.js";
|
|
14
14
|
export { contractLabWitnesses, createReferenceContractLabHandler, runContractLab, runContractLabOverHttp, runContractLabThroughAdapter, } from "./contract-lab.js";
|
|
15
15
|
export { cookieJar } from "./cookies.js";
|
|
16
|
+
export { assertDataAdapterConformance, DataAdapterConformanceError, runDataAdapterConformance, } from "./data-conformance.js";
|
|
16
17
|
export { createFailureLab, FailureInjectedError, runFailureScenario, } from "./failure-lab.js";
|
|
17
18
|
export { defineFaultProfile, referenceFaultProfile, runFaultProfile, } from "./fault-profile.js";
|
|
18
19
|
export { proveIdempotency, } from "./idempotency.js";
|
|
19
20
|
export { assertIncidentReplays, captureIncident, generateRegressionTest, IncidentReplayError, redactForEmission, replayIncident, shapeOf, } from "./incident.js";
|
|
21
|
+
export { assertPredictionLab, PREDICTION_LAB_SEED, predictionLabCaseIds, runPredictionLab, toPredictionLabContext, } from "./prediction-lab.js";
|
|
20
22
|
export { testSession } from "./session.js";
|
|
21
23
|
export { httpToolAdapter, inProcessToolAdapter, mcpToolAdapter, testToolAdapter, } from "./tool-contract.js";
|
|
22
24
|
export { assertTrajectoryInvariants, checkTrajectoryInvariants, createTrajectoryTranscript, recordTrajectory, replayTrajectory, runTrajectory, trajectoryRegressionId, } from "./trajectory.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,wBAAwB,EAIxB,yBAAyB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,wBAAwB,EAIxB,yBAAyB,EAYzB,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,qCAAqC,EACrC,8BAA8B,EAC9B,2BAA2B,EAC3B,gCAAgC,EAChC,4BAA4B,GAC7B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAKL,wBAAwB,EAKxB,uBAAuB,EAGvB,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EAMxB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAIlB,uBAAuB,EACvB,qBAAqB,GAEtB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,yBAAyB,EAGzB,0BAA0B,EAc1B,8BAA8B,EAC9B,cAAc,EACd,0BAA0B,EAC1B,iCAAiC,EACjC,4BAA4B,EAC5B,kCAAkC,EAClC,kCAAkC,EAClC,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAKL,oBAAoB,EACpB,iCAAiC,EACjC,cAAc,EACd,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAkB,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAQ3B,yBAAyB,GAC1B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACL,gBAAgB,EAGhB,oBAAoB,EAOpB,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,kBAAkB,EAQlB,qBAAqB,EACrB,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAIL,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,qBAAqB,EAIrB,eAAe,EAEf,sBAAsB,EAEtB,mBAAmB,EAGnB,iBAAiB,EACjB,cAAc,EACd,OAAO,GACR,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EAOnB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAA2D,WAAW,EAAE,MAAM,cAAc,CAAA;AACnG,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,0BAA0B,EAE1B,yBAAyB,EACzB,0BAA0B,EAE1B,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EAOb,sBAAsB,GACvB,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeded hostile corpus for predictions and projections - the prediction-side sibling of
|
|
3
|
+
* `adversarial.ts`.
|
|
4
|
+
*
|
|
5
|
+
* `adversarial.ts` proves HTTP body/query/response contracts with validator-proven hostile
|
|
6
|
+
* mutations. This module proves the same shaped guarantees one layer up: the `@nifrajs/webmcp`
|
|
7
|
+
* prediction store (stale versions, expiry, prototype-grafting patches, non-atomic patches,
|
|
8
|
+
* commit conflicts, reconcile/tool rollback) and the WebMCP-plus-MCP projection of one
|
|
9
|
+
* capability (the same witness accepted or rejected identically on both surfaces).
|
|
10
|
+
*
|
|
11
|
+
* Every case has a stable ID, every run carries its replay seed, and every clock is injected -
|
|
12
|
+
* nothing reads `Date.now` or `crypto.randomUUID` implicitly. `only` replays a subset by ID.
|
|
13
|
+
*
|
|
14
|
+
* Deliberately out of scope: A2A and AG-UI projections. Neither package exposes a same-contract
|
|
15
|
+
* projection from a tool/capability (`a2a` has `agentCard`/`mountA2A` at the protocol level; there
|
|
16
|
+
* is no `capability -> a2a/ag-ui` seam), so a parity case here would invent the seam it claims to
|
|
17
|
+
* test. Proposing such a seam needs consumer evidence first (N7), not a lab that assumes it.
|
|
18
|
+
*/
|
|
19
|
+
export type PredictionLabTarget = "prediction" | "projection";
|
|
20
|
+
export interface PredictionLabContext {
|
|
21
|
+
readonly seed: number;
|
|
22
|
+
readonly caseId: string;
|
|
23
|
+
readonly target: PredictionLabTarget;
|
|
24
|
+
readonly mutation?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface PredictionLabReplay {
|
|
27
|
+
readonly seed: number;
|
|
28
|
+
readonly caseId: string;
|
|
29
|
+
}
|
|
30
|
+
export interface PredictionLabResult {
|
|
31
|
+
readonly id: string;
|
|
32
|
+
readonly target: PredictionLabTarget;
|
|
33
|
+
readonly mutation?: string;
|
|
34
|
+
readonly ok: boolean;
|
|
35
|
+
readonly message: string;
|
|
36
|
+
readonly replay: PredictionLabReplay;
|
|
37
|
+
}
|
|
38
|
+
export interface PredictionLabReport {
|
|
39
|
+
readonly ok: boolean;
|
|
40
|
+
readonly seed: number;
|
|
41
|
+
readonly results: readonly PredictionLabResult[];
|
|
42
|
+
readonly failures: readonly PredictionLabResult[];
|
|
43
|
+
readonly counts: {
|
|
44
|
+
readonly passed: number;
|
|
45
|
+
readonly failed: number;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface PredictionLabOptions {
|
|
49
|
+
/** Replayable seed. Prediction IDs and clocks derive from it deterministically. */
|
|
50
|
+
readonly seed?: number;
|
|
51
|
+
/** Replay only these stable case IDs. */
|
|
52
|
+
readonly only?: string | readonly string[];
|
|
53
|
+
}
|
|
54
|
+
export declare const PREDICTION_LAB_SEED = 1347568964;
|
|
55
|
+
export declare function runPredictionLab(options?: PredictionLabOptions): Promise<PredictionLabReport>;
|
|
56
|
+
/** Run the lab and throw a joined error on failure - the `assertAdversarialContract` shape. */
|
|
57
|
+
export declare function assertPredictionLab(options?: PredictionLabOptions): Promise<PredictionLabReport>;
|
|
58
|
+
/** Stable case IDs in run order. */
|
|
59
|
+
export declare const predictionLabCaseIds: readonly string[];
|
|
60
|
+
export declare function toPredictionLabContext(seed: number, labCase: {
|
|
61
|
+
readonly id: string;
|
|
62
|
+
readonly target: PredictionLabTarget;
|
|
63
|
+
readonly mutation?: string;
|
|
64
|
+
}): PredictionLabContext;
|
|
65
|
+
//# sourceMappingURL=prediction-lab.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prediction-lab.d.ts","sourceRoot":"","sources":["../src/prediction-lab.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAeH,MAAM,MAAM,mBAAmB,GAAG,YAAY,GAAG,YAAY,CAAA;AAE7D,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAA;IAChD,QAAQ,CAAC,QAAQ,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACjD,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACtE;AAED,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,yCAAyC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CAC3C;AAED,eAAO,MAAM,mBAAmB,aAAgB,CAAA;AAohBhD,wBAAsB,gBAAgB,CACpC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAqD9B;AAED,+FAA+F;AAC/F,wBAAsB,mBAAmB,CACvC,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,mBAAmB,CAAC,CAQ9B;AAED,oCAAoC;AACpC,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAEjD,CAAA;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;IACP,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAC3B,GACA,oBAAoB,CAOtB"}
|