default behaviour in >=2.0.0 (#69) reverts #18 and #55 - now dataPath points to the object that is validated and not to the missing property; old (<=1.4.10 ) error reporting of dataPath for "required" keyword is available with option errorDataPath == "property"
parent
771e79f36b
commit
a46600e14a
|
@ -53,6 +53,9 @@ function Ajv(opts) {
|
|||
addInitialSchemas();
|
||||
if (this.opts.formats) addInitialFormats();
|
||||
|
||||
if (this.opts.errorDataPath == 'property')
|
||||
this.opts._errorDataPathProperty = true;
|
||||
|
||||
|
||||
/**
|
||||
* Validate data using schema
|
||||
|
|
|
@ -161,7 +161,7 @@
|
|||
not: "'should NOT be valid'",
|
||||
oneOf: "'should match exactly one schema in oneOf'",
|
||||
pattern: "'should match pattern \"{{=it.util.escapeQuotes($schema)}}\"'",
|
||||
required: "'is a required property'",
|
||||
required: "'{{? it.opts._errorDataPathProperty }}is a required property{{??}}should have required property {{=$missingProperty}}{{?}}'",
|
||||
type: "'should be {{? $isArray }}{{= $typeSchema.join(\",\") }}{{??}}{{=$typeSchema}}{{?}}'",
|
||||
uniqueItems: "'should NOT have duplicate items (items ## ' + j + ' and ' + i + ' are identical)'",
|
||||
custom: "'should pass \"{{=$rule.keyword}}\" keyword validation'"
|
||||
|
|
|
@ -15,7 +15,9 @@
|
|||
var $i = 'i' + $lvl
|
||||
, $propertyPath = 'schema' + $lvl + '[' + $i + ']'
|
||||
, $missingProperty = '\' + "\'" + ' + $propertyPath + ' + "\'" + \'';
|
||||
it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers);
|
||||
if (it.opts._errorDataPathProperty) {
|
||||
it.errorPath = it.util.getPathExpr($currentErrorPath, $propertyPath, it.opts.jsonPointers);
|
||||
}
|
||||
}}
|
||||
#}}
|
||||
|
||||
|
@ -43,9 +45,11 @@
|
|||
{{
|
||||
var $propertyPath = 'missing' + $lvl
|
||||
, $missingProperty = '\' + ' + $propertyPath + ' + \'';
|
||||
it.errorPath = it.opts.jsonPointers
|
||||
? it.util.getPathExpr($currentErrorPath, $propertyPath, true)
|
||||
: $currentErrorPath + ' + ' + $propertyPath;
|
||||
if (it.opts._errorDataPathProperty) {
|
||||
it.errorPath = it.opts.jsonPointers
|
||||
? it.util.getPathExpr($currentErrorPath, $propertyPath, true)
|
||||
: $currentErrorPath + ' + ' + $propertyPath;
|
||||
}
|
||||
}}
|
||||
{{# def.error:'required' }}
|
||||
} else {
|
||||
|
@ -66,7 +70,9 @@
|
|||
{{
|
||||
var $prop = it.util.getProperty($property)
|
||||
, $missingProperty = it.util.escapeQuotes($prop);
|
||||
it.errorPath = it.util.getPath($currentErrorPath, $property, it.opts.jsonPointers);
|
||||
if (it.opts._errorDataPathProperty) {
|
||||
it.errorPath = it.util.getPath($currentErrorPath, $property, it.opts.jsonPointers);
|
||||
}
|
||||
}}
|
||||
if ({{=$data}}{{=$prop}} === undefined) {
|
||||
{{# def.addError:'required' }}
|
||||
|
|
|
@ -9,11 +9,15 @@ describe('Validation errors', function () {
|
|||
var ajv, ajvJP, fullAjv;
|
||||
|
||||
beforeEach(function() {
|
||||
ajv = Ajv();
|
||||
ajvJP = Ajv({ jsonPointers: true });
|
||||
fullAjv = Ajv({ allErrors: true, jsonPointers: true });
|
||||
createInstances();
|
||||
});
|
||||
|
||||
function createInstances(errorDataPath) {
|
||||
ajv = Ajv({ errorDataPath: errorDataPath });
|
||||
ajvJP = Ajv({ errorDataPath: errorDataPath, jsonPointers: true });
|
||||
fullAjv = Ajv({ errorDataPath: errorDataPath, allErrors: true, jsonPointers: true });
|
||||
}
|
||||
|
||||
it('error should include dataPath', function() {
|
||||
testSchema1({
|
||||
properties: {
|
||||
|
@ -71,7 +75,18 @@ describe('Validation errors', function () {
|
|||
});
|
||||
|
||||
|
||||
it('errors for required should include missing property in dataPath', function() {
|
||||
it('with option errorDataPath="property" errors for required should include missing property in dataPath', function() {
|
||||
createInstances('property');
|
||||
testRequired('property');
|
||||
});
|
||||
|
||||
|
||||
it('without option errorDataPath errors for required should NOT include missing property in dataPath', function() {
|
||||
testRequired();
|
||||
});
|
||||
|
||||
|
||||
function testRequired(errorDataPath) {
|
||||
var schema = {
|
||||
required: ['foo', 'bar', 'baz']
|
||||
};
|
||||
|
@ -83,28 +98,49 @@ describe('Validation errors', function () {
|
|||
var validate = ajv.compile(schema);
|
||||
shouldBeValid(validate, data);
|
||||
shouldBeInvalid(validate, invalidData1);
|
||||
shouldBeError(validate.errors[0], 'required', '.bar', 'is a required property');
|
||||
shouldBeError(validate.errors[0], 'required', path('.bar'), msg('.bar'));
|
||||
shouldBeInvalid(validate, invalidData2);
|
||||
shouldBeError(validate.errors[0], 'required', '.foo', 'is a required property');
|
||||
shouldBeError(validate.errors[0], 'required', path('.foo'), msg('.foo'));
|
||||
|
||||
var validateJP = ajvJP.compile(schema);
|
||||
shouldBeValid(validateJP, data);
|
||||
shouldBeInvalid(validateJP, invalidData1);
|
||||
shouldBeError(validateJP.errors[0], 'required', '/bar', 'is a required property');
|
||||
shouldBeError(validateJP.errors[0], 'required', path('/bar'), msg('bar'));
|
||||
shouldBeInvalid(validateJP, invalidData2);
|
||||
shouldBeError(validateJP.errors[0], 'required', '/foo', 'is a required property');
|
||||
shouldBeError(validateJP.errors[0], 'required', path('/foo'), msg('foo'));
|
||||
|
||||
var fullValidate = fullAjv.compile(schema);
|
||||
shouldBeValid(fullValidate, data);
|
||||
shouldBeInvalid(fullValidate, invalidData1);
|
||||
shouldBeError(fullValidate.errors[0], 'required', '/bar', 'is a required property');
|
||||
shouldBeError(fullValidate.errors[0], 'required', path('/bar'), msg('.bar'));
|
||||
shouldBeInvalid(fullValidate, invalidData2, 2);
|
||||
shouldBeError(fullValidate.errors[0], 'required', '/foo', 'is a required property');
|
||||
shouldBeError(fullValidate.errors[1], 'required', '/baz', 'is a required property');
|
||||
shouldBeError(fullValidate.errors[0], 'required', path('/foo'), msg('.foo'));
|
||||
shouldBeError(fullValidate.errors[1], 'required', path('/baz'), msg('.baz'));
|
||||
|
||||
function path(dataPath) {
|
||||
return errorDataPath == 'property' ? dataPath : '';
|
||||
}
|
||||
|
||||
function msg(prop) {
|
||||
return errorDataPath == 'property'
|
||||
? 'is a required property'
|
||||
: 'should have required property ' + prop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it('required validation and errors for large data/schemas with option errorDataPath="property"', function() {
|
||||
createInstances('property');
|
||||
testRequiredLargeSchema('property');
|
||||
});
|
||||
|
||||
|
||||
it('required validation and errors for large data/schemas', function() {
|
||||
it('required validation and errors for large data/schemas WITHOUT option errorDataPath="property"', function() {
|
||||
testRequiredLargeSchema();
|
||||
});
|
||||
|
||||
|
||||
function testRequiredLargeSchema(errorDataPath) {
|
||||
var schema = { required: [] }
|
||||
, data = {}
|
||||
, invalidData1 = {}
|
||||
|
@ -121,25 +157,35 @@ describe('Validation errors', function () {
|
|||
var validate = ajv.compile(schema);
|
||||
shouldBeValid(validate, data);
|
||||
shouldBeInvalid(validate, invalidData1);
|
||||
shouldBeError(validate.errors[0], 'required', "['1']", "is a required property");
|
||||
shouldBeError(validate.errors[0], 'required', path("['1']"), msg("'1'"));
|
||||
shouldBeInvalid(validate, invalidData2);
|
||||
shouldBeError(validate.errors[0], 'required', "['2']", "is a required property");
|
||||
shouldBeError(validate.errors[0], 'required', path("['2']"), msg("'2'"));
|
||||
|
||||
var validateJP = ajvJP.compile(schema);
|
||||
shouldBeValid(validateJP, data);
|
||||
shouldBeInvalid(validateJP, invalidData1);
|
||||
shouldBeError(validateJP.errors[0], 'required', "/1", "is a required property");
|
||||
shouldBeError(validateJP.errors[0], 'required', path("/1"), msg("'1'"));
|
||||
shouldBeInvalid(validateJP, invalidData2);
|
||||
shouldBeError(validateJP.errors[0], 'required', "/2", "is a required property");
|
||||
shouldBeError(validateJP.errors[0], 'required', path("/2"), msg("'2'"));
|
||||
|
||||
var fullValidate = fullAjv.compile(schema);
|
||||
shouldBeValid(fullValidate, data);
|
||||
shouldBeInvalid(fullValidate, invalidData1);
|
||||
shouldBeError(fullValidate.errors[0], 'required', '/1', "is a required property");
|
||||
shouldBeError(fullValidate.errors[0], 'required', path('/1'), msg("'1'"));
|
||||
shouldBeInvalid(fullValidate, invalidData2, 2);
|
||||
shouldBeError(fullValidate.errors[0], 'required', '/2', "is a required property");
|
||||
shouldBeError(fullValidate.errors[1], 'required', '/98', "is a required property");
|
||||
});
|
||||
shouldBeError(fullValidate.errors[0], 'required', path('/2'), msg("'2'"));
|
||||
shouldBeError(fullValidate.errors[1], 'required', path('/98'), msg("'98'"));
|
||||
|
||||
function path(dataPath) {
|
||||
return errorDataPath == 'property' ? dataPath : '';
|
||||
}
|
||||
|
||||
function msg(prop) {
|
||||
return errorDataPath == 'property'
|
||||
? 'is a required property'
|
||||
: 'should have required property ' + prop;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
it('errors for items should include item index without quotes in dataPath (#48)', function() {
|
||||
|
|
|
@ -12,7 +12,8 @@ var instances = getAjvInstances(fullTest ? {
|
|||
verbose: true,
|
||||
format: 'full',
|
||||
inlineRefs: false,
|
||||
jsonPointers: true
|
||||
jsonPointers: true,
|
||||
errorDataPath: 'property'
|
||||
} : { allErrors: true });
|
||||
|
||||
var remoteRefs = {
|
||||
|
|
Loading…
Reference in New Issue