@nifrajs/testing 3.5.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.
@@ -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
@@ -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,12 +7,13 @@
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
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";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,wBAAwB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,yBAAyB,EAC9B,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,sBAAsB,GACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,EACjC,KAAK,uBAAuB,EAC5B,qCAAqC,EACrC,8BAA8B,EAC9B,2BAA2B,EAC3B,gCAAgC,EAChC,4BAA4B,GAC7B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,wBAAwB,EACxB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,eAAe,EACf,uBAAuB,EACvB,wBAAwB,EACxB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,wBAAwB,EACxB,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACL,yBAAyB,EACzB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,0BAA0B,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,+BAA+B,EACpC,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,KAAK,+BAA+B,EACpC,KAAK,kBAAkB,EACvB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,8BAA8B,EAC9B,cAAc,EACd,0BAA0B,EAC1B,iCAAiC,EACjC,4BAA4B,EAC5B,kCAAkC,EAClC,kCAAkC,EAClC,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,oBAAoB,EACpB,iCAAiC,EACjC,cAAc,EACd,sBAAsB,EACtB,4BAA4B,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,KAAK,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,EACL,gBAAgB,EAChB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,oBAAoB,EACpB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,kBAAkB,GACnB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,kBAAkB,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,EAC3B,qBAAqB,EACrB,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACL,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,eAAe,EACf,KAAK,6BAA6B,EAClC,sBAAsB,EACtB,KAAK,eAAe,EACpB,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,iBAAiB,EACjB,cAAc,EACd,OAAO,GACR,MAAM,eAAe,CAAA;AACtB,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,kBAAkB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AACnG,OAAO,EACL,eAAe,EACf,oBAAoB,EACpB,cAAc,EACd,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACL,0BAA0B,EAC1B,KAAK,iCAAiC,EACtC,yBAAyB,EACzB,0BAA0B,EAC1B,KAAK,uBAAuB,EAC5B,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,KAAK,qBAAqB,EAC1B,KAAK,0BAA0B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,sBAAsB,GACvB,MAAM,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ 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";
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,EAUzB,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,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"}
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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nifrajs/testing",
3
- "version": "3.5.0",
3
+ "version": "4.0.0",
4
4
  "description": "Contract-derived adversarial tests, runtime-matrix response conformance, and cookie-aware in-process sessions for Nifra apps.",
5
5
  "keywords": [
6
6
  "bun",
@@ -14,6 +14,9 @@
14
14
  "adversarial"
15
15
  ],
16
16
  "type": "module",
17
+ "nifra": {
18
+ "environment": "library"
19
+ },
17
20
  "main": "./dist/index.js",
18
21
  "module": "./dist/index.js",
19
22
  "types": "./dist/index.d.ts",
@@ -37,6 +40,11 @@
37
40
  "bun": "./src/zod.ts",
38
41
  "types": "./dist/zod.d.ts",
39
42
  "default": "./dist/zod.js"
43
+ },
44
+ "./e2e": {
45
+ "bun": "./src/e2e.ts",
46
+ "types": "./dist/e2e.d.ts",
47
+ "default": "./dist/e2e.js"
40
48
  }
41
49
  },
42
50
  "files": [
@@ -49,19 +57,23 @@
49
57
  },
50
58
  "license": "MIT",
51
59
  "dependencies": {
52
- "@nifrajs/client": "3.5.0",
53
- "@nifrajs/agent": "3.5.0",
54
- "@nifrajs/core": "3.5.0",
55
- "@nifrajs/mcp": "3.5.0",
56
- "@nifrajs/mock": "3.5.0",
57
- "@nifrajs/webmcp": "3.5.0"
60
+ "@nifrajs/client": "4.0.0",
61
+ "@nifrajs/agent": "4.0.0",
62
+ "@nifrajs/core": "4.0.0",
63
+ "@nifrajs/mcp": "4.0.0",
64
+ "@nifrajs/mock": "4.0.0",
65
+ "@nifrajs/webmcp": "4.0.0"
58
66
  },
59
67
  "peerDependencies": {
60
- "zod": ">=4.0.0"
68
+ "zod": ">=4.0.0",
69
+ "@nifrajs/node": ">=3.5.0"
61
70
  },
62
71
  "peerDependenciesMeta": {
63
72
  "zod": {
64
73
  "optional": true
74
+ },
75
+ "@nifrajs/node": {
76
+ "optional": true
65
77
  }
66
78
  },
67
79
  "publishConfig": {