@lingxia/test 0.17.0 → 0.19.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/dist/clock.d.ts +30 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +99 -0
- package/dist/clock.js.map +1 -0
- package/dist/coverage.d.ts +25 -0
- package/dist/coverage.d.ts.map +1 -0
- package/dist/coverage.js +92 -0
- package/dist/coverage.js.map +1 -0
- package/dist/deadline.d.ts +82 -0
- package/dist/deadline.d.ts.map +1 -0
- package/dist/deadline.js +184 -0
- package/dist/deadline.js.map +1 -0
- package/dist/dialogs.d.ts +28 -0
- package/dist/dialogs.d.ts.map +1 -0
- package/dist/dialogs.js +74 -0
- package/dist/dialogs.js.map +1 -0
- package/dist/equal.d.ts +28 -0
- package/dist/equal.d.ts.map +1 -0
- package/dist/equal.js +149 -0
- package/dist/equal.js.map +1 -0
- package/dist/errors.d.ts +8 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +37 -0
- package/dist/errors.js.map +1 -0
- package/dist/expect.d.ts +35 -7
- package/dist/expect.d.ts.map +1 -1
- package/dist/expect.js +216 -68
- package/dist/expect.js.map +1 -1
- package/dist/fixture.d.ts +205 -40
- package/dist/fixture.d.ts.map +1 -1
- package/dist/fixture.js +1178 -156
- package/dist/fixture.js.map +1 -1
- package/dist/format.d.ts +2 -0
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +78 -0
- package/dist/format.js.map +1 -1
- package/dist/host-types.d.ts +65 -0
- package/dist/host-types.d.ts.map +1 -0
- package/dist/host-types.js +2 -0
- package/dist/host-types.js.map +1 -0
- package/dist/host.d.ts +20 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +34 -2
- package/dist/host.js.map +1 -1
- package/dist/ids.d.ts +16 -0
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js +38 -3
- package/dist/ids.js.map +1 -1
- package/dist/index.d.ts +5 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/index.js.map +1 -1
- package/dist/json-result.d.ts +3 -0
- package/dist/json-result.d.ts.map +1 -0
- package/dist/json-result.js +62 -0
- package/dist/json-result.js.map +1 -0
- package/dist/junit.d.ts +1 -1
- package/dist/junit.d.ts.map +1 -1
- package/dist/junit.js +40 -5
- package/dist/junit.js.map +1 -1
- package/dist/locator.d.ts +116 -7
- package/dist/locator.d.ts.map +1 -1
- package/dist/locator.js +444 -58
- package/dist/locator.js.map +1 -1
- package/dist/mock.d.ts +43 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +162 -0
- package/dist/mock.js.map +1 -0
- package/dist/network.d.ts +68 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +287 -0
- package/dist/network.js.map +1 -0
- package/dist/openapi.d.ts +127 -0
- package/dist/openapi.d.ts.map +1 -0
- package/dist/openapi.js +414 -0
- package/dist/openapi.js.map +1 -0
- package/dist/pending.d.ts +84 -0
- package/dist/pending.d.ts.map +1 -0
- package/dist/pending.js +311 -0
- package/dist/pending.js.map +1 -0
- package/dist/redact.d.ts +41 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +168 -0
- package/dist/redact.js.map +1 -0
- package/dist/remote.d.ts +32 -0
- package/dist/remote.d.ts.map +1 -0
- package/dist/remote.js +117 -0
- package/dist/remote.js.map +1 -0
- package/dist/report-extras.d.ts +16 -0
- package/dist/report-extras.d.ts.map +1 -0
- package/dist/report-extras.js +125 -0
- package/dist/report-extras.js.map +1 -0
- package/dist/report-types.d.ts +428 -0
- package/dist/report-types.d.ts.map +1 -0
- package/dist/report-types.js +6 -0
- package/dist/report-types.js.map +1 -0
- package/dist/report.d.ts +15 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +196 -19
- package/dist/report.js.map +1 -1
- package/dist/runner.d.ts +13 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +11 -0
- package/dist/runner.js.map +1 -0
- package/dist/runtime.d.ts +55 -4
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1500 -139
- package/dist/runtime.js.map +1 -1
- package/dist/schema.d.ts +29 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +463 -0
- package/dist/schema.js.map +1 -0
- package/dist/spec-api.d.ts +10 -2
- package/dist/spec-api.d.ts.map +1 -1
- package/dist/tags.d.ts +26 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +78 -0
- package/dist/tags.js.map +1 -0
- package/dist/types.d.ts +863 -168
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +18 -5
- package/schemas/lxdev.schema.json +50 -0
- package/schemas/mock-config.schema.json +21 -0
- package/schemas/scenario.schema.json +180 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI contract checks for `lxdev test --openapi`: find the operation a
|
|
3
|
+
* Logic `fetch` hit, and validate its JSON response against the documented
|
|
4
|
+
* schema. lxdev reads and parses the files; this module only sees JSON.
|
|
5
|
+
*/
|
|
6
|
+
import type { NetworkResponseRecord } from "@lingxia/types/automation";
|
|
7
|
+
import { type Dialect, type SchemaIssue } from "./schema.js";
|
|
8
|
+
import type { ContractIssue, OpenApiSummary } from "./report-types.js";
|
|
9
|
+
export interface OpenApiSource {
|
|
10
|
+
/** The file name, as lxdev read it. */
|
|
11
|
+
name: string;
|
|
12
|
+
doc: unknown;
|
|
13
|
+
}
|
|
14
|
+
/** `toMatchSchema` target: a component schema name, a `#/…` ref, or `{ ref, document? }`. */
|
|
15
|
+
export type SchemaTarget = string | {
|
|
16
|
+
ref: string;
|
|
17
|
+
document?: string;
|
|
18
|
+
};
|
|
19
|
+
interface Segment {
|
|
20
|
+
literal?: string;
|
|
21
|
+
}
|
|
22
|
+
interface Operation {
|
|
23
|
+
doc: LoadedDocument;
|
|
24
|
+
method: string;
|
|
25
|
+
template: string;
|
|
26
|
+
segments: Segment[];
|
|
27
|
+
literals: number;
|
|
28
|
+
bases: string[];
|
|
29
|
+
operationId?: string;
|
|
30
|
+
responses: Record<string, unknown>;
|
|
31
|
+
pointer: string;
|
|
32
|
+
}
|
|
33
|
+
interface LoadedDocument {
|
|
34
|
+
name: string;
|
|
35
|
+
root: Record<string, unknown>;
|
|
36
|
+
dialect: Dialect;
|
|
37
|
+
version: string;
|
|
38
|
+
title?: string;
|
|
39
|
+
operations: number;
|
|
40
|
+
}
|
|
41
|
+
/** The outcome of one captured response. */
|
|
42
|
+
export type ContractCheck = {
|
|
43
|
+
kind: "unmatched";
|
|
44
|
+
method: string;
|
|
45
|
+
path: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: "undocumented";
|
|
48
|
+
operation: string;
|
|
49
|
+
status: number;
|
|
50
|
+
} | {
|
|
51
|
+
kind: "skipped";
|
|
52
|
+
operation: string;
|
|
53
|
+
status: number;
|
|
54
|
+
reason: "no_schema" | "not_json" | "empty" | "truncated";
|
|
55
|
+
} | {
|
|
56
|
+
kind: "valid";
|
|
57
|
+
operation: string;
|
|
58
|
+
status: number;
|
|
59
|
+
schema: string;
|
|
60
|
+
} | {
|
|
61
|
+
kind: "invalid";
|
|
62
|
+
operation: string;
|
|
63
|
+
status: number;
|
|
64
|
+
schema: string;
|
|
65
|
+
issues: SchemaIssue[];
|
|
66
|
+
};
|
|
67
|
+
export declare class OpenApiIndex {
|
|
68
|
+
readonly documents: LoadedDocument[];
|
|
69
|
+
private readonly operations;
|
|
70
|
+
constructor(sources: readonly OpenApiSource[]);
|
|
71
|
+
/**
|
|
72
|
+
* The operation `method url` hits: server base path, then the path
|
|
73
|
+
* template (a `{param}` is one non-empty segment). Hosts are not compared,
|
|
74
|
+
* so the same contract checks staging and production. A concrete path
|
|
75
|
+
* beats a templated one.
|
|
76
|
+
*/
|
|
77
|
+
match(method: string, url: string): Operation | undefined;
|
|
78
|
+
/** Check one captured response against the contract. */
|
|
79
|
+
check(record: Pick<NetworkResponseRecord, "method" | "url" | "status" | "contentType" | "body" | "bodyTruncated">): ContractCheck;
|
|
80
|
+
/** Find a `toMatchSchema` target, or throw saying what exists. */
|
|
81
|
+
resolveTarget(target: SchemaTarget): {
|
|
82
|
+
schema: unknown;
|
|
83
|
+
pointer: string;
|
|
84
|
+
doc: LoadedDocument;
|
|
85
|
+
};
|
|
86
|
+
/** Validate `value` against a target; empty when it matches. */
|
|
87
|
+
validate(value: unknown, target: SchemaTarget): {
|
|
88
|
+
issues: SchemaIssue[];
|
|
89
|
+
pointer: string;
|
|
90
|
+
document: string;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** The path of an absolute or relative URL, without query or fragment. */
|
|
94
|
+
export declare function pathOf(url: string): string;
|
|
95
|
+
/** `true` when `path` fits the template; a `{param}` takes one non-empty segment. */
|
|
96
|
+
export declare function templateMatches(segments: readonly Segment[], path: string | undefined): boolean;
|
|
97
|
+
/** Compile a path template for tests and tools. */
|
|
98
|
+
export declare function compileTemplate(template: string): Segment[];
|
|
99
|
+
/** The run's contract, for `toMatchSchema`; `undefined` without `--openapi`. */
|
|
100
|
+
export declare function activeOpenApi(): OpenApiIndex | undefined;
|
|
101
|
+
export declare function setActiveOpenApi(index: OpenApiIndex | undefined): void;
|
|
102
|
+
/** `control.openapi`: a JSON list of `{ name, doc }` lxdev parsed from the files. */
|
|
103
|
+
export declare function parseOpenApiControl(raw: string | undefined): OpenApiIndex | undefined;
|
|
104
|
+
/** Accumulates the run's `openapi` report section. */
|
|
105
|
+
export declare class ContractLedger {
|
|
106
|
+
readonly index: OpenApiIndex;
|
|
107
|
+
readonly summary: OpenApiSummary;
|
|
108
|
+
constructor(index: OpenApiIndex);
|
|
109
|
+
/**
|
|
110
|
+
* Check one spec's responses. Mismatches in routed responses (`route`,
|
|
111
|
+
* `patch`) are the spec's violations; the real server's are warnings.
|
|
112
|
+
*/
|
|
113
|
+
checkSpec(caseId: string, records: readonly NetworkResponseRecord[]): {
|
|
114
|
+
violations: ContractIssue[];
|
|
115
|
+
warnings: ContractIssue[];
|
|
116
|
+
checked: number;
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** The spec failure a routed contract violation produces. */
|
|
120
|
+
export declare class ContractError extends Error {
|
|
121
|
+
readonly name = "ContractError";
|
|
122
|
+
readonly code = "E_OPENAPI_CONTRACT";
|
|
123
|
+
constructor(violations: readonly ContractIssue[]);
|
|
124
|
+
}
|
|
125
|
+
export declare function describeViolations(violations: readonly ContractIssue[]): string;
|
|
126
|
+
export {};
|
|
127
|
+
//# sourceMappingURL=openapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
|
package/dist/openapi.js
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
import { formatIssues, resolvePointer, validateSchema, } from "./schema.js";
|
|
2
|
+
const METHODS = ["get", "put", "post", "delete", "options", "head", "patch", "trace"];
|
|
3
|
+
const JSON_TYPE = /^\s*(application|text)\/([^;\s]*\+)?json\s*(;|$)/i;
|
|
4
|
+
export class OpenApiIndex {
|
|
5
|
+
constructor(sources) {
|
|
6
|
+
this.operations = [];
|
|
7
|
+
this.documents = sources.map((source) => loadDocument(source));
|
|
8
|
+
for (const doc of this.documents) {
|
|
9
|
+
const paths = doc.root.paths;
|
|
10
|
+
if (!isObject(paths))
|
|
11
|
+
continue;
|
|
12
|
+
const docBases = basePaths(doc.root.servers);
|
|
13
|
+
for (const [template, rawItem] of Object.entries(paths)) {
|
|
14
|
+
const item = deref(doc.root, rawItem);
|
|
15
|
+
if (!isObject(item))
|
|
16
|
+
continue;
|
|
17
|
+
const bases = Array.isArray(item.servers) ? basePaths(item.servers) : docBases;
|
|
18
|
+
const segments = splitPath(template).map((part) => /^\{[^}]+\}$/.test(part) ? {} : { literal: part });
|
|
19
|
+
for (const method of METHODS) {
|
|
20
|
+
const operation = item[method];
|
|
21
|
+
if (!isObject(operation))
|
|
22
|
+
continue;
|
|
23
|
+
doc.operations += 1;
|
|
24
|
+
const opBases = Array.isArray(operation.servers) ? basePaths(operation.servers) : bases;
|
|
25
|
+
this.operations.push({
|
|
26
|
+
doc,
|
|
27
|
+
method: method.toUpperCase(),
|
|
28
|
+
template,
|
|
29
|
+
segments,
|
|
30
|
+
literals: segments.filter((segment) => segment.literal !== undefined).length,
|
|
31
|
+
bases: opBases,
|
|
32
|
+
operationId: typeof operation.operationId === "string" ? operation.operationId : undefined,
|
|
33
|
+
responses: isObject(operation.responses) ? operation.responses : {},
|
|
34
|
+
pointer: `#/paths/${escapePointer(template)}/${method}`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The operation `method url` hits: server base path, then the path
|
|
42
|
+
* template (a `{param}` is one non-empty segment). Hosts are not compared,
|
|
43
|
+
* so the same contract checks staging and production. A concrete path
|
|
44
|
+
* beats a templated one.
|
|
45
|
+
*/
|
|
46
|
+
match(method, url) {
|
|
47
|
+
const path = pathOf(url);
|
|
48
|
+
let best;
|
|
49
|
+
for (const operation of this.operations) {
|
|
50
|
+
if (operation.method !== method.toUpperCase())
|
|
51
|
+
continue;
|
|
52
|
+
if (!operation.bases.some((base) => templateMatches(operation.segments, stripBase(path, base))))
|
|
53
|
+
continue;
|
|
54
|
+
if (!best || operation.literals > best.literals)
|
|
55
|
+
best = operation;
|
|
56
|
+
}
|
|
57
|
+
return best;
|
|
58
|
+
}
|
|
59
|
+
/** Check one captured response against the contract. */
|
|
60
|
+
check(record) {
|
|
61
|
+
const operation = this.match(record.method, record.url);
|
|
62
|
+
if (!operation)
|
|
63
|
+
return { kind: "unmatched", method: record.method.toUpperCase(), path: pathOf(record.url) };
|
|
64
|
+
const label = `${operation.method} ${operation.template}`;
|
|
65
|
+
const found = responseFor(operation, record.status);
|
|
66
|
+
if (!found)
|
|
67
|
+
return { kind: "undocumented", operation: label, status: record.status };
|
|
68
|
+
const media = mediaFor(operation.doc.root, found.response, record.contentType);
|
|
69
|
+
if (!media) {
|
|
70
|
+
return { kind: "skipped", operation: label, status: record.status, reason: record.contentType && !JSON_TYPE.test(record.contentType) ? "not_json" : "no_schema" };
|
|
71
|
+
}
|
|
72
|
+
// Before `empty`: a body the capture bound omitted arrives as null.
|
|
73
|
+
if (record.bodyTruncated)
|
|
74
|
+
return { kind: "skipped", operation: label, status: record.status, reason: "truncated" };
|
|
75
|
+
if (record.body === null || record.body === "") {
|
|
76
|
+
return { kind: "skipped", operation: label, status: record.status, reason: "empty" };
|
|
77
|
+
}
|
|
78
|
+
let value;
|
|
79
|
+
try {
|
|
80
|
+
value = JSON.parse(record.body);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
kind: "invalid",
|
|
85
|
+
operation: label,
|
|
86
|
+
status: record.status,
|
|
87
|
+
schema: media.pointer,
|
|
88
|
+
issues: [{ path: "", message: `the body is not JSON: ${error.message}`, schema: media.pointer }],
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
const issues = validateSchema(value, media.schema, media.pointer, {
|
|
92
|
+
root: operation.doc.root,
|
|
93
|
+
dialect: operation.doc.dialect,
|
|
94
|
+
direction: "response",
|
|
95
|
+
});
|
|
96
|
+
return issues.length === 0
|
|
97
|
+
? { kind: "valid", operation: label, status: record.status, schema: media.pointer }
|
|
98
|
+
: { kind: "invalid", operation: label, status: record.status, schema: media.pointer, issues };
|
|
99
|
+
}
|
|
100
|
+
/** Find a `toMatchSchema` target, or throw saying what exists. */
|
|
101
|
+
resolveTarget(target) {
|
|
102
|
+
const ref = typeof target === "string"
|
|
103
|
+
? (target.startsWith("#") ? target : `#/components/schemas/${escapePointer(target)}`)
|
|
104
|
+
: target.ref;
|
|
105
|
+
const documentName = typeof target === "string" ? undefined : target.document;
|
|
106
|
+
if (typeof ref !== "string" || !ref.startsWith("#")) {
|
|
107
|
+
throw new TypeError("toMatchSchema takes a schema name, a '#/…' ref, or { ref: '#/…', document? }");
|
|
108
|
+
}
|
|
109
|
+
const docs = documentName === undefined
|
|
110
|
+
? this.documents
|
|
111
|
+
: this.documents.filter((doc) => doc.name === documentName || doc.name.endsWith(`/${documentName}`));
|
|
112
|
+
if (documentName !== undefined && docs.length === 0) {
|
|
113
|
+
throw new Error(`toMatchSchema: no --openapi document named ${JSON.stringify(documentName)} (loaded: ${this.documents.map((doc) => doc.name).join(", ")})`);
|
|
114
|
+
}
|
|
115
|
+
const hits = docs.filter((doc) => resolvePointer(doc.root, ref) !== undefined);
|
|
116
|
+
if (hits.length === 0) {
|
|
117
|
+
const known = this.documents.flatMap((doc) => {
|
|
118
|
+
const schemas = isObject(doc.root.components) && isObject(doc.root.components.schemas)
|
|
119
|
+
? Object.keys(doc.root.components.schemas) : [];
|
|
120
|
+
return schemas;
|
|
121
|
+
});
|
|
122
|
+
throw new Error(`toMatchSchema: ${ref} is not in ${docs.map((doc) => doc.name).join(", ")}` +
|
|
123
|
+
(known.length > 0 ? ` (component schemas: ${known.slice(0, 20).join(", ")}${known.length > 20 ? ", …" : ""})` : ""));
|
|
124
|
+
}
|
|
125
|
+
if (hits.length > 1) {
|
|
126
|
+
throw new Error(`toMatchSchema: ${ref} is defined in ${hits.map((doc) => doc.name).join(" and ")}; pass { ref, document }`);
|
|
127
|
+
}
|
|
128
|
+
const doc = hits[0];
|
|
129
|
+
return { schema: resolvePointer(doc.root, ref), pointer: ref, doc };
|
|
130
|
+
}
|
|
131
|
+
/** Validate `value` against a target; empty when it matches. */
|
|
132
|
+
validate(value, target) {
|
|
133
|
+
const { schema, pointer, doc } = this.resolveTarget(target);
|
|
134
|
+
return {
|
|
135
|
+
issues: validateSchema(value, schema, pointer, { root: doc.root, dialect: doc.dialect, direction: "response" }),
|
|
136
|
+
pointer,
|
|
137
|
+
document: doc.name,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function loadDocument(source) {
|
|
142
|
+
if (!isObject(source.doc))
|
|
143
|
+
throw new Error(`--openapi ${source.name}: not an OpenAPI document (expected an object)`);
|
|
144
|
+
const version = source.doc.openapi;
|
|
145
|
+
if (typeof version !== "string" || !/^3\.[01]\./.test(version)) {
|
|
146
|
+
throw new Error(`--openapi ${source.name}: openapi ${JSON.stringify(version)} is not supported; use OpenAPI 3.0 or 3.1`);
|
|
147
|
+
}
|
|
148
|
+
const info = isObject(source.doc.info) ? source.doc.info : {};
|
|
149
|
+
return {
|
|
150
|
+
name: source.name,
|
|
151
|
+
root: source.doc,
|
|
152
|
+
dialect: version.startsWith("3.1") ? "3.1" : "3.0",
|
|
153
|
+
version,
|
|
154
|
+
title: typeof info.title === "string" ? info.title : undefined,
|
|
155
|
+
operations: 0,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/** Server URL path prefixes, with `{variables}` at their defaults. */
|
|
159
|
+
function basePaths(servers) {
|
|
160
|
+
const list = Array.isArray(servers) && servers.length > 0 ? servers : [{ url: "/" }];
|
|
161
|
+
const bases = new Set();
|
|
162
|
+
for (const server of list) {
|
|
163
|
+
if (!isObject(server) || typeof server.url !== "string")
|
|
164
|
+
continue;
|
|
165
|
+
const variables = isObject(server.variables) ? server.variables : {};
|
|
166
|
+
const url = server.url.replace(/\{([^}]+)\}/g, (_, name) => {
|
|
167
|
+
const variable = variables[name];
|
|
168
|
+
return isObject(variable) && typeof variable.default === "string" ? variable.default : "";
|
|
169
|
+
});
|
|
170
|
+
bases.add(normalizePath(pathOf(url)));
|
|
171
|
+
}
|
|
172
|
+
return [...bases];
|
|
173
|
+
}
|
|
174
|
+
/** The path of an absolute or relative URL, without query or fragment. */
|
|
175
|
+
export function pathOf(url) {
|
|
176
|
+
const cut = url.search(/[?#]/);
|
|
177
|
+
const bare = cut >= 0 ? url.slice(0, cut) : url;
|
|
178
|
+
const match = /^[a-z][a-z0-9+.-]*:\/\/[^/]*(.*)$/i.exec(bare);
|
|
179
|
+
const path = match ? match[1] : bare;
|
|
180
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
181
|
+
}
|
|
182
|
+
function normalizePath(path) {
|
|
183
|
+
const trimmed = path.replace(/\/+$/, "");
|
|
184
|
+
return trimmed === "" ? "" : trimmed;
|
|
185
|
+
}
|
|
186
|
+
function stripBase(path, base) {
|
|
187
|
+
if (base === "")
|
|
188
|
+
return path;
|
|
189
|
+
if (path === base)
|
|
190
|
+
return "/";
|
|
191
|
+
return path.startsWith(`${base}/`) ? path.slice(base.length) : undefined;
|
|
192
|
+
}
|
|
193
|
+
function splitPath(path) {
|
|
194
|
+
return path.split("/").filter((part) => part.length > 0);
|
|
195
|
+
}
|
|
196
|
+
/** `true` when `path` fits the template; a `{param}` takes one non-empty segment. */
|
|
197
|
+
export function templateMatches(segments, path) {
|
|
198
|
+
if (path === undefined)
|
|
199
|
+
return false;
|
|
200
|
+
const parts = splitPath(path);
|
|
201
|
+
if (parts.length !== segments.length)
|
|
202
|
+
return false;
|
|
203
|
+
return segments.every((segment, index) => {
|
|
204
|
+
if (segment.literal === undefined)
|
|
205
|
+
return true;
|
|
206
|
+
const part = parts[index];
|
|
207
|
+
if (part === segment.literal)
|
|
208
|
+
return true;
|
|
209
|
+
try {
|
|
210
|
+
return decodeURIComponent(part) === segment.literal;
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return false;
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
/** Compile a path template for tests and tools. */
|
|
218
|
+
export function compileTemplate(template) {
|
|
219
|
+
return splitPath(template).map((part) => (/^\{[^}]+\}$/.test(part) ? {} : { literal: part }));
|
|
220
|
+
}
|
|
221
|
+
/** The documented response for `status`: exact, then `4XX`, then `default`. */
|
|
222
|
+
function responseFor(operation, status) {
|
|
223
|
+
const responses = operation.responses;
|
|
224
|
+
const range = `${Math.floor(status / 100)}XX`;
|
|
225
|
+
const key = Object.keys(responses).find((name) => name === String(status))
|
|
226
|
+
?? Object.keys(responses).find((name) => name.toUpperCase() === range)
|
|
227
|
+
?? (Object.prototype.hasOwnProperty.call(responses, "default") ? "default" : undefined);
|
|
228
|
+
if (key === undefined)
|
|
229
|
+
return undefined;
|
|
230
|
+
const response = deref(operation.doc.root, responses[key]);
|
|
231
|
+
return isObject(response) ? { response } : undefined;
|
|
232
|
+
}
|
|
233
|
+
/** The JSON media type entry that describes a response of `contentType`. */
|
|
234
|
+
function mediaFor(root, response, contentType) {
|
|
235
|
+
const content = response.content;
|
|
236
|
+
if (!isObject(content))
|
|
237
|
+
return undefined;
|
|
238
|
+
const actual = (contentType ?? "").split(";")[0].trim().toLowerCase();
|
|
239
|
+
if (actual !== "" && !JSON_TYPE.test(actual))
|
|
240
|
+
return undefined;
|
|
241
|
+
const keys = Object.keys(content);
|
|
242
|
+
const key = keys.find((name) => name.split(";")[0].trim().toLowerCase() === actual)
|
|
243
|
+
?? keys.find((name) => name.toLowerCase().startsWith("application/json"))
|
|
244
|
+
?? keys.find((name) => JSON_TYPE.test(name))
|
|
245
|
+
?? keys.find((name) => name === "*/*" || name === "application/*");
|
|
246
|
+
if (key === undefined)
|
|
247
|
+
return undefined;
|
|
248
|
+
const media = content[key];
|
|
249
|
+
if (!isObject(media) || media.schema === undefined)
|
|
250
|
+
return undefined;
|
|
251
|
+
const schema = media.schema;
|
|
252
|
+
const pointer = isObject(schema) && typeof schema.$ref === "string" && Object.keys(schema).length === 1
|
|
253
|
+
? schema.$ref
|
|
254
|
+
: `${responsePointer(root, response)}/content/${escapePointer(key)}/schema`;
|
|
255
|
+
return { schema, pointer };
|
|
256
|
+
}
|
|
257
|
+
/** Best-effort location of a response object, for messages only. */
|
|
258
|
+
function responsePointer(root, response) {
|
|
259
|
+
const components = isObject(root.components) && isObject(root.components.responses) ? root.components.responses : {};
|
|
260
|
+
for (const [name, candidate] of Object.entries(components)) {
|
|
261
|
+
if (candidate === response)
|
|
262
|
+
return `#/components/responses/${escapePointer(name)}`;
|
|
263
|
+
}
|
|
264
|
+
return "response";
|
|
265
|
+
}
|
|
266
|
+
function deref(root, node) {
|
|
267
|
+
let current = node;
|
|
268
|
+
for (let hop = 0; hop < 32 && isObject(current) && typeof current.$ref === "string"; hop += 1) {
|
|
269
|
+
current = resolvePointer(root, current.$ref);
|
|
270
|
+
}
|
|
271
|
+
return current;
|
|
272
|
+
}
|
|
273
|
+
function escapePointer(segment) {
|
|
274
|
+
return segment.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
275
|
+
}
|
|
276
|
+
function isObject(value) {
|
|
277
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
278
|
+
}
|
|
279
|
+
// ------------------------------ run state ------------------------------
|
|
280
|
+
let active;
|
|
281
|
+
/** The run's contract, for `toMatchSchema`; `undefined` without `--openapi`. */
|
|
282
|
+
export function activeOpenApi() {
|
|
283
|
+
return active;
|
|
284
|
+
}
|
|
285
|
+
export function setActiveOpenApi(index) {
|
|
286
|
+
active = index;
|
|
287
|
+
}
|
|
288
|
+
/** `control.openapi`: a JSON list of `{ name, doc }` lxdev parsed from the files. */
|
|
289
|
+
export function parseOpenApiControl(raw) {
|
|
290
|
+
if (raw === undefined)
|
|
291
|
+
return undefined;
|
|
292
|
+
const parsed = JSON.parse(raw);
|
|
293
|
+
if (!Array.isArray(parsed) || parsed.length === 0)
|
|
294
|
+
throw new Error("openapi control must be a non-empty JSON list");
|
|
295
|
+
return new OpenApiIndex(parsed.map((entry, index) => {
|
|
296
|
+
const record = (isObject(entry) ? entry : {});
|
|
297
|
+
return { name: typeof record.name === "string" ? record.name : `openapi-${index + 1}`, doc: record.doc };
|
|
298
|
+
}));
|
|
299
|
+
}
|
|
300
|
+
const MAX_WARNINGS = 100;
|
|
301
|
+
const MAX_UNMATCHED = 50;
|
|
302
|
+
/** Accumulates the run's `openapi` report section. */
|
|
303
|
+
export class ContractLedger {
|
|
304
|
+
constructor(index) {
|
|
305
|
+
this.index = index;
|
|
306
|
+
this.summary = {
|
|
307
|
+
documents: index.documents.map((doc) => ({
|
|
308
|
+
name: doc.name,
|
|
309
|
+
version: doc.version,
|
|
310
|
+
...(doc.title ? { title: doc.title } : {}),
|
|
311
|
+
operations: doc.operations,
|
|
312
|
+
})),
|
|
313
|
+
responses: 0,
|
|
314
|
+
validated: 0,
|
|
315
|
+
routed: { validated: 0, failed: 0 },
|
|
316
|
+
network: { validated: 0, mismatched: 0 },
|
|
317
|
+
skipped: { no_schema: 0, not_json: 0, empty: 0, truncated: 0 },
|
|
318
|
+
undocumented: [],
|
|
319
|
+
unmatched: [],
|
|
320
|
+
warnings: [],
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Check one spec's responses. Mismatches in routed responses (`route`,
|
|
325
|
+
* `patch`) are the spec's violations; the real server's are warnings.
|
|
326
|
+
*/
|
|
327
|
+
checkSpec(caseId, records) {
|
|
328
|
+
const violations = [];
|
|
329
|
+
const warnings = [];
|
|
330
|
+
for (const record of records) {
|
|
331
|
+
this.summary.responses += 1;
|
|
332
|
+
const outcome = this.index.check(record);
|
|
333
|
+
const routed = record.source !== "network";
|
|
334
|
+
switch (outcome.kind) {
|
|
335
|
+
case "unmatched": {
|
|
336
|
+
const found = this.summary.unmatched.find((entry) => entry.method === outcome.method && entry.path === outcome.path);
|
|
337
|
+
if (found)
|
|
338
|
+
found.count += 1;
|
|
339
|
+
else if (this.summary.unmatched.length < MAX_UNMATCHED) {
|
|
340
|
+
this.summary.unmatched.push({ method: outcome.method, path: outcome.path, count: 1 });
|
|
341
|
+
}
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
case "undocumented": {
|
|
345
|
+
const found = this.summary.undocumented.find((entry) => entry.operation === outcome.operation && entry.status === outcome.status && entry.source === record.source);
|
|
346
|
+
if (found)
|
|
347
|
+
found.count += 1;
|
|
348
|
+
else
|
|
349
|
+
this.summary.undocumented.push({ operation: outcome.operation, status: outcome.status, source: record.source, count: 1 });
|
|
350
|
+
break;
|
|
351
|
+
}
|
|
352
|
+
case "skipped":
|
|
353
|
+
this.summary.skipped[outcome.reason] += 1;
|
|
354
|
+
break;
|
|
355
|
+
case "valid":
|
|
356
|
+
this.summary.validated += 1;
|
|
357
|
+
if (routed)
|
|
358
|
+
this.summary.routed.validated += 1;
|
|
359
|
+
else
|
|
360
|
+
this.summary.network.validated += 1;
|
|
361
|
+
break;
|
|
362
|
+
case "invalid": {
|
|
363
|
+
this.summary.validated += 1;
|
|
364
|
+
const issue = {
|
|
365
|
+
case: caseId,
|
|
366
|
+
source: record.source,
|
|
367
|
+
method: record.method,
|
|
368
|
+
url: record.url,
|
|
369
|
+
status: outcome.status,
|
|
370
|
+
operation: outcome.operation,
|
|
371
|
+
schema: outcome.schema,
|
|
372
|
+
...(record.pattern ? { pattern: record.pattern } : {}),
|
|
373
|
+
issues: outcome.issues.map(({ path, message, schema }) => ({ path, message, schema })),
|
|
374
|
+
};
|
|
375
|
+
if (routed) {
|
|
376
|
+
this.summary.routed.validated += 1;
|
|
377
|
+
this.summary.routed.failed += 1;
|
|
378
|
+
violations.push(issue);
|
|
379
|
+
}
|
|
380
|
+
else {
|
|
381
|
+
this.summary.network.validated += 1;
|
|
382
|
+
this.summary.network.mismatched += 1;
|
|
383
|
+
warnings.push(issue);
|
|
384
|
+
if (this.summary.warnings.length < MAX_WARNINGS)
|
|
385
|
+
this.summary.warnings.push(issue);
|
|
386
|
+
}
|
|
387
|
+
break;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return { violations, warnings, checked: records.length };
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
/** The spec failure a routed contract violation produces. */
|
|
395
|
+
export class ContractError extends Error {
|
|
396
|
+
constructor(violations) {
|
|
397
|
+
super(describeViolations(violations));
|
|
398
|
+
this.name = "ContractError";
|
|
399
|
+
this.code = "E_OPENAPI_CONTRACT";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
export function describeViolations(violations) {
|
|
403
|
+
const lines = violations.slice(0, 5).map((violation) => {
|
|
404
|
+
const by = violation.source === "patch" ? "patched by" : "fulfilled by";
|
|
405
|
+
const route = violation.pattern ? ` (${by} route ${violation.pattern})` : "";
|
|
406
|
+
return `${violation.operation} → ${violation.status}${route}: the response does not match ${violation.schema}\n${formatIssues(violation.issues)}`;
|
|
407
|
+
});
|
|
408
|
+
const more = violations.length > 5 ? `\n…and ${violations.length - 5} more` : "";
|
|
409
|
+
const head = violations.length === 1
|
|
410
|
+
? "A routed response breaks the OpenAPI contract:"
|
|
411
|
+
: `${violations.length} routed responses break the OpenAPI contract:`;
|
|
412
|
+
return `${head}\n${lines.join("\n")}${more}`;
|
|
413
|
+
}
|
|
414
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../src/openapi.ts"],"names":[],"mappings":"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"}
|