json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
294 lines (239 loc) • 9.86 kB
text/typescript
/* eslint quote-props: 0, no-unused-expressions: 0 */
import { strict as assert } from "assert";
import { toSchemaNodes } from "./toSchemaNodes";
import { compileSchema } from "../compileSchema";
describe("toSchemaNodes", () => {
it("should execute callback on root-schema", () => {
const rootSchema = compileSchema({
type: "object",
properties: {}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes[0].schema, rootSchema.schema);
});
it("should call on unspecified properties", () => {
const rootSchema = compileSchema({
type: "object",
properties: {
title: {}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 2);
assert.deepEqual(nodes[1].evaluationPath, "#/properties/title");
});
it("should call on each property schema", () => {
const rootSchema = compileSchema({
type: "object",
properties: {
first: { type: "string" },
second: { type: "number" }
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.properties.first);
assert.deepEqual(nodes[1].evaluationPath, "#/properties/first");
assert.deepEqual(nodes[2].schema, rootSchema.schema.properties.second);
assert.deepEqual(nodes[2].evaluationPath, "#/properties/second");
});
it("should call on each property schema if type is missing", () => {
const rootSchema = compileSchema({
properties: {
first: { type: "string" },
second: { type: "number" }
},
$ref: "schema-relative-uri-defs2.json"
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
});
it("should call on each item schema", () => {
const rootSchema = compileSchema({
$schema: "draft-2019-09",
type: "array",
items: [{ type: "string" }, { type: "number" }]
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.items[0]);
assert.deepEqual(nodes[1].evaluationPath, "#/items/0");
assert.deepEqual(nodes[2].schema, rootSchema.schema.items[1]);
assert.deepEqual(nodes[2].evaluationPath, "#/items/1");
});
it("should call on each prefixItem", () => {
const rootSchema = compileSchema({
type: "array",
prefixItems: [{ type: "string" }, { type: "number" }]
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.prefixItems[0]);
assert.deepEqual(nodes[1].evaluationPath, "#/prefixItems/0");
assert.deepEqual(nodes[2].schema, rootSchema.schema.prefixItems[1]);
assert.deepEqual(nodes[2].evaluationPath, "#/prefixItems/1");
});
it("should call on each item property", () => {
const rootSchema = compileSchema({
type: "array",
items: {
type: "object",
properties: {
first: { type: "string" },
second: { type: "number" }
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 4);
assert.deepEqual(nodes[2].schema, rootSchema.schema.items.properties.first);
assert.deepEqual(nodes[2].evaluationPath, "#/items/properties/first");
assert.deepEqual(nodes[3].schema, rootSchema.schema.items.properties.second);
assert.deepEqual(nodes[3].evaluationPath, "#/items/properties/second");
});
it("should call on each oneOf-schema", () => {
const rootSchema = compileSchema({
oneOf: [{ type: "string" }, { type: "number" }]
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.oneOf[0]);
assert.deepEqual(nodes[1].evaluationPath, "#/oneOf/0");
assert.deepEqual(nodes[2].schema, rootSchema.schema.oneOf[1]);
assert.deepEqual(nodes[2].evaluationPath, "#/oneOf/1");
});
it("should call on each oneOf-schema in items", () => {
const rootSchema = compileSchema({
type: "array",
items: {
oneOf: [{ type: "string" }, { type: "number" }]
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 4);
assert.deepEqual(nodes[1].schema, rootSchema.schema.items);
assert.deepEqual(nodes[1].evaluationPath, "#/items");
assert.deepEqual(nodes[2].schema, rootSchema.schema.items.oneOf[0]);
assert.deepEqual(nodes[2].evaluationPath, "#/items/oneOf/0");
assert.deepEqual(nodes[3].schema, rootSchema.schema.items.oneOf[1]);
assert.deepEqual(nodes[3].evaluationPath, "#/items/oneOf/1");
});
it("should call on each anyOf-schema", () => {
const rootSchema = compileSchema({
anyOf: [{ type: "string" }, { type: "number" }]
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.anyOf[0]);
assert.deepEqual(nodes[1].evaluationPath, "#/anyOf/0");
assert.deepEqual(nodes[2].schema, rootSchema.schema.anyOf[1]);
assert.deepEqual(nodes[2].evaluationPath, "#/anyOf/1");
});
it("should call on each allOf-schema", () => {
const rootSchema = compileSchema({
allOf: [{ type: "string" }, { type: "number" }]
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.allOf[0]);
assert.deepEqual(nodes[2].schema, rootSchema.schema.allOf[1]);
});
it("should call on definitions", () => {
const rootSchema = compileSchema({
definitions: {
image: {
type: "string",
format: "url"
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 2);
assert.deepEqual(nodes[1].schema, rootSchema.schema.definitions.image);
});
it("should call on additionalProperties", () => {
const rootSchema = compileSchema({
type: "object",
additionalProperties: {
type: "object",
properties: {
url: { type: "string" }
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[1].schema, rootSchema.schema.additionalProperties);
});
it("should ignore dependency list", () => {
const rootSchema = compileSchema({
dependencies: {
url: ["title"]
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 1);
});
it("should call on each dependency schema", () => {
const rootSchema = compileSchema({
type: "object",
dependencies: {
url: ["title"],
target: {
type: "string"
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 2);
assert.deepEqual(nodes[1].schema, rootSchema.schema.dependencies.target);
});
it("should iterate definitions", () => {
const rootSchema = compileSchema({
definitions: {
bar: { type: "array" }
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 2);
assert.deepEqual(nodes[0].schema, rootSchema.schema);
assert.deepEqual(nodes[1].schema, rootSchema.schema.definitions.bar);
});
it("should iterate over nested definitions", () => {
const rootSchema = compileSchema({
definitions: {
bar: { type: "array" },
nested: {
definitions: {
foo: { type: "string" }
}
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 4);
assert.deepEqual(nodes[0].schema, rootSchema.schema);
assert.deepEqual(nodes[1].schema, rootSchema.schema.definitions.bar);
assert.deepEqual(nodes[2].schema, rootSchema.schema.definitions.nested);
assert.deepEqual(nodes[3].schema, rootSchema.schema.definitions.nested.definitions.foo);
});
it("should support array-types", () => {
// https://json-schema.org/draft/2020-12/json-schema-draft.html#rfc.section.7.6.1
const rootSchema = compileSchema({
type: "object",
properties: {
simple: {
type: ["string", "number"]
},
primitive: {
type: ["string", "null"]
}
}
});
const nodes = toSchemaNodes(rootSchema);
assert.deepEqual(nodes.length, 3);
assert.deepEqual(nodes[0].schema, rootSchema.schema);
assert.deepEqual(nodes[1].schema, rootSchema.schema.properties.simple);
assert.deepEqual(nodes[2].schema, rootSchema.schema.properties.primitive);
});
});