Allow custom keywords that are not valid JS identifiers
Custom keywords were required to be valid JS identifiers due to the way they were being used in the generated code. This prevented the use of keywords with the `x-` prefix that is required by [swagger](http://swagger.io]. This change fixes that by updating the only place that was using them directly as an identifier to use //brackets// notation rather than //dot// notation. This brings the definition of `$schemaPath` in `definitions.def` in line with the way the rule definition is accessed from `RULES.custom` at the top of `custom.jst`. The validation of the keyword name has been changed to allow any name in this change, but this should be updated to either just remove the test or update it to a new rule before this change is included in the project. Finally, this also updates a number of the tests in `custom.spec.js` to use non-valid identifiers for the names of some of the custom keywords being tested (primarily by adding `x-` to the front of the name). Test Plan: - Run `npm test` and ensure all tests run and passmaster
parent
7613986c29
commit
66db560ca5
|
@ -3,7 +3,7 @@
|
||||||
var $lvl = it.level;
|
var $lvl = it.level;
|
||||||
var $dataLvl = it.dataLevel;
|
var $dataLvl = it.dataLevel;
|
||||||
var $schema = it.schema[$keyword];
|
var $schema = it.schema[$keyword];
|
||||||
var $schemaPath = it.schemaPath + '.' + $keyword;
|
var $schemaPath = it.schemaPath + '[\'' + $keyword + '\']';
|
||||||
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
var $errSchemaPath = it.errSchemaPath + '/' + $keyword;
|
||||||
var $breakOnError = !it.opts.allErrors;
|
var $breakOnError = !it.opts.allErrors;
|
||||||
var $errorKeyword;
|
var $errorKeyword;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var IDENTIFIER = /^[a-z_$][a-z0-9_$]*$/i;
|
var IDENTIFIER = /^.*$/i;
|
||||||
var customRuleCode = require('./dotjs/custom');
|
var customRuleCode = require('./dotjs/custom');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
|
@ -37,7 +37,7 @@ describe('Custom keywords', function () {
|
||||||
metaSchema: { "type": "boolean" }
|
metaSchema: { "type": "boolean" }
|
||||||
});
|
});
|
||||||
|
|
||||||
shouldBeInvalidSchema({ "even": "not_boolean" });
|
shouldBeInvalidSchema({ "x-even": "not_boolean" });
|
||||||
|
|
||||||
function validateEven(schema, data) {
|
function validateEven(schema, data) {
|
||||||
return data % 2 ? !schema : schema;
|
return data % 2 ? !schema : schema;
|
||||||
|
@ -69,9 +69,9 @@ describe('Custom keywords', function () {
|
||||||
"additionalItems": false
|
"additionalItems": false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
shouldBeInvalidSchema({ range: [ "1", 2 ] });
|
shouldBeInvalidSchema({ 'x-range': [ "1", 2 ] });
|
||||||
shouldBeInvalidSchema({ range: {} });
|
shouldBeInvalidSchema({ 'x-range': {} });
|
||||||
shouldBeInvalidSchema({ range: [ 1, 2, 3 ] });
|
shouldBeInvalidSchema({ 'x-range': [ 1, 2, 3 ] });
|
||||||
|
|
||||||
function validateRange(schema, data, parentSchema) {
|
function validateRange(schema, data, parentSchema) {
|
||||||
return parentSchema.exclusiveRange === true
|
return parentSchema.exclusiveRange === true
|
||||||
|
@ -94,7 +94,7 @@ describe('Custom keywords', function () {
|
||||||
var valid = minOk && maxOk;
|
var valid = minOk && maxOk;
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
var err = { keyword: 'range' };
|
var err = { keyword: 'x-range' };
|
||||||
validateRange.errors = [err];
|
validateRange.errors = [err];
|
||||||
var comparison, limit;
|
var comparison, limit;
|
||||||
if (minOk) {
|
if (minOk) {
|
||||||
|
@ -121,7 +121,7 @@ describe('Custom keywords', function () {
|
||||||
describe('rule with "compiled" keyword validation', function() {
|
describe('rule with "compiled" keyword validation', function() {
|
||||||
it('should add and validate rule', function() {
|
it('should add and validate rule', function() {
|
||||||
testEvenKeyword({ type: 'number', compile: compileEven });
|
testEvenKeyword({ type: 'number', compile: compileEven });
|
||||||
shouldBeInvalidSchema({ "even": "not_boolean" });
|
shouldBeInvalidSchema({ "x-even": "not_boolean" });
|
||||||
|
|
||||||
function compileEven(schema) {
|
function compileEven(schema) {
|
||||||
if (typeof schema != 'boolean') throw new Error('The value of "even" keyword must be boolean');
|
if (typeof schema != 'boolean') throw new Error('The value of "even" keyword must be boolean');
|
||||||
|
@ -138,7 +138,7 @@ describe('Custom keywords', function () {
|
||||||
compile: compileEven,
|
compile: compileEven,
|
||||||
metaSchema: { "type": "boolean" }
|
metaSchema: { "type": "boolean" }
|
||||||
});
|
});
|
||||||
shouldBeInvalidSchema({ "even": "not_boolean" });
|
shouldBeInvalidSchema({ "x-even": "not_boolean" });
|
||||||
|
|
||||||
function compileEven(schema) {
|
function compileEven(schema) {
|
||||||
return schema ? isEven : isOdd;
|
return schema ? isEven : isOdd;
|
||||||
|
@ -565,7 +565,7 @@ describe('Custom keywords', function () {
|
||||||
metaSchema: { "type": "boolean" }
|
metaSchema: { "type": "boolean" }
|
||||||
});
|
});
|
||||||
compileCalled .should.equal(true);
|
compileCalled .should.equal(true);
|
||||||
shouldBeInvalidSchema({ "even": "false" });
|
shouldBeInvalidSchema({ "x-even-$data": "false" });
|
||||||
|
|
||||||
function validateEven(schema, data) {
|
function validateEven(schema, data) {
|
||||||
return data % 2 ? !schema : schema;
|
return data % 2 ? !schema : schema;
|
||||||
|
@ -613,7 +613,7 @@ describe('Custom keywords', function () {
|
||||||
metaSchema: { "type": "boolean" }
|
metaSchema: { "type": "boolean" }
|
||||||
}, 2);
|
}, 2);
|
||||||
macroCalled .should.equal(true);
|
macroCalled .should.equal(true);
|
||||||
shouldBeInvalidSchema({ "even": "false" });
|
shouldBeInvalidSchema({ "x-even-$data": "false" });
|
||||||
|
|
||||||
function validateEven(schema, data) {
|
function validateEven(schema, data) {
|
||||||
return data % 2 ? !schema : schema;
|
return data % 2 ? !schema : schema;
|
||||||
|
@ -658,7 +658,7 @@ describe('Custom keywords', function () {
|
||||||
metaSchema: { "type": "boolean" }
|
metaSchema: { "type": "boolean" }
|
||||||
});
|
});
|
||||||
inlineCalled .should.equal(true);
|
inlineCalled .should.equal(true);
|
||||||
shouldBeInvalidSchema({ "even": "false" });
|
shouldBeInvalidSchema({ "x-even-$data": "false" });
|
||||||
|
|
||||||
function validateEven(schema, data) {
|
function validateEven(schema, data) {
|
||||||
return data % 2 ? !schema : schema;
|
return data % 2 ? !schema : schema;
|
||||||
|
@ -685,8 +685,8 @@ describe('Custom keywords', function () {
|
||||||
|
|
||||||
function testEvenKeyword(definition, numErrors) {
|
function testEvenKeyword(definition, numErrors) {
|
||||||
instances.forEach(function (_ajv) {
|
instances.forEach(function (_ajv) {
|
||||||
_ajv.addKeyword('even', definition);
|
_ajv.addKeyword('x-even', definition);
|
||||||
var schema = { "even": true };
|
var schema = { "x-even": true };
|
||||||
var validate = _ajv.compile(schema);
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
shouldBeValid(validate, 2);
|
shouldBeValid(validate, 2);
|
||||||
|
@ -698,9 +698,9 @@ describe('Custom keywords', function () {
|
||||||
|
|
||||||
function testEvenKeyword$data(definition, numErrors) {
|
function testEvenKeyword$data(definition, numErrors) {
|
||||||
instances.forEach(function (_ajv) {
|
instances.forEach(function (_ajv) {
|
||||||
_ajv.addKeyword('even', definition);
|
_ajv.addKeyword('x-even-$data', definition);
|
||||||
|
|
||||||
var schema = { "even": true };
|
var schema = { "x-even-$data": true };
|
||||||
var validate = _ajv.compile(schema);
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
shouldBeValid(validate, 2);
|
shouldBeValid(validate, 2);
|
||||||
|
@ -710,7 +710,7 @@ describe('Custom keywords', function () {
|
||||||
|
|
||||||
schema = {
|
schema = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"data": { "even": { "$data": "1/evenValue" } },
|
"data": { "x-even-$data": { "$data": "1/evenValue" } },
|
||||||
"evenValue": {}
|
"evenValue": {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -744,15 +744,15 @@ describe('Custom keywords', function () {
|
||||||
|
|
||||||
function testMultipleConstantKeyword(definition, numErrors) {
|
function testMultipleConstantKeyword(definition, numErrors) {
|
||||||
instances.forEach(function (_ajv) {
|
instances.forEach(function (_ajv) {
|
||||||
_ajv.addKeyword('constant', definition);
|
_ajv.addKeyword('x-constant', definition);
|
||||||
|
|
||||||
var schema = {
|
var schema = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": { "constant": 1 },
|
"a": { "x-constant": 1 },
|
||||||
"b": { "constant": 1 }
|
"b": { "x-constant": 1 }
|
||||||
},
|
},
|
||||||
"additionalProperties": { "constant": { "foo": "bar" } },
|
"additionalProperties": { "x-constant": { "foo": "bar" } },
|
||||||
"items": { "constant": { "foo": "bar" } }
|
"items": { "x-constant": { "foo": "bar" } }
|
||||||
};
|
};
|
||||||
var validate = _ajv.compile(schema);
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
|
@ -771,9 +771,9 @@ describe('Custom keywords', function () {
|
||||||
|
|
||||||
function testRangeKeyword(definition, customErrors, numErrors) {
|
function testRangeKeyword(definition, customErrors, numErrors) {
|
||||||
instances.forEach(function (_ajv) {
|
instances.forEach(function (_ajv) {
|
||||||
_ajv.addKeyword('range', definition);
|
_ajv.addKeyword('x-range', definition);
|
||||||
|
|
||||||
var schema = { "range": [2, 4] };
|
var schema = { "x-range": [2, 4] };
|
||||||
var validate = _ajv.compile(schema);
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
shouldBeValid(validate, 2);
|
shouldBeValid(validate, 2);
|
||||||
|
@ -782,14 +782,14 @@ describe('Custom keywords', function () {
|
||||||
shouldBeValid(validate, 'abc');
|
shouldBeValid(validate, 'abc');
|
||||||
|
|
||||||
shouldBeInvalid(validate, 1.99, numErrors);
|
shouldBeInvalid(validate, 1.99, numErrors);
|
||||||
if (customErrors) shouldBeRangeError(validate.errors[0], '', '#/range', '>=', 2);
|
if (customErrors) shouldBeRangeError(validate.errors[0], '', '#/x-range', '>=', 2);
|
||||||
shouldBeInvalid(validate, 4.01, numErrors);
|
shouldBeInvalid(validate, 4.01, numErrors);
|
||||||
if (customErrors) shouldBeRangeError(validate.errors[0], '', '#/range','<=', 4);
|
if (customErrors) shouldBeRangeError(validate.errors[0], '', '#/x-range','<=', 4);
|
||||||
|
|
||||||
schema = {
|
schema = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"foo": {
|
"foo": {
|
||||||
"range": [2, 4],
|
"x-range": [2, 4],
|
||||||
"exclusiveRange": true
|
"exclusiveRange": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -801,23 +801,23 @@ describe('Custom keywords', function () {
|
||||||
shouldBeValid(validate, { foo: 3.99 });
|
shouldBeValid(validate, { foo: 3.99 });
|
||||||
|
|
||||||
shouldBeInvalid(validate, { foo: 2 }, numErrors);
|
shouldBeInvalid(validate, { foo: 2 }, numErrors);
|
||||||
if (customErrors) shouldBeRangeError(validate.errors[0], '.foo', '#/properties/foo/range', '>', 2, true);
|
if (customErrors) shouldBeRangeError(validate.errors[0], '.foo', '#/properties/foo/x-range', '>', 2, true);
|
||||||
shouldBeInvalid(validate, { foo: 4 }, numErrors);
|
shouldBeInvalid(validate, { foo: 4 }, numErrors);
|
||||||
if (customErrors) shouldBeRangeError(validate.errors[0], '.foo', '#/properties/foo/range', '<', 4, true);
|
if (customErrors) shouldBeRangeError(validate.errors[0], '.foo', '#/properties/foo/x-range', '<', 4, true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function testMultipleRangeKeyword(definition, numErrors) {
|
function testMultipleRangeKeyword(definition, numErrors) {
|
||||||
instances.forEach(function (_ajv) {
|
instances.forEach(function (_ajv) {
|
||||||
_ajv.addKeyword('range', definition);
|
_ajv.addKeyword('x-range', definition);
|
||||||
|
|
||||||
var schema = {
|
var schema = {
|
||||||
"properties": {
|
"properties": {
|
||||||
"a": { "range": [2, 4], "exclusiveRange": true },
|
"a": { "x-range": [2, 4], "exclusiveRange": true },
|
||||||
"b": { "range": [2, 4], "exclusiveRange": false }
|
"b": { "x-range": [2, 4], "exclusiveRange": false }
|
||||||
},
|
},
|
||||||
"additionalProperties": { "range": [5, 7] },
|
"additionalProperties": { "x-range": [5, 7] },
|
||||||
"items": { "range": [5, 7] }
|
"items": { "x-range": [5, 7] }
|
||||||
};
|
};
|
||||||
var validate = _ajv.compile(schema);
|
var validate = _ajv.compile(schema);
|
||||||
|
|
||||||
|
@ -836,7 +836,7 @@ describe('Custom keywords', function () {
|
||||||
delete error.schema;
|
delete error.schema;
|
||||||
delete error.data;
|
delete error.data;
|
||||||
error .should.eql({
|
error .should.eql({
|
||||||
keyword: 'range',
|
keyword: 'x-range',
|
||||||
dataPath: dataPath,
|
dataPath: dataPath,
|
||||||
schemaPath: schemaPath,
|
schemaPath: schemaPath,
|
||||||
message: 'should be ' + comparison + ' ' + limit,
|
message: 'should be ' + comparison + ' ' + limit,
|
||||||
|
@ -906,14 +906,14 @@ describe('Custom keywords', function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw if keyword is not a valid identifier', function() {
|
it('should not throw even if keyword is not a valid identifier', function() {
|
||||||
should.not.throw(function() {
|
should.not.throw(function() {
|
||||||
ajv.addKeyword('mykeyword', {
|
ajv.addKeyword('mykeyword', {
|
||||||
validate: function() { return true; }
|
validate: function() { return true; }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
should.throw(function() {
|
should.not.throw(function() {
|
||||||
ajv.addKeyword('my-keyword', {
|
ajv.addKeyword('my-keyword', {
|
||||||
validate: function() { return true; }
|
validate: function() { return true; }
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{
|
{{
|
||||||
var $data = 'data' + (it.dataLevel || '')
|
var $data = 'data' + (it.dataLevel || '')
|
||||||
, $min = it.schema.range[0]
|
, $min = it.schema['x-range'][0]
|
||||||
, $max = it.schema.range[1]
|
, $max = it.schema['x-range'][1]
|
||||||
, $gt = it.schema.exclusiveRange ? '>' : '>='
|
, $gt = it.schema.exclusiveRange ? '>' : '>='
|
||||||
, $lt = it.schema.exclusiveRange ? '<' : '<=';
|
, $lt = it.schema.exclusiveRange ? '<' : '<=';
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{
|
{{
|
||||||
var $data = 'data' + (it.dataLevel || '')
|
var $data = 'data' + (it.dataLevel || '')
|
||||||
, $min = it.schema.range[0]
|
, $min = it.schema['x-range'][0]
|
||||||
, $max = it.schema.range[1]
|
, $max = it.schema['x-range'][1]
|
||||||
, $exclusive = !!it.schema.exclusiveRange
|
, $exclusive = !!it.schema.exclusiveRange
|
||||||
, $gt = $exclusive ? '>' : '>='
|
, $gt = $exclusive ? '>' : '>='
|
||||||
, $lt = $exclusive ? '<' : '<='
|
, $lt = $exclusive ? '<' : '<='
|
||||||
|
@ -16,7 +16,7 @@ if (!valid{{=$lvl}}) {
|
||||||
var {{=$err}};
|
var {{=$err}};
|
||||||
if (minOk{{=$lvl}}) {
|
if (minOk{{=$lvl}}) {
|
||||||
{{=$err}} = {
|
{{=$err}} = {
|
||||||
keyword: 'range',
|
keyword: 'x-range',
|
||||||
message: 'should be {{=$lt}} {{=$max}}',
|
message: 'should be {{=$lt}} {{=$max}}',
|
||||||
params: {
|
params: {
|
||||||
comparison: '{{=$lt}}',
|
comparison: '{{=$lt}}',
|
||||||
|
@ -26,7 +26,7 @@ if (!valid{{=$lvl}}) {
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
{{=$err}} = {
|
{{=$err}} = {
|
||||||
keyword: 'range',
|
keyword: 'x-range',
|
||||||
message: 'should be {{=$gt}} {{=$min}}',
|
message: 'should be {{=$gt}} {{=$min}}',
|
||||||
params: {
|
params: {
|
||||||
comparison: '{{=$gt}}',
|
comparison: '{{=$gt}}',
|
||||||
|
|
Loading…
Reference in New Issue