-
-
Notifications
You must be signed in to change notification settings - Fork 244
Expand file tree
/
Copy pathbundle-ref-through-ref.spec.ts
More file actions
63 lines (56 loc) · 2.25 KB
/
bundle-ref-through-ref.spec.ts
File metadata and controls
63 lines (56 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { describe, it, expect } from "vitest";
import $RefParser from "../../../lib/index.js";
import path from "../../utils/path.js";
describe("Issue #338: bundle() should not create refs through refs", () => {
it("should produce valid bundled output where no $ref path traverses through another $ref", async () => {
const parser = new $RefParser();
const schema = await parser.bundle(path.rel("test/specs/bundle-ref-through-ref/schemaA.json"));
const bundledStr = JSON.stringify(schema, null, 2);
// Collect all $ref values in the bundled schema
const refs: string[] = [];
function collectRefs(obj: any, path: string) {
if (!obj || typeof obj !== "object") return;
if (Array.isArray(obj)) {
obj.forEach((item, i) => collectRefs(item, `${path}/${i}`));
return;
}
for (const [key, val] of Object.entries(obj)) {
if (key === "$ref" && typeof val === "string") {
refs.push(val);
} else {
collectRefs(val, `${path}/${key}`);
}
}
}
collectRefs(schema, "#");
// For each $ref, verify the path can be resolved by walking the literal
// object structure (without following $ref indirection)
for (const ref of refs) {
if (!ref.startsWith("#/")) continue;
const segments = ref.slice(2).split("/");
let current: any = schema;
let valid = true;
let failedAt = "";
for (const seg of segments) {
if (current === null || current === undefined || typeof current !== "object") {
valid = false;
failedAt = seg;
break;
}
// If the current value at this path is itself a $ref, the path is invalid
// (JSON pointer resolution doesn't follow $ref indirection)
if ("$ref" in current && typeof current.$ref === "string" && seg !== "$ref") {
// This position has a $ref - the pointer can't traverse through it
valid = false;
failedAt = `$ref at ${seg}`;
break;
}
const idx = Array.isArray(current) ? parseInt(seg) : seg;
current = current[idx];
}
expect(valid, `$ref "${ref}" traverses through another $ref (failed at: ${failedAt}). Bundled:\n${bundledStr}`).toBe(
true,
);
}
});
});