UNPKG

ajv-cli

Version:

Command line interface for Ajv JSON schema validator

384 lines (352 loc) 12.8 kB
import cli from "./cli" import assert = require("assert") import type {DefinedError} from "ajv" describe("validate", function () { this.timeout(10000) describe("single file validation", () => { it("should validate valid data", (done) => { cli("-s test/schema -d test/valid_data", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it('should validate valid data with the "yml" extension', (done) => { cli("-s test/schema -d test/valid_data.yml", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it('should validate valid data with the "yaml" extension', (done) => { cli("-s test/schema -d test/valid_data.yaml", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it('should validate valid data with the "json5" extension', (done) => { cli("-s test/schema -d test/valid_data.json5", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it('should validate valid data with the "jsonc" extension', (done) => { cli("-s test/schema -d test/valid_data.jsonc", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it("falls back to require on unsupported formats", (done) => { cli( "-s test/schema.json -d test/invalid_format.cson --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assert.ok(/Invalid or unexpected token/i.exec(stderr)) done() } ) }) it("should validate invalid data", (done) => { cli( "-s test/schema.json -d test/invalid_data.json --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assertRequiredErrors(stderr) done() } ) }) it("should print usage if syntax is invalid", (done) => { cli("-d test/valid_data", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assert(stderr.includes("usage")) assert(stderr.includes("parameter")) assert(stderr.includes("required")) done() }) }) it("should validate valid data with JTD schema", (done) => { cli("validate -s test/jtd/schema -d test/jtd/data --spec=jtd", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it("should validate invalid data with JTD schema", (done) => { cli( "validate -s test/jtd/schema -d test/jtd/invalid_data --spec=jtd --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assertErrors(stderr, 1).forEach((errors) => assert.strictEqual(errors.length, 1)) done() } ) }) }) describe("multiple file validation", () => { describe("with glob", () => { it("should exit without error if all files are valid", (done) => { cli('-s test/schema -d "test/valid*.json"', (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 2) assert.strictEqual(stderr, "") done() }) }) it("should exit with error if some files are invalid", (done) => { cli( '-s test/schema -d "test/{valid,invalid}*.json" --errors=line', (error, stdout, stderr) => { assert(error instanceof Error) assertValid(stdout, 2) assertRequiredErrors(stderr, "#", 2) done() } ) }) }) describe("with multiple files or patterns", () => { it("should exit without error if all files are valid", (done) => { cli( "-s test/schema -d test/valid_data.json -d test/valid_data2.json", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 2) assert.strictEqual(stderr, "") done() } ) }) it("should exit with error if some files are invalid", (done) => { cli( "-s test/schema -d test/valid_data.json -d test/valid_data2.json -d test/invalid_data.json --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assertValid(stdout, 2) assertRequiredErrors(stderr) done() } ) }) it("should exit with error if some files are invalid (multiple patterns)", (done) => { cli( '-s test/schema -d "test/valid*.json" -d "test/invalid*.json" --errors=line', (error, stdout, stderr) => { assert(error instanceof Error) assertValid(stdout, 2) assertRequiredErrors(stderr, "#", 2) done() } ) }) }) }) describe("validate schema with $ref", () => { it("should resolve reference and validate", (done) => { cli("-s test/schema_with_ref -r test/schema -d test/valid_data", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() }) }) it("should resolve reference and validate invalid data", (done) => { cli( "-s test/schema_with_ref -r test/schema -d test/invalid_data --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assertRequiredErrors(stderr, "schema.json") done() } ) }) }) describe("validate with schema using added meta-schema", () => { it("should validate valid data", (done) => { cli( "-s test/meta/schema -d test/meta/valid_data -m test/meta/meta_schema --strict=false", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() } ) }) it("should validate invalid data", (done) => { cli( "-s test/meta/schema -d test/meta/invalid_data -m test/meta/meta_schema --errors=line --strict=false", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") const results = assertErrors(stderr) const errors = results[0] const err = errors[0] assert.strictEqual(err.keyword, "type") assert.strictEqual(err.instancePath, "/foo") assert.strictEqual(err.schemaPath, "#/properties/foo/type") done() } ) }) it("should fail on invalid schema", (done) => { cli( "-s test/meta/invalid_schema -d test/meta/valid_data -m test/meta/meta_schema --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") const lines = stderr.split("\n") assert.strictEqual(lines.length, 3) assert(lines[0].includes("schema")) assert(lines[0].includes("invalid")) assert(lines[1].includes("error")) assert(/my_keyword\smust\sbe\sboolean/.test(lines[1])) done() } ) }) }) describe('option "changes"', () => { it("should log changes in the object after validation", (done) => { cli( "-s test/schema -d test/data_with_additional --remove-additional --changes=line", (error, stdout, stderr) => { assert.strictEqual(error, null) const lines = assertValid(stdout, 1, 2) assert(lines[1].includes("changes")) const changes = JSON.parse(lines[2]) assert.deepStrictEqual(changes, [ {op: "remove", path: "/1/additionalInfo"}, {op: "remove", path: "/0/additionalInfo"}, ]) assert.strictEqual(stderr, "") done() } ) }) }) describe('option "data"', () => { it("should exit with error when not specified in the presence of `$data` references", (done) => { cli( "validate -s test/schema_with_data_reference -d test/data_for_schema_with_data_reference", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") assert(stderr.includes("test/schema_with_data_reference is invalid")) assert(stderr.includes("larger/minimum")) assert(stderr.includes("must be number")) done() } ) }) it("it should enable `$data` references when specified", (done) => { cli( "validate --data -s test/schema_with_data_reference -d test/data_for_schema_with_data_reference", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() } ) }) }) describe("custom keywords", () => { it("should validate valid data; custom keyword definition in file", (done) => { cli( "validate -s test/custom/schema -c ./test/custom/typeof.js -d test/custom/valid_data", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() } ) }) it("should validate valid data; custom keyword definition in package", (done) => { cli( "validate -s test/custom/schema -c ajv-keywords/dist/keywords/typeof -d test/custom/valid_data", (error, stdout, stderr) => { assert.strictEqual(error, null) assertValid(stdout, 1) assert.strictEqual(stderr, "") done() } ) }) it("should validate invalid data; custom keyword definition in file", (done) => { cli( "validate -s test/custom/schema -c ./test/custom/typeof.js -d test/custom/invalid_data --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") const results = assertErrors(stderr) const errors = results[0] const err = errors[0] assert.strictEqual(err.keyword, "typeof") assert.strictEqual(err.instancePath, "") assert.strictEqual(err.schemaPath, "#/typeof") done() } ) }) it("should validate invalid data; custom keyword definition in package", (done) => { cli( "validate -s test/custom/schema -c ajv-keywords/dist/keywords/typeof -d test/custom/invalid_data --errors=line", (error, stdout, stderr) => { assert(error instanceof Error) assert.strictEqual(stdout, "") const results = assertErrors(stderr) const errors = results[0] const err = errors[0] assert.strictEqual(err.keyword, "typeof") assert.strictEqual(err.instancePath, "") assert.strictEqual(err.schemaPath, "#/typeof") done() } ) }) }) }) function assertValid(stdout: string, count: number, extraLines = 0): string[] { const lines = stdout.split("\n") assert.strictEqual(lines.length, count + extraLines + 1) for (let i = 0; i < count; i++) assert(/\svalid/.test(lines[i])) return lines } function assertRequiredErrors(stderr: string, schemaRef = "#", count = 1): void { const results = assertErrors(stderr, count) results.forEach((errors) => { const err = errors[0] assert.strictEqual(err.keyword, "required") assert.strictEqual(err.instancePath, "/0/dimensions") assert.strictEqual(err.schemaPath, schemaRef + "/items/properties/dimensions/required") assert.deepStrictEqual(err.params, {missingProperty: "height"}) }) } function assertErrors(stderr: string, count = 1): DefinedError[][] { const lines = stderr.split("\n") assert.strictEqual(lines.length, count * 2 + 1) const results: DefinedError[][] = [] for (let i = 0; i < count; i += 2) { assert(/\sinvalid/.test(lines[i])) const errors = JSON.parse(lines[i + 1]) assert.strictEqual(errors.length, 1) results.push(errors) } return results }