refactor: split options.spec.js file
parent
51685b8eef
commit
71dc5dc27d
|
@ -12,9 +12,9 @@
|
||||||
".tonic_example.js"
|
".tonic_example.js"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"eslint": "eslint lib/*.js lib/compile/*.js spec/*.js scripts",
|
"eslint": "eslint lib/{compile/,}*.js spec/{**/,}*.js scripts --ignore-pattern spec/JSON-Schema-Test-Suite",
|
||||||
"jshint": "jshint lib/*.js lib/**/*.js --exclude lib/dotjs/**/*",
|
"jshint": "jshint lib/{compile/,}*.js",
|
||||||
"test-spec": "mocha spec/*.spec.js -R spec",
|
"test-spec": "mocha spec/{**/,}*.spec.js -R spec",
|
||||||
"test-fast": "AJV_FAST_TEST=true npm run test-spec",
|
"test-fast": "AJV_FAST_TEST=true npm run test-spec",
|
||||||
"test-debug": "mocha spec/*.spec.js --debug-brk -R spec",
|
"test-debug": "mocha spec/*.spec.js --debug-brk -R spec",
|
||||||
"test-cov": "nyc npm run test-spec",
|
"test-cov": "nyc npm run test-spec",
|
||||||
|
|
1579
spec/options.spec.js
1579
spec/options.spec.js
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,92 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('$comment option', function() {
|
||||||
|
describe('= true', function() {
|
||||||
|
var logCalls, consoleLog;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
consoleLog = console.log;
|
||||||
|
console.log = log;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function () {
|
||||||
|
console.log = consoleLog;
|
||||||
|
});
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
logCalls.push(Array.prototype.slice.call(arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should log the text from $comment keyword', function() {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
foo: {$comment: 'property foo'},
|
||||||
|
bar: {$comment: 'property bar', type: 'integer'}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ajv = new Ajv({$comment: true});
|
||||||
|
var fullAjv = new Ajv({allErrors: true, $comment: true});
|
||||||
|
|
||||||
|
[ajv, fullAjv].forEach(function (_ajv) {
|
||||||
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
|
test({}, true, []);
|
||||||
|
test({foo: 1}, true, [['property foo']]);
|
||||||
|
test({foo: 1, bar: 2}, true, [['property foo'], ['property bar']]);
|
||||||
|
test({foo: 1, bar: 'baz'}, false, [['property foo'], ['property bar']]);
|
||||||
|
|
||||||
|
function test(data, valid, expectedLogCalls) {
|
||||||
|
logCalls = [];
|
||||||
|
validate(data) .should.equal(valid);
|
||||||
|
logCalls .should.eql(expectedLogCalls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log = consoleLog;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('function hook', function() {
|
||||||
|
var hookCalls;
|
||||||
|
|
||||||
|
function hook() {
|
||||||
|
hookCalls.push(Array.prototype.slice.call(arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should pass the text from $comment keyword to the hook', function() {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
foo: {$comment: 'property foo'},
|
||||||
|
bar: {$comment: 'property bar', type: 'integer'}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var ajv = new Ajv({$comment: hook});
|
||||||
|
var fullAjv = new Ajv({allErrors: true, $comment: hook});
|
||||||
|
|
||||||
|
[ajv, fullAjv].forEach(function (_ajv) {
|
||||||
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
|
test({}, true, []);
|
||||||
|
test({foo: 1}, true, [['property foo', '#/properties/foo/$comment', schema]]);
|
||||||
|
test({foo: 1, bar: 2}, true,
|
||||||
|
[['property foo', '#/properties/foo/$comment', schema],
|
||||||
|
['property bar', '#/properties/bar/$comment', schema]]);
|
||||||
|
test({foo: 1, bar: 'baz'}, false,
|
||||||
|
[['property foo', '#/properties/foo/$comment', schema],
|
||||||
|
['property bar', '#/properties/bar/$comment', schema]]);
|
||||||
|
|
||||||
|
function test(data, valid, expectedHookCalls) {
|
||||||
|
hookCalls = [];
|
||||||
|
validate(data) .should.equal(valid);
|
||||||
|
hookCalls .should.eql(expectedHookCalls);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,79 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('meta and validateSchema options', function() {
|
||||||
|
it('should add draft-7 meta schema by default', function() {
|
||||||
|
testOptionMeta(new Ajv);
|
||||||
|
testOptionMeta(new Ajv({ meta: true }));
|
||||||
|
|
||||||
|
function testOptionMeta(ajv) {
|
||||||
|
ajv.getSchema('http://json-schema.org/draft-07/schema') .should.be.a('function');
|
||||||
|
ajv.validateSchema({ type: 'integer' }) .should.equal(true);
|
||||||
|
ajv.validateSchema({ type: 123 }) .should.equal(false);
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 'integer' }); });
|
||||||
|
should.throw(function() { ajv.addSchema({ type: 123 }); });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if meta: false and validateSchema: true', function() {
|
||||||
|
var ajv = new Ajv({ meta: false });
|
||||||
|
should.not.exist(ajv.getSchema('http://json-schema.org/draft-07/schema'));
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 'wrong_type' }, 'integer'); });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should skip schema validation with validateSchema: false', function() {
|
||||||
|
var ajv = new Ajv;
|
||||||
|
should.throw(function() { ajv.addSchema({ type: 123 }, 'integer'); });
|
||||||
|
|
||||||
|
ajv = new Ajv({ validateSchema: false });
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 123 }, 'integer'); });
|
||||||
|
|
||||||
|
ajv = new Ajv({ validateSchema: false, meta: false });
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 123 }, 'integer'); });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw on invalid schema with validateSchema: "log"', function() {
|
||||||
|
var logError = console.error;
|
||||||
|
var loggedError = false;
|
||||||
|
console.error = function() { loggedError = true; logError.apply(console, arguments); };
|
||||||
|
|
||||||
|
var ajv = new Ajv({ validateSchema: 'log' });
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 123 }, 'integer'); });
|
||||||
|
loggedError .should.equal(true);
|
||||||
|
|
||||||
|
loggedError = false;
|
||||||
|
ajv = new Ajv({ validateSchema: 'log', meta: false });
|
||||||
|
should.not.throw(function() { ajv.addSchema({ type: 123 }, 'integer'); });
|
||||||
|
loggedError .should.equal(false);
|
||||||
|
console.error = logError;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should validate v6 schema', function() {
|
||||||
|
var ajv = new Ajv;
|
||||||
|
ajv.validateSchema({ contains: { minimum: 2 } }) .should.equal(true);
|
||||||
|
ajv.validateSchema({ contains: 2 }). should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use option meta as default meta schema', function() {
|
||||||
|
var meta = {
|
||||||
|
$schema: 'http://json-schema.org/draft-07/schema',
|
||||||
|
properties: {
|
||||||
|
myKeyword: { type: 'boolean' }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var ajv = new Ajv({ meta: meta });
|
||||||
|
ajv.validateSchema({ myKeyword: true }) .should.equal(true);
|
||||||
|
ajv.validateSchema({ myKeyword: 2 }) .should.equal(false);
|
||||||
|
ajv.validateSchema({
|
||||||
|
$schema: 'http://json-schema.org/draft-07/schema',
|
||||||
|
myKeyword: 2
|
||||||
|
}) .should.equal(true);
|
||||||
|
|
||||||
|
ajv = new Ajv;
|
||||||
|
ajv.validateSchema({ myKeyword: true }) .should.equal(true);
|
||||||
|
ajv.validateSchema({ myKeyword: 2 }) .should.equal(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,97 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('nullable option', function() {
|
||||||
|
var ajv;
|
||||||
|
|
||||||
|
describe('= true', function() {
|
||||||
|
beforeEach(function () {
|
||||||
|
ajv = new Ajv({
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add keyword "nullable"', function() {
|
||||||
|
testNullable({
|
||||||
|
type: 'number',
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
testNullable({
|
||||||
|
type: ['number'],
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
testNullable({
|
||||||
|
type: ['number', 'null']
|
||||||
|
});
|
||||||
|
|
||||||
|
testNullable({
|
||||||
|
type: ['number', 'null'],
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
testNotNullable({type: 'number'});
|
||||||
|
|
||||||
|
testNotNullable({type: ['number']});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should respect "nullable" == false with opts.nullable == true', function() {
|
||||||
|
testNotNullable({
|
||||||
|
type: 'number',
|
||||||
|
nullable: false
|
||||||
|
});
|
||||||
|
|
||||||
|
testNotNullable({
|
||||||
|
type: ['number'],
|
||||||
|
nullable: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('without option "nullable"', function() {
|
||||||
|
it('should ignore keyword nullable', function() {
|
||||||
|
ajv = new Ajv;
|
||||||
|
|
||||||
|
testNotNullable({
|
||||||
|
type: 'number',
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
testNotNullable({
|
||||||
|
type: ['number'],
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
testNullable({
|
||||||
|
type: ['number', 'null'],
|
||||||
|
});
|
||||||
|
|
||||||
|
testNullable({
|
||||||
|
type: ['number', 'null'],
|
||||||
|
nullable: true
|
||||||
|
});
|
||||||
|
|
||||||
|
should.not.throw(function () {
|
||||||
|
ajv.compile({nullable: false});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testNullable(schema) {
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate(1) .should.equal(true);
|
||||||
|
validate(null) .should.equal(true);
|
||||||
|
validate('1') .should.equal(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testNotNullable(schema) {
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate(1) .should.equal(true);
|
||||||
|
validate(null) .should.equal(false);
|
||||||
|
validate('1') .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,130 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('options to add schemas', function() {
|
||||||
|
describe('schemas', function() {
|
||||||
|
it('should add schemas from object', function() {
|
||||||
|
var ajv = new Ajv({ schemas: {
|
||||||
|
int: { type: 'integer' },
|
||||||
|
str: { type: 'string' }
|
||||||
|
}});
|
||||||
|
|
||||||
|
ajv.validate('int', 123) .should.equal(true);
|
||||||
|
ajv.validate('int', 'foo') .should.equal(false);
|
||||||
|
ajv.validate('str', 'foo') .should.equal(true);
|
||||||
|
ajv.validate('str', 123) .should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add schemas from array', function() {
|
||||||
|
var ajv = new Ajv({ schemas: [
|
||||||
|
{ $id: 'int', type: 'integer' },
|
||||||
|
{ $id: 'str', type: 'string' },
|
||||||
|
{ $id: 'obj', properties: { int: { $ref: 'int' }, str: { $ref: 'str' } } }
|
||||||
|
]});
|
||||||
|
|
||||||
|
ajv.validate('obj', { int: 123, str: 'foo' }) .should.equal(true);
|
||||||
|
ajv.validate('obj', { int: 'foo', str: 'bar' }) .should.equal(false);
|
||||||
|
ajv.validate('obj', { int: 123, str: 456 }) .should.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('addUsedSchema', function() {
|
||||||
|
[true, undefined].forEach(function (optionValue) {
|
||||||
|
describe('= ' + optionValue, function() {
|
||||||
|
var ajv;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
ajv = new Ajv({ addUsedSchema: optionValue });
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('compile and validate', function() {
|
||||||
|
it('should add schema', function() {
|
||||||
|
var schema = { $id: 'str', type: 'string' };
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate('abc') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
ajv.getSchema('str') .should.equal(validate);
|
||||||
|
|
||||||
|
schema = { $id: 'int', type: 'integer' };
|
||||||
|
ajv.validate(schema, 1) .should.equal(true);
|
||||||
|
ajv.validate(schema, 'abc') .should.equal(false);
|
||||||
|
ajv.getSchema('int') .should.be.a('function');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw with duplicate ID', function() {
|
||||||
|
ajv.compile({ $id: 'str', type: 'string' });
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.compile({ $id: 'str', minLength: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
|
var schema = { $id: 'int', type: 'integer' };
|
||||||
|
var schema2 = { $id: 'int', minimum: 0 };
|
||||||
|
ajv.validate(schema, 1) .should.equal(true);
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.validate(schema2, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= false', function() {
|
||||||
|
var ajv;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
ajv = new Ajv({ addUsedSchema: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('compile and validate', function() {
|
||||||
|
it('should NOT add schema', function() {
|
||||||
|
var schema = { $id: 'str', type: 'string' };
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate('abc') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
should.equal(ajv.getSchema('str'), undefined);
|
||||||
|
|
||||||
|
schema = { $id: 'int', type: 'integer' };
|
||||||
|
ajv.validate(schema, 1) .should.equal(true);
|
||||||
|
ajv.validate(schema, 'abc') .should.equal(false);
|
||||||
|
should.equal(ajv.getSchema('int'), undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT throw with duplicate ID', function() {
|
||||||
|
ajv.compile({ $id: 'str', type: 'string' });
|
||||||
|
should.not.throw(function() {
|
||||||
|
ajv.compile({ $id: 'str', minLength: 2 });
|
||||||
|
});
|
||||||
|
|
||||||
|
var schema = { $id: 'int', type: 'integer' };
|
||||||
|
var schema2 = { $id: 'int', minimum: 0 };
|
||||||
|
ajv.validate(schema, 1) .should.equal(true);
|
||||||
|
should.not.throw(function() {
|
||||||
|
ajv.validate(schema2, 1) .should.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('serialize', function() {
|
||||||
|
var serializeCalled;
|
||||||
|
|
||||||
|
it('should use custom function to serialize schema to string', function() {
|
||||||
|
serializeCalled = undefined;
|
||||||
|
var ajv = new Ajv({ serialize: serialize });
|
||||||
|
ajv.addSchema({ type: 'string' });
|
||||||
|
should.equal(serializeCalled, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
function serialize(schema) {
|
||||||
|
serializeCalled = true;
|
||||||
|
return JSON.stringify(schema);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,115 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('code generation options', function () {
|
||||||
|
describe('sourceCode', function() {
|
||||||
|
describe('= true', function() {
|
||||||
|
it('should add source.code property', function() {
|
||||||
|
test(new Ajv({sourceCode: true}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({ "type": "number" });
|
||||||
|
validate.source.code .should.be.a('string');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= false and default', function() {
|
||||||
|
it('should not add source and sourceCode properties', function() {
|
||||||
|
test(new Ajv);
|
||||||
|
test(new Ajv({sourceCode: false}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({ "type": "number" });
|
||||||
|
should.not.exist(validate.source);
|
||||||
|
should.not.exist(validate.sourceCode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('processCode', function() {
|
||||||
|
it('should process generated code', function() {
|
||||||
|
var ajv = new Ajv;
|
||||||
|
var validate = ajv.compile({type: 'string'});
|
||||||
|
validate.toString().split('\n').length .should.equal(1);
|
||||||
|
|
||||||
|
var beautify = require('js-beautify').js_beautify;
|
||||||
|
var ajvPC = new Ajv({processCode: beautify});
|
||||||
|
validate = ajvPC.compile({type: 'string'});
|
||||||
|
validate.toString().split('\n').length .should.be.above(1);
|
||||||
|
validate('foo') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('passContext option', function() {
|
||||||
|
var ajv, contexts;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
contexts = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= true', function() {
|
||||||
|
it('should pass this value as context to custom keyword validation function', function() {
|
||||||
|
var validate = getValidate(true);
|
||||||
|
var self = {};
|
||||||
|
validate.call(self, {});
|
||||||
|
contexts .should.have.length(4);
|
||||||
|
contexts.forEach(function(ctx) {
|
||||||
|
ctx .should.equal(self);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= false', function() {
|
||||||
|
it('should pass ajv instance as context to custom keyword validation function', function() {
|
||||||
|
var validate = getValidate(false);
|
||||||
|
var self = {};
|
||||||
|
validate.call(self, {});
|
||||||
|
contexts .should.have.length(4);
|
||||||
|
contexts.forEach(function(ctx) {
|
||||||
|
ctx .should.equal(ajv);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function getValidate(passContext) {
|
||||||
|
ajv = new Ajv({ passContext: passContext, inlineRefs: false });
|
||||||
|
ajv.addKeyword('testValidate', { validate: storeContext });
|
||||||
|
ajv.addKeyword('testCompile', { compile: compileTestValidate });
|
||||||
|
|
||||||
|
var schema = {
|
||||||
|
definitions: {
|
||||||
|
test1: {
|
||||||
|
testValidate: true,
|
||||||
|
testCompile: true,
|
||||||
|
},
|
||||||
|
test2: {
|
||||||
|
allOf: [ { $ref: '#/definitions/test1' } ]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
allOf: [
|
||||||
|
{ $ref: '#/definitions/test1' },
|
||||||
|
{ $ref: '#/definitions/test2' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
return ajv.compile(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeContext() {
|
||||||
|
contexts.push(this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function compileTestValidate() {
|
||||||
|
return storeContext;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,167 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('referenced schema options', function() {
|
||||||
|
describe('extendRefs', function() {
|
||||||
|
describe('= true', function() {
|
||||||
|
it('should allow extending $ref with other keywords', function() {
|
||||||
|
test(new Ajv({ extendRefs: true }), true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT log warning if extendRefs is true', function() {
|
||||||
|
testWarning(new Ajv({ extendRefs: true }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= "ignore" and default', function() {
|
||||||
|
it('should ignore other keywords when $ref is used', function() {
|
||||||
|
test(new Ajv);
|
||||||
|
test(new Ajv({ extendRefs: 'ignore' }), false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should log warning when other keywords are used with $ref', function() {
|
||||||
|
testWarning(new Ajv, /keywords\signored/);
|
||||||
|
testWarning(new Ajv({ extendRefs: 'ignore' }), /keywords\signored/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= "fail"', function() {
|
||||||
|
it('should fail schema compilation if other keywords are used with $ref', function() {
|
||||||
|
testFail(new Ajv({ extendRefs: 'fail' }));
|
||||||
|
|
||||||
|
function testFail(ajv) {
|
||||||
|
should.throw(function() {
|
||||||
|
var schema = {
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"$ref": "#/definitions/int",
|
||||||
|
"minimum": 10
|
||||||
|
};
|
||||||
|
ajv.compile(schema);
|
||||||
|
});
|
||||||
|
|
||||||
|
should.not.throw(function() {
|
||||||
|
var schema = {
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"allOf": [
|
||||||
|
{ "$ref": "#/definitions/int" },
|
||||||
|
{ "minimum": 10 }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
ajv.compile(schema);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function test(ajv, shouldExtendRef) {
|
||||||
|
var schema = {
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"$ref": "#/definitions/int",
|
||||||
|
"minimum": 10
|
||||||
|
};
|
||||||
|
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate(10) .should.equal(true);
|
||||||
|
validate(1) .should.equal(!shouldExtendRef);
|
||||||
|
|
||||||
|
schema = {
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"foo": {
|
||||||
|
"$ref": "#/definitions/int",
|
||||||
|
"minimum": 10
|
||||||
|
},
|
||||||
|
"bar": {
|
||||||
|
"allOf": [
|
||||||
|
{ "$ref": "#/definitions/int" },
|
||||||
|
{ "minimum": 10 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
validate = ajv.compile(schema);
|
||||||
|
validate({ foo: 10, bar: 10 }) .should.equal(true);
|
||||||
|
validate({ foo: 1, bar: 10 }) .should.equal(!shouldExtendRef);
|
||||||
|
validate({ foo: 10, bar: 1 }) .should.equal(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testWarning(ajv, msgPattern) {
|
||||||
|
var oldConsole;
|
||||||
|
try {
|
||||||
|
oldConsole = console.warn;
|
||||||
|
var consoleMsg;
|
||||||
|
console.warn = function() {
|
||||||
|
consoleMsg = Array.prototype.join.call(arguments, ' ');
|
||||||
|
};
|
||||||
|
|
||||||
|
var schema = {
|
||||||
|
"definitions": {
|
||||||
|
"int": { "type": "integer" }
|
||||||
|
},
|
||||||
|
"$ref": "#/definitions/int",
|
||||||
|
"minimum": 10
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.compile(schema);
|
||||||
|
if (msgPattern) consoleMsg .should.match(msgPattern);
|
||||||
|
else should.not.exist(consoleMsg);
|
||||||
|
} finally {
|
||||||
|
console.warn = oldConsole;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('missingRefs', function() {
|
||||||
|
it('should throw if ref is missing without this option', function() {
|
||||||
|
var ajv = new Ajv;
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.compile({ $ref: 'missing_reference' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw and pass validation with missingRef == "ignore"', function() {
|
||||||
|
testMissingRefsIgnore(new Ajv({ missingRefs: 'ignore' }));
|
||||||
|
testMissingRefsIgnore(new Ajv({ missingRefs: 'ignore', allErrors: true }));
|
||||||
|
|
||||||
|
function testMissingRefsIgnore(ajv) {
|
||||||
|
var validate = ajv.compile({ $ref: 'missing_reference' });
|
||||||
|
validate({}) .should.equal(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not throw and fail validation with missingRef == "fail" if the ref is used', function() {
|
||||||
|
testMissingRefsFail(new Ajv({ missingRefs: 'fail' }));
|
||||||
|
testMissingRefsFail(new Ajv({ missingRefs: 'fail', verbose: true }));
|
||||||
|
testMissingRefsFail(new Ajv({ missingRefs: 'fail', allErrors: true }));
|
||||||
|
testMissingRefsFail(new Ajv({ missingRefs: 'fail', allErrors: true, verbose: true }));
|
||||||
|
|
||||||
|
function testMissingRefsFail(ajv) {
|
||||||
|
var validate = ajv.compile({
|
||||||
|
anyOf: [
|
||||||
|
{ type: 'number' },
|
||||||
|
{ $ref: 'missing_reference' }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
validate(123) .should.equal(true);
|
||||||
|
validate('foo') .should.equal(false);
|
||||||
|
|
||||||
|
validate = ajv.compile({ $ref: 'missing_reference' });
|
||||||
|
validate({}) .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,158 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('reporting options', function () {
|
||||||
|
describe('verbose', function() {
|
||||||
|
it('should add schema, parentSchema and data to errors with verbose option == true', function() {
|
||||||
|
testVerbose(new Ajv({ verbose: true }));
|
||||||
|
testVerbose(new Ajv({ verbose: true, allErrors: true }));
|
||||||
|
|
||||||
|
function testVerbose(ajv) {
|
||||||
|
var schema = { properties: { foo: { minimum: 5 } } };
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
var data = { foo: 3 };
|
||||||
|
validate(data) .should.equal(false);
|
||||||
|
validate.errors .should.have.length(1);
|
||||||
|
var err = validate.errors[0];
|
||||||
|
|
||||||
|
should.equal(err.schema, 5);
|
||||||
|
err.parentSchema .should.eql({ minimum: 5 });
|
||||||
|
err.parentSchema .should.equal(schema.properties.foo); // by reference
|
||||||
|
should.equal(err.data, 3);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('allErrors', function() {
|
||||||
|
it('should be disabled inside "not" keyword', function() {
|
||||||
|
test(new Ajv, false);
|
||||||
|
test(new Ajv({ allErrors: true }), true);
|
||||||
|
|
||||||
|
function test(ajv, allErrors) {
|
||||||
|
var format1called = false
|
||||||
|
, format2called = false;
|
||||||
|
|
||||||
|
ajv.addFormat('format1', function() {
|
||||||
|
format1called = true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.addFormat('format2', function() {
|
||||||
|
format2called = true;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
var schema1 = {
|
||||||
|
allOf: [
|
||||||
|
{ format: 'format1' },
|
||||||
|
{ format: 'format2' }
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate(schema1, 'abc') .should.equal(false);
|
||||||
|
ajv.errors .should.have.length(allErrors ? 2 : 1);
|
||||||
|
format1called .should.equal(true);
|
||||||
|
format2called .should.equal(allErrors);
|
||||||
|
|
||||||
|
var schema2 = {
|
||||||
|
not: schema1
|
||||||
|
};
|
||||||
|
|
||||||
|
format1called = format2called = false;
|
||||||
|
ajv.validate(schema2, 'abc') .should.equal(true);
|
||||||
|
should.equal(ajv.errors, null);
|
||||||
|
format1called .should.equal(true);
|
||||||
|
format2called .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('logger', function() {
|
||||||
|
/**
|
||||||
|
* The logger option tests are based on the meta scenario which writes into the logger.warn
|
||||||
|
*/
|
||||||
|
|
||||||
|
var origConsoleWarn = console.warn;
|
||||||
|
var consoleCalled;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
consoleCalled = false;
|
||||||
|
console.warn = function() {
|
||||||
|
consoleCalled = true;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
console.warn = origConsoleWarn;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no custom logger is given - global console should be used', function() {
|
||||||
|
var ajv = new Ajv({
|
||||||
|
meta: false
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.compile({
|
||||||
|
type: 'number',
|
||||||
|
minimum: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
should.equal(consoleCalled, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('custom logger is an object - logs should only report to it', function() {
|
||||||
|
var loggerCalled = false;
|
||||||
|
|
||||||
|
var logger = {
|
||||||
|
warn: log,
|
||||||
|
log: log,
|
||||||
|
error: log
|
||||||
|
};
|
||||||
|
|
||||||
|
var ajv = new Ajv({
|
||||||
|
meta: false,
|
||||||
|
logger: logger
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.compile({
|
||||||
|
type: 'number',
|
||||||
|
minimum: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
should.equal(loggerCalled, true);
|
||||||
|
should.equal(consoleCalled, false);
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
loggerCalled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logger option is false - no logs should be reported', function() {
|
||||||
|
var ajv = new Ajv({
|
||||||
|
meta: false,
|
||||||
|
logger: false
|
||||||
|
});
|
||||||
|
|
||||||
|
ajv.compile({
|
||||||
|
type: 'number',
|
||||||
|
minimum: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
should.equal(consoleCalled, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('logger option is an object without required methods - an error should be thrown', function() {
|
||||||
|
(function(){
|
||||||
|
new Ajv({
|
||||||
|
meta: false,
|
||||||
|
logger: {}
|
||||||
|
});
|
||||||
|
}).should.throw(Error, /logger must implement log, warn and error methods/);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,94 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('validation options', function() {
|
||||||
|
describe('format', function() {
|
||||||
|
it('should not validate formats if option format == false', function() {
|
||||||
|
var ajv = new Ajv
|
||||||
|
, ajvFF = new Ajv({ format: false });
|
||||||
|
|
||||||
|
var schema = { format: 'date-time' };
|
||||||
|
var invalideDateTime = '06/19/1963 08:30:06 PST';
|
||||||
|
|
||||||
|
ajv.validate(schema, invalideDateTime) .should.equal(false);
|
||||||
|
ajvFF.validate(schema, invalideDateTime) .should.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('formats', function() {
|
||||||
|
it('should add formats from options', function() {
|
||||||
|
var ajv = new Ajv({ formats: {
|
||||||
|
identifier: /^[a-z_$][a-z0-9_$]*$/i
|
||||||
|
}});
|
||||||
|
|
||||||
|
var validate = ajv.compile({ format: 'identifier' });
|
||||||
|
validate('Abc1') .should.equal(true);
|
||||||
|
validate('123') .should.equal(false);
|
||||||
|
validate(123) .should.equal(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('uniqueItems', function() {
|
||||||
|
it('should not validate uniqueItems with uniqueItems option == false', function() {
|
||||||
|
testUniqueItems(new Ajv({ uniqueItems: false }));
|
||||||
|
testUniqueItems(new Ajv({ uniqueItems: false, allErrors: true }));
|
||||||
|
|
||||||
|
function testUniqueItems(ajv) {
|
||||||
|
var validate = ajv.compile({ uniqueItems: true });
|
||||||
|
validate([1,2,3]) .should.equal(true);
|
||||||
|
validate([1,1,1]) .should.equal(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('unicode', function() {
|
||||||
|
it('should use String.prototype.length with unicode option == false', function() {
|
||||||
|
var ajvUnicode = new Ajv;
|
||||||
|
testUnicode(new Ajv({ unicode: false }));
|
||||||
|
testUnicode(new Ajv({ unicode: false, allErrors: true }));
|
||||||
|
|
||||||
|
function testUnicode(ajv) {
|
||||||
|
var validateWithUnicode = ajvUnicode.compile({ minLength: 2 });
|
||||||
|
var validate = ajv.compile({ minLength: 2 });
|
||||||
|
|
||||||
|
validateWithUnicode('😀') .should.equal(false);
|
||||||
|
validate('😀') .should.equal(true);
|
||||||
|
|
||||||
|
validateWithUnicode = ajvUnicode.compile({ maxLength: 1 });
|
||||||
|
validate = ajv.compile({ maxLength: 1 });
|
||||||
|
|
||||||
|
validateWithUnicode('😀') .should.equal(true);
|
||||||
|
validate('😀') .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('multipleOfPrecision', function() {
|
||||||
|
it('should allow for some deviation from 0 when validating multipleOf with value < 1', function() {
|
||||||
|
test(new Ajv({ multipleOfPrecision: 7 }));
|
||||||
|
test(new Ajv({ multipleOfPrecision: 7, allErrors: true }));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var schema = { multipleOf: 0.01 };
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
validate(4.18) .should.equal(true);
|
||||||
|
validate(4.181) .should.equal(false);
|
||||||
|
|
||||||
|
schema = { multipleOf: 0.0000001 };
|
||||||
|
validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
validate(53.198098) .should.equal(true);
|
||||||
|
validate(53.1980981) .should.equal(true);
|
||||||
|
validate(53.19809811) .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,178 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('ownProperties option', function() {
|
||||||
|
var ajv, ajvOP, ajvOP1;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
ajv = new Ajv({ allErrors: true });
|
||||||
|
ajvOP = new Ajv({ ownProperties: true, allErrors: true });
|
||||||
|
ajvOP1 = new Ajv({ ownProperties: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with additionalProperties', function() {
|
||||||
|
var schema = {
|
||||||
|
properties: { a: { type: 'number' } },
|
||||||
|
additionalProperties: false
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1 };
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with properties keyword', function() {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
a: { type: 'number' },
|
||||||
|
b: { type: 'number' }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1 };
|
||||||
|
var proto = { b: 'not a number' };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with required keyword', function() {
|
||||||
|
var schema = {
|
||||||
|
required: ['a', 'b']
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1 };
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto, 1, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with required keyword - many properties', function() {
|
||||||
|
ajv = new Ajv({ allErrors: true, loopRequired: 1 });
|
||||||
|
ajvOP = new Ajv({ ownProperties: true, allErrors: true, loopRequired: 1 });
|
||||||
|
ajvOP1 = new Ajv({ ownProperties: true, loopRequired: 1 });
|
||||||
|
|
||||||
|
var schema = {
|
||||||
|
required: ['a', 'b', 'c', 'd']
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1, b: 2 };
|
||||||
|
var proto = { c: 3, d: 4 };
|
||||||
|
test(schema, obj, proto, 2, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with required keyword as $data', function() {
|
||||||
|
ajv = new Ajv({ allErrors: true, $data: true });
|
||||||
|
ajvOP = new Ajv({ ownProperties: true, allErrors: true, $data: true });
|
||||||
|
ajvOP1 = new Ajv({ ownProperties: true, $data: true });
|
||||||
|
|
||||||
|
var schema = {
|
||||||
|
required: { $data: '0/req' },
|
||||||
|
properties: {
|
||||||
|
req: {
|
||||||
|
type: 'array',
|
||||||
|
items: { type: 'string' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
req: ['a', 'b'],
|
||||||
|
a: 1
|
||||||
|
};
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto, 1, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with properties and required keyword', function() {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
a: { type: 'number' },
|
||||||
|
b: { type: 'number' }
|
||||||
|
},
|
||||||
|
required: ['a', 'b']
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1 };
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto, 1, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with dependencies keyword', function() {
|
||||||
|
var schema = {
|
||||||
|
dependencies: {
|
||||||
|
a: ['c'],
|
||||||
|
b: ['d']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1, c: 3 };
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
|
||||||
|
obj = { a: 1, b: 2, c: 3 };
|
||||||
|
proto = { d: 4 };
|
||||||
|
test(schema, obj, proto, 1, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with schema dependencies', function() {
|
||||||
|
var schema = {
|
||||||
|
dependencies: {
|
||||||
|
a: { not: { required: ['c'] } },
|
||||||
|
b: { not: { required: ['d'] } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { a: 1, d: 3 };
|
||||||
|
var proto = { b: 2 };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
|
||||||
|
obj = { a: 1, b: 2 };
|
||||||
|
proto = { d: 4 };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with patternProperties', function() {
|
||||||
|
var schema = {
|
||||||
|
patternProperties: { 'f.*o': { type: 'integer' } },
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { fooo: 1 };
|
||||||
|
var proto = { foo: 'not a number' };
|
||||||
|
test(schema, obj, proto);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should only validate own properties with propertyNames', function() {
|
||||||
|
var schema = {
|
||||||
|
propertyNames: {
|
||||||
|
format: 'email'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var obj = { 'e@example.com': 2 };
|
||||||
|
var proto = { 'not email': 1 };
|
||||||
|
test(schema, obj, proto, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
function test(schema, obj, proto, errors, reverse) {
|
||||||
|
errors = errors || 1;
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
var validateOP = ajvOP.compile(schema);
|
||||||
|
var validateOP1 = ajvOP1.compile(schema);
|
||||||
|
var data = Object.create(proto);
|
||||||
|
for (var key in obj) data[key] = obj[key];
|
||||||
|
|
||||||
|
if (reverse) {
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
validateOP(data) .should.equal(false);
|
||||||
|
validateOP.errors .should.have.length(errors);
|
||||||
|
validateOP1(data) .should.equal(false);
|
||||||
|
validateOP1.errors .should.have.length(1);
|
||||||
|
} else {
|
||||||
|
validate(data) .should.equal(false);
|
||||||
|
validate.errors .should.have.length(errors);
|
||||||
|
validateOP(data) .should.equal(true);
|
||||||
|
validateOP1(data) .should.equal(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,122 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('removeAdditional option', function() {
|
||||||
|
it('should remove all additional properties', function() {
|
||||||
|
var ajv = new Ajv({ removeAdditional: 'all' });
|
||||||
|
|
||||||
|
ajv.addSchema({
|
||||||
|
$id: '//test/fooBar',
|
||||||
|
properties: { foo: { type: 'string' }, bar: { type: 'string' } }
|
||||||
|
});
|
||||||
|
|
||||||
|
var object = {
|
||||||
|
foo: 'foo', bar: 'bar', baz: 'baz-to-be-removed'
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate('//test/fooBar', object).should.equal(true);
|
||||||
|
object.should.have.property('foo');
|
||||||
|
object.should.have.property('bar');
|
||||||
|
object.should.not.have.property('baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should remove properties that would error when `additionalProperties = false`', function() {
|
||||||
|
var ajv = new Ajv({ removeAdditional: true });
|
||||||
|
|
||||||
|
ajv.addSchema({
|
||||||
|
$id: '//test/fooBar',
|
||||||
|
properties: { foo: { type: 'string' }, bar: { type: 'string' } },
|
||||||
|
additionalProperties: false
|
||||||
|
});
|
||||||
|
|
||||||
|
var object = {
|
||||||
|
foo: 'foo', bar: 'bar', baz: 'baz-to-be-removed'
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate('//test/fooBar', object).should.equal(true);
|
||||||
|
object.should.have.property('foo');
|
||||||
|
object.should.have.property('bar');
|
||||||
|
object.should.not.have.property('baz');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should remove properties that would error when `additionalProperties = false` (many properties, boolean schema)', function() {
|
||||||
|
var ajv = new Ajv({removeAdditional: true});
|
||||||
|
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
obj: {
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
a: { type: 'string' },
|
||||||
|
b: false,
|
||||||
|
c: { type: 'string' },
|
||||||
|
d: { type: 'string' },
|
||||||
|
e: { type: 'string' },
|
||||||
|
f: { type: 'string' },
|
||||||
|
g: { type: 'string' },
|
||||||
|
h: { type: 'string' },
|
||||||
|
i: { type: 'string' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var data = {
|
||||||
|
obj: {
|
||||||
|
a: 'valid',
|
||||||
|
b: 'should not be removed',
|
||||||
|
additional: 'will be removed'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate(schema, data) .should.equal(false);
|
||||||
|
data .should.eql({
|
||||||
|
obj: {
|
||||||
|
a: 'valid',
|
||||||
|
b: 'should not be removed'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should remove properties that would error when `additionalProperties` is a schema', function() {
|
||||||
|
var ajv = new Ajv({ removeAdditional: 'failing' });
|
||||||
|
|
||||||
|
ajv.addSchema({
|
||||||
|
$id: '//test/fooBar',
|
||||||
|
properties: { foo: { type: 'string' }, bar: { type: 'string' } },
|
||||||
|
additionalProperties: { type: 'string' }
|
||||||
|
});
|
||||||
|
|
||||||
|
var object = {
|
||||||
|
foo: 'foo', bar: 'bar', baz: 'baz-to-be-kept', fizz: 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate('//test/fooBar', object).should.equal(true);
|
||||||
|
object.should.have.property('foo');
|
||||||
|
object.should.have.property('bar');
|
||||||
|
object.should.have.property('baz');
|
||||||
|
object.should.not.have.property('fizz');
|
||||||
|
|
||||||
|
ajv.addSchema({
|
||||||
|
$id: '//test/fooBar2',
|
||||||
|
properties: { foo: { type: 'string' }, bar: { type: 'string' } },
|
||||||
|
additionalProperties: { type: 'string', pattern: '^to-be-', maxLength: 10 }
|
||||||
|
});
|
||||||
|
|
||||||
|
object = {
|
||||||
|
foo: 'foo', bar: 'bar', baz: 'to-be-kept', quux: 'to-be-removed', fizz: 1000
|
||||||
|
};
|
||||||
|
|
||||||
|
ajv.validate('//test/fooBar2', object).should.equal(true);
|
||||||
|
object.should.have.property('foo');
|
||||||
|
object.should.have.property('bar');
|
||||||
|
object.should.have.property('baz');
|
||||||
|
object.should.not.have.property('fizz');
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,72 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('schemaId option', function() {
|
||||||
|
describe('= "$id" (default)', function() {
|
||||||
|
it('should use $id and ignore id', function() {
|
||||||
|
test(new Ajv);
|
||||||
|
test(new Ajv({schemaId: '$id'}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
ajv.addSchema({ $id: 'mySchema1', type: 'string' });
|
||||||
|
var validate = ajv.getSchema('mySchema1');
|
||||||
|
validate('foo') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
|
||||||
|
validate = ajv.compile({ id: 'mySchema2', type: 'string' });
|
||||||
|
should.not.exist(ajv.getSchema('mySchema2'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= "id"', function() {
|
||||||
|
it('should use id and ignore $id', function() {
|
||||||
|
var ajv = new Ajv({schemaId: 'id', meta: false});
|
||||||
|
ajv.addMetaSchema(require('../../lib/refs/json-schema-draft-04.json'));
|
||||||
|
ajv._opts.defaultMeta = 'http://json-schema.org/draft-04/schema#';
|
||||||
|
|
||||||
|
ajv.addSchema({ id: 'mySchema1', type: 'string' });
|
||||||
|
var validate = ajv.getSchema('mySchema1');
|
||||||
|
validate('foo') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
|
||||||
|
validate = ajv.compile({ $id: 'mySchema2', type: 'string' });
|
||||||
|
should.not.exist(ajv.getSchema('mySchema2'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= "auto"', function() {
|
||||||
|
it('should use both id and $id', function() {
|
||||||
|
var ajv = new Ajv({schemaId: 'auto'});
|
||||||
|
|
||||||
|
ajv.addSchema({ $id: 'mySchema1', type: 'string' });
|
||||||
|
var validate = ajv.getSchema('mySchema1');
|
||||||
|
validate('foo') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
|
||||||
|
ajv.addSchema({ id: 'mySchema2', type: 'string' });
|
||||||
|
validate = ajv.getSchema('mySchema2');
|
||||||
|
validate('foo') .should.equal(true);
|
||||||
|
validate(1) .should.equal(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw if both id and $id are available and different', function() {
|
||||||
|
var ajv = new Ajv({schemaId: 'auto'});
|
||||||
|
|
||||||
|
ajv.compile({
|
||||||
|
id: 'mySchema',
|
||||||
|
$id: 'mySchema'
|
||||||
|
});
|
||||||
|
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.compile({
|
||||||
|
id: 'mySchema1',
|
||||||
|
$id: 'mySchema2'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,108 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var should = require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('unknownFormats option', function() {
|
||||||
|
describe('= true (default)', function() {
|
||||||
|
it('should fail schema compilation if unknown format is used', function() {
|
||||||
|
test(new Ajv);
|
||||||
|
test(new Ajv({unknownFormats: true}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.compile({ format: 'unknown' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail validation if unknown format is used via $data', function() {
|
||||||
|
test(new Ajv({$data: true}));
|
||||||
|
test(new Ajv({$data: true, unknownFormats: true}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({
|
||||||
|
properties: {
|
||||||
|
foo: { format: { $data: '1/bar' } },
|
||||||
|
bar: { type: 'string' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validate({foo: 1, bar: 'unknown'}) .should.equal(false);
|
||||||
|
validate({foo: '2016-10-16', bar: 'date'}) .should.equal(true);
|
||||||
|
validate({foo: '20161016', bar: 'date'}) .should.equal(false);
|
||||||
|
validate({foo: '20161016'}) .should.equal(true);
|
||||||
|
|
||||||
|
validate({foo: '2016-10-16', bar: 'unknown'}) .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= "ignore (default before 5.0.0)"', function() {
|
||||||
|
it('should pass schema compilation and be valid if unknown format is used', function() {
|
||||||
|
test(new Ajv({unknownFormats: 'ignore'}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({ format: 'unknown' });
|
||||||
|
validate('anything') .should.equal(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be valid if unknown format is used via $data', function() {
|
||||||
|
test(new Ajv({$data: true, unknownFormats: 'ignore'}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({
|
||||||
|
properties: {
|
||||||
|
foo: { format: { $data: '1/bar' } },
|
||||||
|
bar: { type: 'string' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validate({foo: 1, bar: 'unknown'}) .should.equal(true);
|
||||||
|
validate({foo: '2016-10-16', bar: 'date'}) .should.equal(true);
|
||||||
|
validate({foo: '20161016', bar: 'date'}) .should.equal(false);
|
||||||
|
validate({foo: '20161016'}) .should.equal(true);
|
||||||
|
validate({foo: '2016-10-16', bar: 'unknown'}) .should.equal(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('= [String]', function() {
|
||||||
|
it('should pass schema compilation and be valid if whitelisted unknown format is used', function() {
|
||||||
|
test(new Ajv({unknownFormats: ['allowed']}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({ format: 'allowed' });
|
||||||
|
validate('anything') .should.equal(true);
|
||||||
|
|
||||||
|
should.throw(function() {
|
||||||
|
ajv.compile({ format: 'unknown' });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be valid if whitelisted unknown format is used via $data', function() {
|
||||||
|
test(new Ajv({$data: true, unknownFormats: ['allowed']}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile({
|
||||||
|
properties: {
|
||||||
|
foo: { format: { $data: '1/bar' } },
|
||||||
|
bar: { type: 'string' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
validate({foo: 1, bar: 'allowed'}) .should.equal(true);
|
||||||
|
validate({foo: 1, bar: 'unknown'}) .should.equal(false);
|
||||||
|
validate({foo: '2016-10-16', bar: 'date'}) .should.equal(true);
|
||||||
|
validate({foo: '20161016', bar: 'date'}) .should.equal(false);
|
||||||
|
validate({foo: '20161016'}) .should.equal(true);
|
||||||
|
|
||||||
|
validate({foo: '2016-10-16', bar: 'allowed'}) .should.equal(true);
|
||||||
|
validate({foo: '2016-10-16', bar: 'unknown'}) .should.equal(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,223 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Ajv = require('../ajv');
|
||||||
|
var getAjvInstances = require('../ajv_instances');
|
||||||
|
require('../chai').should();
|
||||||
|
|
||||||
|
|
||||||
|
describe('useDefaults options', function() {
|
||||||
|
it('should replace undefined property with default value', function() {
|
||||||
|
var instances = getAjvInstances({
|
||||||
|
allErrors: true,
|
||||||
|
loopRequired: 3
|
||||||
|
}, { useDefaults: true });
|
||||||
|
|
||||||
|
instances.forEach(test);
|
||||||
|
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
foo: { type: 'string', default: 'abc' },
|
||||||
|
bar: { type: 'number', default: 1 },
|
||||||
|
baz: { type: 'boolean', default: false },
|
||||||
|
nil: { type: 'null', default: null },
|
||||||
|
obj: { type: 'object', default: {} },
|
||||||
|
arr: { type: 'array', default: [] }
|
||||||
|
},
|
||||||
|
required: ['foo', 'bar', 'baz', 'nil', 'obj', 'arr'],
|
||||||
|
minProperties: 6
|
||||||
|
};
|
||||||
|
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({ foo: 'abc', bar: 1, baz: false, nil: null, obj: {}, arr:[] });
|
||||||
|
|
||||||
|
data = { foo: 'foo', bar: 2, obj: { test: true } };
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({ foo: 'foo', bar: 2, baz: false, nil: null, obj: { test: true }, arr:[] });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should replace undefined item with default value', function() {
|
||||||
|
test(new Ajv({ useDefaults: true }));
|
||||||
|
test(new Ajv({ useDefaults: true, allErrors: true }));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var schema = {
|
||||||
|
items: [
|
||||||
|
{ type: 'string', default: 'abc' },
|
||||||
|
{ type: 'number', default: 1 },
|
||||||
|
{ type: 'boolean', default: false }
|
||||||
|
],
|
||||||
|
minItems: 3
|
||||||
|
};
|
||||||
|
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
var data = [];
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql([ 'abc', 1, false ]);
|
||||||
|
|
||||||
|
data = [ 'foo' ];
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql([ 'foo', 1, false ]);
|
||||||
|
|
||||||
|
data = ['foo', 2,'false'];
|
||||||
|
validate(data) .should.equal(false);
|
||||||
|
validate.errors .should.have.length(1);
|
||||||
|
data .should.eql([ 'foo', 2, 'false' ]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply default in "then" subschema (issue #635)', function() {
|
||||||
|
test(new Ajv({ useDefaults: true }));
|
||||||
|
test(new Ajv({ useDefaults: true, allErrors: true }));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var schema = {
|
||||||
|
if: { required: ['foo'] },
|
||||||
|
then: {
|
||||||
|
properties: {
|
||||||
|
bar: { default: 2 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else: {
|
||||||
|
properties: {
|
||||||
|
foo: { default: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({foo: 1});
|
||||||
|
|
||||||
|
data = {foo: 1};
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({foo: 1, bar: 2});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('useDefaults: by value / by reference', function() {
|
||||||
|
describe('using by value', function() {
|
||||||
|
it('should NOT modify underlying defaults when modifying validated data', function() {
|
||||||
|
test('value', new Ajv({ useDefaults: true }));
|
||||||
|
test('value', new Ajv({ useDefaults: true, allErrors: true }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('using by reference', function() {
|
||||||
|
it('should modify underlying defaults when modifying validated data', function() {
|
||||||
|
test('reference', new Ajv({ useDefaults: 'shared' }));
|
||||||
|
test('reference', new Ajv({ useDefaults: 'shared', allErrors: true }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function test(useDefaultsMode, ajv) {
|
||||||
|
var schema = {
|
||||||
|
properties: {
|
||||||
|
items: {
|
||||||
|
type: 'array',
|
||||||
|
default: ['a-default']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
var data = {};
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data.items .should.eql([ 'a-default' ]);
|
||||||
|
|
||||||
|
data.items.push('another-value');
|
||||||
|
data.items .should.eql([ 'a-default', 'another-value' ]);
|
||||||
|
|
||||||
|
var data2 = {};
|
||||||
|
validate(data2) .should.equal(true);
|
||||||
|
|
||||||
|
if (useDefaultsMode == 'reference')
|
||||||
|
data2.items .should.eql([ 'a-default', 'another-value' ]);
|
||||||
|
else if (useDefaultsMode == 'value')
|
||||||
|
data2.items .should.eql([ 'a-default' ]);
|
||||||
|
else
|
||||||
|
throw new Error('unknown useDefaults mode');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe('defaults with "empty" values', function() {
|
||||||
|
var schema, data;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
schema = {
|
||||||
|
properties: {
|
||||||
|
obj: {
|
||||||
|
properties: {
|
||||||
|
str: {default: 'foo'},
|
||||||
|
n1: {default: 1},
|
||||||
|
n2: {default: 2},
|
||||||
|
n3: {default: 3}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
arr: {
|
||||||
|
items: [
|
||||||
|
{default: 'foo'},
|
||||||
|
{default: 1},
|
||||||
|
{default: 2},
|
||||||
|
{default: 3}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
data = {
|
||||||
|
obj: {
|
||||||
|
str: '',
|
||||||
|
n1: null,
|
||||||
|
n2: undefined
|
||||||
|
},
|
||||||
|
arr: ['', null, undefined]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should NOT assign defaults when useDefaults is true/"shared"', function() {
|
||||||
|
test(new Ajv({useDefaults: true}));
|
||||||
|
test(new Ajv({useDefaults: 'shared'}));
|
||||||
|
|
||||||
|
function test(ajv) {
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({
|
||||||
|
obj: {
|
||||||
|
str: '',
|
||||||
|
n1: null,
|
||||||
|
n2: 2,
|
||||||
|
n3: 3
|
||||||
|
},
|
||||||
|
arr: ['', null, 2, 3]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should assign defaults when useDefaults = "empty"', function() {
|
||||||
|
var ajv = new Ajv({useDefaults: 'empty'});
|
||||||
|
var validate = ajv.compile(schema);
|
||||||
|
validate(data) .should.equal(true);
|
||||||
|
data .should.eql({
|
||||||
|
obj: {
|
||||||
|
str: 'foo',
|
||||||
|
n1: 1,
|
||||||
|
n2: 2,
|
||||||
|
n3: 3
|
||||||
|
},
|
||||||
|
arr: ['foo', 1, 2, 3]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue