json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
288 lines (243 loc) • 10.3 kB
text/typescript
import { strict as assert } from "assert";
import { compileSchema } from "../../compileSchema";
describe("keyword : $ref : resolve", () => {
it("should return undefined for missing reference", () => {
const node = compileSchema({
$ref: "#/$defs/header",
minLength: 1
}).resolveRef();
assert.deepEqual(node, undefined);
});
it("should resolve $ref from definitions", () => {
const node = compileSchema({
$ref: "#/definitions/header",
definitions: { header: { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
it("should resolve $ref from $defs", () => {
const node = compileSchema({
$ref: "#/$defs/header",
$defs: { header: { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
it("should resolve nested $ref from $defs", () => {
const { node: _node } = compileSchema({
properties: {
header: { $ref: "#/$defs/header" }
},
$defs: { header: { type: "string", minLength: 1 } }
}).getNodeChild("header");
const node = _node.resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
it("should resolve root pointer, not merging schema", () => {
const { node: _node } = compileSchema({
type: "object",
minProperties: 1,
properties: {
header: { $ref: "#", minProperties: 2 }
}
}).getNodeChild("header");
const node = _node.resolveRef();
assert.deepEqual(node.schema, {
type: "object",
minProperties: 1,
properties: {
header: { $ref: "#", minProperties: 2 }
}
});
});
it("should resolve with full domain", () => {
const node = compileSchema({
$id: "https://root.schema",
$ref: "https://root.schema#/$defs/header",
$defs: { header: { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { /*$id: "https://root.schema",*/ type: "string", minLength: 1 });
});
it("should resolve locally without domain", () => {
const node = compileSchema({
$id: "https://root.schema",
$ref: "#/$defs/header",
$defs: { header: { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { /*$id: "https://root.schema",*/ type: "string", minLength: 1 });
});
describe("uri encoded pointer", () => {
it("should resolve url encoded property", () => {
const node = compileSchema({
$ref: "#/$defs/header%25title",
$defs: { "header%title": { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
it("should resolve ~0 to ~", () => {
const node = compileSchema({
$ref: "#/$defs/tilde~0field",
$defs: { "tilde~field": { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
it("should resolve ~1 to /", () => {
const node = compileSchema({
$ref: "#/$defs/slash~1field",
$defs: { "slash/field": { type: "string", minLength: 1 } }
}).resolveRef();
assert.deepEqual(node.schema, { type: "string", minLength: 1 });
});
});
describe("remoteSchema", () => {
it("should resolve remoteSchema from $ref", () => {
const node = compileSchema({
$ref: "https://remote.schema"
})
.addRemoteSchema("https://remote.schema", { type: "object", minProperties: 1 })
.resolveRef();
assert.deepEqual(node.$id, "https://remote.schema");
assert.deepEqual(node.schema, {
type: "object",
minProperties: 1
});
});
it("should resolve $defs in remoteSchema from $ref", () => {
const node = compileSchema({
$ref: "https://remote.schema#/$defs/header"
})
.addRemoteSchema("https://remote.schema", { $defs: { header: { type: "object", minProperties: 1 } } })
.resolveRef();
assert.deepEqual(node.schema, { type: "object", minProperties: 1 });
});
it("should resolve $defs in correct remoteSchema from $ref", () => {
const node = compileSchema({
$ref: "https://remoteB.schema#/$defs/header"
})
.addRemoteSchema("https://remoteA.schema", { $defs: { header: { type: "string", minLength: 1 } } })
.addRemoteSchema("https://remoteB.schema", { $defs: { header: { type: "object", minProperties: 1 } } })
.resolveRef();
assert.deepEqual(node.schema, { type: "object", minProperties: 1 });
});
it("should resolve $ref to through multiple remoteSchema", () => {
const node = compileSchema({
$ref: "https://remoteA.schema"
})
.addRemoteSchema("https://remoteA.schema", { $ref: "https://remoteB.schema#/$defs/header" })
.addRemoteSchema("https://remoteB.schema", { $defs: { header: { type: "object", minProperties: 1 } } })
.resolveRef()
.resolveRef()
.resolveRef();
assert.deepEqual(node.schema, { type: "object", minProperties: 1 });
});
it("should resolve local $ref from remoteSchema in remoteSchema", () => {
const node = compileSchema({
$ref: "https://remote.schema"
})
.addRemoteSchema("https://remote.schema", {
$ref: "#/$defs/header",
$defs: { header: { type: "object", minProperties: 1 } }
})
.resolveRef()
.resolveRef();
assert.deepEqual(node.schema, { type: "object", minProperties: 1 });
});
it("should resolve remote $ref to origin schema", () => {
const node = compileSchema({
$id: "https://root.schema",
$ref: "https://remote.schema/",
$defs: { header: { type: "object", minProperties: 1 } }
})
.addRemoteSchema("https://remote.schema", {
$ref: "https://root.schema#/$defs/header"
})
.resolveRef()
.resolveRef();
assert.deepEqual(node.schema, { type: "object", minProperties: 1 });
});
});
});
describe("keyword : ref : validate", () => {
it("should return error", () => {
const { errors } = compileSchema({
$schema: "https://json-schema.org/draft/2019-09/schema",
properties: { foo: { $ref: "#" } },
additionalProperties: false
}).validate({ bar: false });
assert.equal(errors.length, 1);
});
it("should return error for recursive mismatch", () => {
const { errors } = compileSchema({
$schema: "https://json-schema.org/draft/2019-09/schema",
properties: { foo: { $ref: "#" } },
additionalProperties: false
}).validate({ foo: { bar: false } });
assert.equal(errors.length, 1);
});
it("should resolve base URI change - change folder", () => {
const node = compileSchema({
$schema: "https://json-schema.org/draft/2019-09/schema",
$id: "http://localhost:1234/draft2019-09/scope_change_defs1.json",
type: "object",
properties: {
list: {
$ref: "baseUriChangeFolder/"
}
},
$defs: {
baz: {
$id: "baseUriChangeFolder/",
type: "array",
items: {
$ref: "folderInteger.json"
}
}
}
});
// console.log("\nADD REMOTE\n");
node.addRemoteSchema("http://localhost:1234/draft2019-09/baseUriChangeFolder/folderInteger.json", {
$schema: "https://json-schema.org/draft/2019-09/schema",
type: "integer"
});
// console.log("\nVALIDATE\n");
const { errors } = node.validate({ list: [1] });
assert.equal(errors.length, 0);
});
it("should resolve base URI change ref valid", () => {
const { errors } = compileSchema({
$schema: "https://json-schema.org/draft/2019-09/schema",
$id: "http://localhost:1234/draft2019-09/",
items: {
$id: "baseUriChange/",
items: {
$ref: "folderInteger.json"
}
}
})
.addRemoteSchema("http://localhost:1234/draft2019-09/baseUriChange/folderInteger.json", {
type: "integer"
})
.validate([[1]]);
assert.equal(errors.length, 0);
});
// requires anchor
it("should resolve Location-independent identifier in remote ref", () => {
const { errors } = compileSchema({
$schema: "https://json-schema.org/draft/2019-09/schema",
$ref: "http://localhost:1234/draft2019-09/locationIndependentIdentifier.json#/$defs/refToInteger"
})
.addRemoteSchema("http://localhost:1234/draft2019-09/locationIndependentIdentifier.json", {
$schema: "https://json-schema.org/draft/2019-09/schema",
$defs: {
refToInteger: {
$ref: "#foo"
},
A: {
$anchor: "foo",
type: "integer"
}
}
})
.validate("foo");
assert.equal(errors.length, 1);
});
});