123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900 |
- 'use strict';
- var Ajv = require('./ajv')
- , should = require('./chai').should();
- describe('Validation errors', function () {
- var ajv, ajvJP, fullAjv;
- beforeEach(function() {
- createInstances();
- });
- function createInstances(errorDataPath) {
- ajv = new Ajv({ errorDataPath: errorDataPath, loopRequired: 21 });
- ajvJP = new Ajv({ errorDataPath: errorDataPath, jsonPointers: true, loopRequired: 21 });
- fullAjv = new Ajv({ errorDataPath: errorDataPath, allErrors: true, verbose: true, jsonPointers: true, loopRequired: 21 });
- }
- it('error should include dataPath', function() {
- var schema = {
- properties: {
- foo: { type: 'number' }
- }
- };
- testSchema1(schema);
- });
- it('"refs" error should include dataPath', function() {
- var schema = {
- definitions: {
- num: { type: 'number' }
- },
- properties: {
- foo: { $ref: '#/definitions/num' }
- }
- };
- testSchema1(schema, '#/definitions/num');
- });
- describe('"additionalProperties" errors', function() {
- it('should include property in dataPath with option errorDataPath="property"', function() {
- createInstances('property');
- testAdditional('property');
- });
- it('should NOT include property in dataPath WITHOUT option errorDataPath', function() {
- testAdditional();
- });
- function testAdditional(errorDataPath) {
- var schema = {
- properties: {
- foo: {},
- bar: {}
- },
- additionalProperties: false
- };
- var data = { foo: 1, bar: 2 }
- , invalidData = { foo: 1, bar: 2, baz: 3, quux: 4 };
- var path = pathFunc(errorDataPath);
- var msg = additionalFunc(errorDataPath);
- var validate = ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData);
- shouldBeError(validate.errors[0], 'additionalProperties', '#/additionalProperties', path("['baz']"), msg, { additionalProperty: 'baz' });
- var validateJP = ajvJP.compile(schema);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData);
- shouldBeError(validateJP.errors[0], 'additionalProperties', '#/additionalProperties', path("/baz"), msg, { additionalProperty: 'baz' });
- var fullValidate = fullAjv.compile(schema);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData, 2);
- shouldBeError(fullValidate.errors[0], 'additionalProperties', '#/additionalProperties', path('/baz'), msg, { additionalProperty: 'baz' });
- shouldBeError(fullValidate.errors[1], 'additionalProperties', '#/additionalProperties', path('/quux'), msg, { additionalProperty: 'quux' });
- if (errorDataPath == 'property') {
- fullValidate.errors
- .filter(function(err) { return err.keyword == 'additionalProperties'; })
- .map(function(err) { return fullAjv._opts.jsonPointers ? err.dataPath.substr(1) : err.dataPath.slice(2,-2); })
- .forEach(function(p) { delete invalidData[p]; });
- invalidData .should.eql({ foo: 1, bar: 2 });
- }
- }
- });
- describe('errors when "additionalProperties" is schema', function() {
- it('should include property in dataPath with option errorDataPath="property"', function() {
- createInstances('property');
- testAdditionalIsSchema('property');
- });
- it('should NOT include property in dataPath WITHOUT option errorDataPath', function() {
- testAdditionalIsSchema();
- });
- function testAdditionalIsSchema() {
- var schema = {
- properties: {
- foo: { type: 'integer' },
- bar: { type: 'integer' }
- },
- additionalProperties: {
- type: 'object',
- properties: {
- quux: { type: 'string' }
- }
- }
- };
- var data = { foo: 1, bar: 2, baz: { quux: 'abc' } }
- , invalidData = { foo: 1, bar: 2, baz: { quux: 3 }, boo: { quux: 4 } };
- var schPath = '#/additionalProperties/properties/quux/type';
- var validate = ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData);
- shouldBeError(validate.errors[0], 'type', schPath, "['baz'].quux", 'should be string', { type: 'string' });
- var validateJP = ajvJP.compile(schema);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData);
- shouldBeError(validateJP.errors[0], 'type', schPath, "/baz/quux", 'should be string', { type: 'string' });
- var fullValidate = fullAjv.compile(schema);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData, 2);
- shouldBeError(fullValidate.errors[0], 'type', schPath, '/baz/quux', 'should be string', { type: 'string' });
- shouldBeError(fullValidate.errors[1], 'type', schPath, '/boo/quux', 'should be string', { type: 'string' });
- }
- });
- describe('"required" errors', function() {
- it('should include missing property in dataPath with option errorDataPath="property"', function() {
- createInstances('property');
- testRequired('property');
- });
- it('should NOT include missing property in dataPath WITHOUT option errorDataPath', function() {
- testRequired();
- });
- function testRequired(errorDataPath) {
- var schema = {
- required: ['foo', 'bar', 'baz']
- };
- _testRequired(errorDataPath, schema, '#', '.');
- }
- it('large data/schemas with option errorDataPath="property"', function() {
- createInstances('property');
- testRequiredLargeSchema('property');
- });
- it('large data/schemas WITHOUT option errorDataPath', function() {
- testRequiredLargeSchema();
- });
- function testRequiredLargeSchema(errorDataPath) {
- var schema = { required: [] }
- , data = {}
- , invalidData1 = {}
- , invalidData2 = {};
- for (var i=0; i<100; i++) {
- schema.required.push(''+i); // properties from '0' to '99' are required
- data[i] = invalidData1[i] = invalidData2[i] = i;
- }
- delete invalidData1[1]; // property '1' will be missing
- delete invalidData2[2]; // properties '2' and '198' will be missing
- delete invalidData2[98];
- var path = pathFunc(errorDataPath);
- var msg = requiredFunc(errorDataPath);
- test();
- schema = { anyOf: [ schema ] };
- test(1, '#/anyOf/0');
- function test(extraErrors, schemaPathPrefix) {
- extraErrors = extraErrors || 0;
- var schPath = (schemaPathPrefix || '#') + '/required';
- var validate = ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData1, 1 + extraErrors);
- shouldBeError(validate.errors[0], 'required', schPath, path("['1']"), msg('1'), { missingProperty: '1' });
- shouldBeInvalid(validate, invalidData2, 1 + extraErrors);
- shouldBeError(validate.errors[0], 'required', schPath, path("['2']"), msg('2'), { missingProperty: '2' });
- var validateJP = ajvJP.compile(schema);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData1, 1 + extraErrors);
- shouldBeError(validateJP.errors[0], 'required', schPath, path("/1"), msg('1'), { missingProperty: '1' });
- shouldBeInvalid(validateJP, invalidData2, 1 + extraErrors);
- shouldBeError(validateJP.errors[0], 'required', schPath, path("/2"), msg('2'), { missingProperty: '2' });
- var fullValidate = fullAjv.compile(schema);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData1, 1 + extraErrors);
- shouldBeError(fullValidate.errors[0], 'required', schPath, path('/1'), msg('1'), { missingProperty: '1' });
- shouldBeInvalid(fullValidate, invalidData2, 2 + extraErrors);
- shouldBeError(fullValidate.errors[0], 'required', schPath, path('/2'), msg('2'), { missingProperty: '2' });
- shouldBeError(fullValidate.errors[1], 'required', schPath, path('/98'), msg('98'), { missingProperty: '98' });
- }
- }
- it('with "properties" with option errorDataPath="property"', function() {
- createInstances('property');
- testRequiredAndProperties('property');
- });
- it('with "properties" WITHOUT option errorDataPath', function() {
- testRequiredAndProperties();
- });
- function testRequiredAndProperties(errorDataPath) {
- var schema = {
- properties: {
- 'foo': { type: 'number' },
- 'bar': { type: 'number' },
- 'baz': { type: 'number' },
- },
- required: ['foo', 'bar', 'baz']
- };
- _testRequired(errorDataPath, schema);
- }
- it('in "anyOf" with option errorDataPath="property"', function() {
- createInstances('property');
- testRequiredInAnyOf('property');
- });
- it('in "anyOf" WITHOUT option errorDataPath', function() {
- testRequiredInAnyOf();
- });
- function testRequiredInAnyOf(errorDataPath) {
- var schema = {
- anyOf: [
- { required: ['foo', 'bar', 'baz'] }
- ]
- };
- _testRequired(errorDataPath, schema, '#/anyOf/0', '.', 1);
- }
- it('should not validate required twice in large schemas with loopRequired option', function() {
- ajv = new Ajv({ loopRequired: 1, allErrors: true });
- var schema = {
- properties: {
- foo: { type: 'integer' },
- bar: { type: 'integer' }
- },
- required: ['foo', 'bar']
- };
- var validate = ajv.compile(schema);
- validate({}) .should.equal(false);
- validate.errors .should.have.length(2);
- });
- it('should not validate required twice with $data ref', function() {
- ajv = new Ajv({ $data: true, allErrors: true });
- var schema = {
- properties: {
- foo: { type: 'integer' },
- bar: { type: 'integer' }
- },
- required: { $data: '0/requiredProperties' }
- };
- var validate = ajv.compile(schema);
- validate({ requiredProperties: ['foo', 'bar'] }) .should.equal(false);
- validate.errors .should.have.length(2);
- });
- });
- describe('"dependencies" errors', function() {
- it('should include missing property in dataPath with option errorDataPath="property"', function() {
- createInstances('property');
- testDependencies('property');
- });
- it('should NOT include missing property in dataPath WITHOUT option errorDataPath', function() {
- testDependencies();
- });
- function testDependencies(errorDataPath) {
- var schema = {
- dependencies: {
- a: ['foo', 'bar', 'baz']
- }
- };
- var data = { a: 0, foo: 1, bar: 2, baz: 3 }
- , invalidData1 = { a: 0, foo: 1, baz: 3 }
- , invalidData2 = { a: 0, bar: 2 };
- var path = pathFunc(errorDataPath);
- var msg = 'should have properties foo, bar, baz when property a is present';
- var validate = ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData1);
- shouldBeError(validate.errors[0], 'dependencies', '#/dependencies', path('.bar'), msg, params('.bar'));
- shouldBeInvalid(validate, invalidData2);
- shouldBeError(validate.errors[0], 'dependencies', '#/dependencies', path('.foo'), msg, params('.foo'));
- var validateJP = ajvJP.compile(schema);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData1);
- shouldBeError(validateJP.errors[0], 'dependencies', '#/dependencies', path('/bar'), msg, params('bar'));
- shouldBeInvalid(validateJP, invalidData2);
- shouldBeError(validateJP.errors[0], 'dependencies', '#/dependencies', path('/foo'), msg, params('foo'));
- var fullValidate = fullAjv.compile(schema);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData1);
- shouldBeError(fullValidate.errors[0], 'dependencies', '#/dependencies', path('/bar'), msg, params('bar'));
- shouldBeInvalid(fullValidate, invalidData2, 2);
- shouldBeError(fullValidate.errors[0], 'dependencies', '#/dependencies', path('/foo'), msg, params('foo'));
- shouldBeError(fullValidate.errors[1], 'dependencies', '#/dependencies', path('/baz'), msg, params('baz'));
- function params(missing) {
- var p = {
- property: 'a',
- deps: 'foo, bar, baz',
- depsCount: 3
- };
- p.missingProperty = missing;
- return p;
- }
- }
- });
- function _testRequired(errorDataPath, schema, schemaPathPrefix, prefix, extraErrors) {
- var schPath = (schemaPathPrefix || '#') + '/required';
- prefix = prefix || '';
- extraErrors = extraErrors || 0;
- var data = { foo: 1, bar: 2, baz: 3 }
- , invalidData1 = { foo: 1, baz: 3 }
- , invalidData2 = { bar: 2 };
- var path = pathFunc(errorDataPath);
- var msg = requiredFunc(errorDataPath);
- var validate = ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData1, 1 + extraErrors);
- shouldBeError(validate.errors[0], 'required', schPath, path('.bar'), msg(prefix + 'bar'), { missingProperty: prefix + 'bar' });
- shouldBeInvalid(validate, invalidData2, 1 + extraErrors);
- shouldBeError(validate.errors[0], 'required', schPath, path('.foo'), msg(prefix + 'foo'), { missingProperty: prefix + 'foo' });
- var validateJP = ajvJP.compile(schema);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData1, 1 + extraErrors);
- shouldBeError(validateJP.errors[0], 'required', schPath, path('/bar'), msg('bar'), { missingProperty: 'bar' });
- shouldBeInvalid(validateJP, invalidData2, 1 + extraErrors);
- shouldBeError(validateJP.errors[0], 'required', schPath, path('/foo'), msg('foo'), { missingProperty: 'foo' });
- var fullValidate = fullAjv.compile(schema);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData1, 1 + extraErrors);
- shouldBeError(fullValidate.errors[0], 'required', schPath, path('/bar'), msg('bar'), { missingProperty: 'bar' });
- shouldBeInvalid(fullValidate, invalidData2, 2 + extraErrors);
- shouldBeError(fullValidate.errors[0], 'required', schPath, path('/foo'), msg('foo'), { missingProperty: 'foo' });
- shouldBeError(fullValidate.errors[1], 'required', schPath, path('/baz'), msg('baz'), { missingProperty: 'baz' });
- }
- function pathFunc(errorDataPath) {
- return function (dataPath) {
- return errorDataPath == 'property' ? dataPath : '';
- };
- }
- function requiredFunc(errorDataPath) {
- return function (prop) {
- return errorDataPath == 'property'
- ? 'is a required property'
- : 'should have required property \'' + prop + '\'';
- };
- }
- function additionalFunc(errorDataPath) {
- return errorDataPath == 'property'
- ? 'is an invalid additional property'
- : 'should NOT have additional properties';
- }
- it('"items" errors should include item index without quotes in dataPath (#48)', function() {
- var schema1 = {
- $id: 'schema1',
- type: 'array',
- items: {
- type: 'integer',
- minimum: 10
- }
- };
- var data = [ 10, 11, 12]
- , invalidData1 = [ 1, 10 ]
- , invalidData2 = [ 10, 9, 11, 8, 12];
- var validate = ajv.compile(schema1);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData1);
- shouldBeError(validate.errors[0], 'minimum', '#/items/minimum', '[0]', 'should be >= 10');
- shouldBeInvalid(validate, invalidData2);
- shouldBeError(validate.errors[0], 'minimum', '#/items/minimum', '[1]', 'should be >= 10');
- var validateJP = ajvJP.compile(schema1);
- shouldBeValid(validateJP, data);
- shouldBeInvalid(validateJP, invalidData1);
- shouldBeError(validateJP.errors[0], 'minimum', '#/items/minimum', '/0', 'should be >= 10');
- shouldBeInvalid(validateJP, invalidData2);
- shouldBeError(validateJP.errors[0], 'minimum', '#/items/minimum', '/1', 'should be >= 10');
- var fullValidate = fullAjv.compile(schema1);
- shouldBeValid(fullValidate, data);
- shouldBeInvalid(fullValidate, invalidData1);
- shouldBeError(fullValidate.errors[0], 'minimum', '#/items/minimum', '/0', 'should be >= 10');
- shouldBeInvalid(fullValidate, invalidData2, 2);
- shouldBeError(fullValidate.errors[0], 'minimum', '#/items/minimum', '/1', 'should be >= 10');
- shouldBeError(fullValidate.errors[1], 'minimum', '#/items/minimum', '/3', 'should be >= 10');
- var schema2 = {
- $id: 'schema2',
- type: 'array',
- items: [{ minimum: 10 }, { minimum: 9 }, { minimum: 12 }]
- };
- validate = ajv.compile(schema2);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData1);
- shouldBeError(validate.errors[0], 'minimum', '#/items/0/minimum', '[0]', 'should be >= 10');
- shouldBeInvalid(validate, invalidData2);
- shouldBeError(validate.errors[0], 'minimum', '#/items/2/minimum', '[2]', 'should be >= 12');
- });
- it('should have correct schema path for additionalItems', function() {
- var schema = {
- type: 'array',
- items: [ { type: 'integer' }, { type: 'integer' } ],
- additionalItems: false
- };
- var data = [ 1, 2 ]
- , invalidData = [ 1, 2, 3 ];
- test(ajv);
- test(ajvJP);
- test(fullAjv);
- function test(_ajv) {
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData);
- shouldBeError(validate.errors[0], 'additionalItems', '#/additionalItems', '', 'should NOT have more than 2 items');
- }
- });
- describe('"propertyNames" errors', function() {
- it('should add propertyName to errors', function() {
- var schema = {
- type: 'object',
- propertyNames: { format: 'email' }
- };
- var data = {
- 'bar.baz@email.example.com': {}
- };
- var invalidData = {
- 'foo': {},
- 'bar': {},
- 'bar.baz@email.example.com': {}
- };
- test(ajv, 2);
- test(ajvJP, 2);
- test(fullAjv, 4);
- function test(_ajv, numErrors) {
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData, numErrors);
- shouldBeError(validate.errors[0], 'format', '#/propertyNames/format', '', 'should match format "email"');
- shouldBeError(validate.errors[1], 'propertyNames', '#/propertyNames', '', 'property name \'foo\' is invalid');
- if (numErrors == 4) {
- shouldBeError(validate.errors[2], 'format', '#/propertyNames/format', '', 'should match format "email"');
- shouldBeError(validate.errors[3], 'propertyNames', '#/propertyNames', '', 'property name \'bar\' is invalid');
- }
- }
- });
- });
- describe('oneOf errors', function() {
- it('should have errors from inner schemas', function() {
- var schema = {
- oneOf: [
- { type: 'number' },
- { type: 'integer' }
- ]
- };
- test(ajv);
- test(fullAjv);
- function test(_ajv) {
- var validate = _ajv.compile(schema);
- validate('foo') .should.equal(false);
- validate.errors.length .should.equal(3);
- validate(1) .should.equal(false);
- validate.errors.length .should.equal(1);
- validate(1.5) .should.equal(true);
- }
- });
- it('should return passing schemas in error params', function() {
- var schema = {
- oneOf: [
- { type: 'number' },
- { type: 'integer' },
- { const: 1.5 }
- ]
- };
- test(ajv);
- test(fullAjv);
- function test(_ajv) {
- var validate = _ajv.compile(schema);
- validate(1) .should.equal(false);
- var err = validate.errors.pop();
- err.keyword .should.equal('oneOf');
- err.params .should.eql({passingSchemas: [0, 1]});
- validate(1.5) .should.equal(false);
- err = validate.errors.pop();
- err.keyword .should.equal('oneOf');
- err.params .should.eql({passingSchemas: [0, 2]});
- validate(2.5) .should.equal(true);
- validate('foo') .should.equal(false);
- err = validate.errors.pop();
- err.keyword .should.equal('oneOf');
- err.params .should.eql({passingSchemas: null});
- }
- });
- });
- describe('anyOf errors', function() {
- it('should have errors from inner schemas', function() {
- var schema = {
- anyOf: [
- { type: 'number' },
- { type: 'integer' }
- ]
- };
- test(ajv);
- test(fullAjv);
- function test(_ajv) {
- var validate = _ajv.compile(schema);
- validate('foo') .should.equal(false);
- validate.errors.length .should.equal(3);
- validate(1) .should.equal(true);
- validate(1.5) .should.equal(true);
- }
- });
- });
- describe('type errors', function() {
- describe('integer', function() {
- it('should have only one error in {allErrors: false} mode', function() {
- test(ajv);
- });
- it('should return all errors in {allErrors: true} mode', function() {
- test(fullAjv, 2);
- });
- function test(_ajv, numErrors) {
- var schema = {
- type: 'integer',
- minimum: 5
- };
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, 5);
- shouldBeInvalid(validate, 5.5);
- shouldBeInvalid(validate, 4);
- shouldBeInvalid(validate, '4');
- shouldBeInvalid(validate, 4.5, numErrors);
- }
- });
- describe('keyword for another type', function() {
- it('should have only one error in {allErrors: false} mode', function() {
- test(ajv);
- });
- it('should return all errors in {allErrors: true} mode', function() {
- test(fullAjv, 2);
- });
- function test(_ajv, numErrors) {
- var schema = {
- type: 'array',
- minItems: 2,
- minimum: 5
- };
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, [1, 2]);
- shouldBeInvalid(validate, [1]);
- shouldBeInvalid(validate, 5);
- shouldBeInvalid(validate, 4, numErrors);
- }
- });
- describe('array of types', function() {
- it('should have only one error in {allErrors: false} mode', function() {
- test(ajv);
- });
- it('should return all errors in {allErrors: true} mode', function() {
- test(fullAjv, 2);
- });
- function test(_ajv, numErrors) {
- var schema = {
- type: ['array', 'object'],
- minItems: 2,
- minProperties: 2,
- minimum: 5
- };
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, [1, 2]);
- shouldBeValid(validate, {foo: 1, bar: 2});
- shouldBeInvalid(validate, [1]);
- shouldBeInvalid(validate, {foo: 1});
- shouldBeInvalid(validate, 5);
- shouldBeInvalid(validate, 4, numErrors);
- }
- });
- });
- describe('exclusiveMaximum/Minimum errors', function() {
- it('should include limits in error message', function() {
- var schema = {
- type: 'integer',
- exclusiveMinimum: 2,
- exclusiveMaximum: 5
- };
- [ajv, fullAjv].forEach(function (_ajv) {
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, 3);
- shouldBeValid(validate, 4);
- shouldBeInvalid(validate, 2);
- testError('exclusiveMinimum', 'should be > 2', {comparison: '>', limit: 2, exclusive: true});
- shouldBeInvalid(validate, 5);
- testError('exclusiveMaximum', 'should be < 5', {comparison: '<', limit: 5, exclusive: true});
- function testError(keyword, message, params) {
- var err = validate.errors[0];
- shouldBeError(err, keyword, '#/' + keyword, '', message, params);
- }
- });
- });
- it('should include limits in error message with $data', function() {
- var schema = {
- "properties": {
- "smaller": {
- "type": "number",
- "exclusiveMaximum": { "$data": "1/larger" }
- },
- "larger": { "type": "number" }
- }
- };
- ajv = new Ajv({$data: true});
- fullAjv = new Ajv({$data: true, allErrors: true, verbose: true, jsonPointers: true});
- [ajv, fullAjv].forEach(function (_ajv) {
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, {smaller: 2, larger: 4});
- shouldBeValid(validate, {smaller: 3, larger: 4});
- shouldBeInvalid(validate, {smaller: 4, larger: 4});
- testError();
- shouldBeInvalid(validate, {smaller: 5, larger: 4});
- testError();
- function testError() {
- var err = validate.errors[0];
- shouldBeError(err, 'exclusiveMaximum',
- '#/properties/smaller/exclusiveMaximum',
- _ajv._opts.jsonPointers ? '/smaller' : '.smaller',
- 'should be < 4',
- {comparison: '<', limit: 4, exclusive: true});
- }
- });
- });
- });
- describe('if/then/else errors', function() {
- var validate, numErrors;
- it('if/then/else should include failing keyword in message and params', function() {
- var schema = {
- 'if': { maximum: 10 },
- 'then': { multipleOf: 2 },
- 'else': { multipleOf: 5 }
- };
- [ajv, fullAjv].forEach(function (_ajv) {
- prepareTest(_ajv, schema);
- shouldBeValid(validate, 8);
- shouldBeValid(validate, 15);
- shouldBeInvalid(validate, 7, numErrors);
- testIfError('then', 2);
- shouldBeInvalid(validate, 17, numErrors);
- testIfError('else', 5);
- });
- });
- it('if/then should include failing keyword in message and params', function() {
- var schema = {
- 'if': { maximum: 10 },
- 'then': { multipleOf: 2 }
- };
- [ajv, fullAjv].forEach(function (_ajv) {
- prepareTest(_ajv, schema);
- shouldBeValid(validate, 8);
- shouldBeValid(validate, 11);
- shouldBeValid(validate, 12);
- shouldBeInvalid(validate, 7, numErrors);
- testIfError('then', 2);
- });
- });
- it('if/else should include failing keyword in message and params', function() {
- var schema = {
- 'if': { maximum: 10 },
- 'else': { multipleOf: 5 }
- };
- [ajv, fullAjv].forEach(function (_ajv) {
- prepareTest(_ajv, schema);
- shouldBeValid(validate, 7);
- shouldBeValid(validate, 8);
- shouldBeValid(validate, 15);
- shouldBeInvalid(validate, 17, numErrors);
- testIfError('else', 5);
- });
- });
- function prepareTest(_ajv, schema) {
- validate = _ajv.compile(schema);
- numErrors = _ajv._opts.allErrors ? 2 : 1;
- }
- function testIfError(ifClause, multipleOf) {
- var err = validate.errors[0];
- shouldBeError(err, 'multipleOf', '#/' + ifClause + '/multipleOf', '',
- 'should be multiple of ' + multipleOf, {multipleOf: multipleOf});
- if (numErrors == 2) {
- err = validate.errors[1];
- shouldBeError(err, 'if', '#/if', '',
- 'should match "' + ifClause + '" schema', {failingKeyword: ifClause});
- }
- }
- });
- describe('uniqueItems errors', function() {
- it('should not return uniqueItems error when non-unique items are of a different type than required', function() {
- var schema = {
- items: {type: 'number'},
- uniqueItems: true
- };
- [ajvJP, fullAjv].forEach(function (_ajv) {
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, [1, 2, 3]);
- shouldBeInvalid(validate, [1, 2, 2]);
- shouldBeError(validate.errors[0], 'uniqueItems', '#/uniqueItems', '',
- 'should NOT have duplicate items (items ## 2 and 1 are identical)',
- {i: 1, j: 2});
- var expectedErrors = _ajv._opts.allErrors ? 2 : 1;
- shouldBeInvalid(validate, [1, "2", "2", 2], expectedErrors);
- testTypeError(0, '/1');
- if (expectedErrors == 2) testTypeError(1, '/2');
- function testTypeError(i, dataPath) {
- var err = validate.errors[i];
- shouldBeError(err, 'type', '#/items/type', dataPath, 'should be number');
- }
- });
- });
- });
- function testSchema1(schema, schemaPathPrefix) {
- _testSchema1(ajv, schema, schemaPathPrefix);
- _testSchema1(ajvJP, schema, schemaPathPrefix);
- _testSchema1(fullAjv, schema, schemaPathPrefix);
- }
- function _testSchema1(_ajv, schema, schemaPathPrefix) {
- var schPath = (schemaPathPrefix || '#/properties/foo') + '/type';
- var data = { foo: 1 }
- , invalidData = { foo: 'bar' };
- var validate = _ajv.compile(schema);
- shouldBeValid(validate, data);
- shouldBeInvalid(validate, invalidData);
- shouldBeError(validate.errors[0], 'type', schPath, _ajv._opts.jsonPointers ? '/foo' : '.foo');
- }
- function shouldBeValid(validate, data) {
- validate(data) .should.equal(true);
- should.equal(validate.errors, null);
- }
- function shouldBeInvalid(validate, data, numErrors) {
- validate(data) .should.equal(false);
- should.equal(validate.errors.length, numErrors || 1);
- }
- function shouldBeError(error, keyword, schemaPath, dataPath, message, params) {
- error.keyword .should.equal(keyword);
- error.schemaPath .should.equal(schemaPath);
- error.dataPath .should.equal(dataPath);
- error.message .should.be.a('string');
- if (message !== undefined) error.message .should.equal(message);
- if (params !== undefined) error.params .should.eql(params);
- }
- });
|