Skip to content

Commit

Permalink
Merge branch 'alex-ivanov-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Gábor Molnár committed Nov 9, 2014
2 parents 9b95c51 + 83808b7 commit da41958
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 94 deletions.
121 changes: 74 additions & 47 deletions js-schema.debug.js
Expand Up @@ -705,61 +705,88 @@ var ObjectSchema = module.exports = Schema.patterns.ObjectSchema = Schema.extend
})
},

errors: function(instance) {
var self = this
if (instance == null)
return ( instance + ' is not Object' )

var errors = {}
validatePropsFunction: function (intance, properties, validatedFields, collectAllErrors, validation) {
var allErrors = [];
for (var k in properties) {
var check = properties[k];
var numberOfMatches = 0;
for (var instanceKey in intance) {
var value = intance[instanceKey];
if (validation(k, instanceKey, check, value)) {
numberOfMatches++;
validatedFields[instanceKey] = true;
}
}

// Simple string properties
Object.keys(this.stringProps).forEach(function(key) {
var result = self.stringProps[key].value.errors(instance[key])
if (result) {
errors[key] = result
if (numberOfMatches < check.min && !check.value.validate(undefined)) {
allErrors.push(intance + " doesn't match " + check + " check");
if (!collectAllErrors)
return allErrors;
}
})
if (Object.keys(errors).length > 0) {
return errors
}
return false
return allErrors;
},
validate: function(instance) {
var self = this

if (instance == null) return false

// Simple string properties
var stringPropsValid = Object.keys(this.stringProps).every(function(key) {
return (self.stringProps[key].min === 0 && !(key in instance)) ||
(self.stringProps[key].value.validate(instance[key]))
})
if (!stringPropsValid) return false

// If there are no RegExp and other validator, that's all
if (!this.regexpProps.length && this.other === anything) return true

// Regexp and other properties
var checked
for (var key in instance) {

// Checking the key against every key regexps
checked = false
var regexpPropsValid = Object.keys(this.regexpProps).every(function(key) {
return (!self.regexpProps[key].key.test(key) ||
((checked = true) && self.regexpProps[key].value.validate(instance[key]))
)
})
if (!regexpPropsValid) return false
collectErrorsAsObject: function (regexpErrors, stringErrors, missedPropsErrors) {
var allErrors = {};
for (var k in regexpErrors) {
if (regexpErrors.hasOwnProperty(k))
allErrors[k] = regexpErrors[k];
}
for (var k in stringErrors) {
if (stringErrors.hasOwnProperty(k))
allErrors[k] = stringErrors[k];
}
for (var k in missedPropsErrors) {
if (missedPropsErrors.hasOwnProperty([k]))
allErrors[k] = missedPropsErrors[k];
}
return allErrors;
},
errorsList: function(instance, collectAllErrors) {
var self = this;

// If the key is not matched by regexps and by simple string checks
// then check it against this.other
if (!checked && !(key in this.stringProps) && !this.other.validate(instance[key])) return false
if (instance == null)
return ( instance + ' is not Object' );

var validatedFields = {};
for (var k in instance) {
validatedFields[k] = false;
}

// If all checks passed, the instance conforms to the schema
return true
var regexpErrors = self.validatePropsFunction(instance, self.regexpProps, validatedFields, collectAllErrors, function (checkKey, instanceKey, check, value) {
return check.key.test(instanceKey) && check.value.validate(value);
});
//if we should not collect all errors, generate error object right away
if (!collectAllErrors && regexpErrors.length > 0)
return this.collectErrorsAsObject(regexpErrors, [], []);


var stringErrors = self.validatePropsFunction(instance, self.stringProps, validatedFields, collectAllErrors, function (checkKey, instanceKey, check, value) {
return checkKey === instanceKey && check.value.validate(value);
});
//if we should not collect all errors, generate error object right away
if (!collectAllErrors && stringErrors.length > 0)
return this.collectErrorsAsObject([], stringErrors, []);

var missedPropsErrors = {};
for (var k in validatedFields) {
var result = validatedFields[k];
if (!result && !self.other.validate(instance[k])) {
missedPropsErrors[k] = "Property " + k + " doesn't match any of checks";
if (!collectAllErrors)
return missedPropsErrors;
}
}
var allErrors = this.collectErrorsAsObject(regexpErrors, stringErrors, missedPropsErrors);
return Object.keys(allErrors).length == 0 ? false : allErrors;
},
errors: function(instance) {
var self = this;
return self.errorsList(instance, true)
},
validate: function(instance) {
var self = this;
return self.errorsList(instance, false) ? false : true;
},

toJSON: Schema.session(function() {
Expand Down
121 changes: 74 additions & 47 deletions lib/patterns/object.js
Expand Up @@ -20,61 +20,88 @@ var ObjectSchema = module.exports = Schema.patterns.ObjectSchema = Schema.extend
})
},

errors: function(instance) {
var self = this
if (instance == null)
return ( instance + ' is not Object' )

var errors = {}
validatePropsFunction: function (intance, properties, validatedFields, collectAllErrors, validation) {
var allErrors = [];
for (var k in properties) {
var check = properties[k];
var numberOfMatches = 0;
for (var instanceKey in intance) {
var value = intance[instanceKey];
if (validation(k, instanceKey, check, value)) {
numberOfMatches++;
validatedFields[instanceKey] = true;
}
}

// Simple string properties
Object.keys(this.stringProps).forEach(function(key) {
var result = self.stringProps[key].value.errors(instance[key])
if (result) {
errors[key] = result
if (numberOfMatches < check.min && !check.value.validate(undefined)) {
allErrors.push(intance + " doesn't match " + check + " check");
if (!collectAllErrors)
return allErrors;
}
})
if (Object.keys(errors).length > 0) {
return errors
}
return false
return allErrors;
},
validate: function(instance) {
var self = this

if (instance == null) return false

// Simple string properties
var stringPropsValid = Object.keys(this.stringProps).every(function(key) {
return (self.stringProps[key].min === 0 && !(key in instance)) ||
(self.stringProps[key].value.validate(instance[key]))
})
if (!stringPropsValid) return false

// If there are no RegExp and other validator, that's all
if (!this.regexpProps.length && this.other === anything) return true

// Regexp and other properties
var checked
for (var key in instance) {

// Checking the key against every key regexps
checked = false
var regexpPropsValid = Object.keys(this.regexpProps).every(function(key) {
return (!self.regexpProps[key].key.test(key) ||
((checked = true) && self.regexpProps[key].value.validate(instance[key]))
)
})
if (!regexpPropsValid) return false
collectErrorsAsObject: function (regexpErrors, stringErrors, missedPropsErrors) {
var allErrors = {};
for (var k in regexpErrors) {
if (regexpErrors.hasOwnProperty(k))
allErrors[k] = regexpErrors[k];
}
for (var k in stringErrors) {
if (stringErrors.hasOwnProperty(k))
allErrors[k] = stringErrors[k];
}
for (var k in missedPropsErrors) {
if (missedPropsErrors.hasOwnProperty([k]))
allErrors[k] = missedPropsErrors[k];
}
return allErrors;
},
errorsList: function(instance, collectAllErrors) {
var self = this;

// If the key is not matched by regexps and by simple string checks
// then check it against this.other
if (!checked && !(key in this.stringProps) && !this.other.validate(instance[key])) return false
if (instance == null)
return ( instance + ' is not Object' );

var validatedFields = {};
for (var k in instance) {
validatedFields[k] = false;
}

// If all checks passed, the instance conforms to the schema
return true
var regexpErrors = self.validatePropsFunction(instance, self.regexpProps, validatedFields, collectAllErrors, function (checkKey, instanceKey, check, value) {
return check.key.test(instanceKey) && check.value.validate(value);
});
//if we should not collect all errors, generate error object right away
if (!collectAllErrors && regexpErrors.length > 0)
return this.collectErrorsAsObject(regexpErrors, [], []);


var stringErrors = self.validatePropsFunction(instance, self.stringProps, validatedFields, collectAllErrors, function (checkKey, instanceKey, check, value) {
return checkKey === instanceKey && check.value.validate(value);
});
//if we should not collect all errors, generate error object right away
if (!collectAllErrors && stringErrors.length > 0)
return this.collectErrorsAsObject([], stringErrors, []);

var missedPropsErrors = {};
for (var k in validatedFields) {
var result = validatedFields[k];
if (!result && !self.other.validate(instance[k])) {
missedPropsErrors[k] = "Property " + k + " doesn't match any of checks";
if (!collectAllErrors)
return missedPropsErrors;
}
}
var allErrors = this.collectErrorsAsObject(regexpErrors, stringErrors, missedPropsErrors);
return Object.keys(allErrors).length == 0 ? false : allErrors;
},
errors: function(instance) {
var self = this;
return self.errorsList(instance, true)
},
validate: function(instance) {
var self = this;
return self.errorsList(instance, false) ? false : true;
},

toJSON: Schema.session(function() {
Expand Down
68 changes: 68 additions & 0 deletions test/extensions/validate-object.js
@@ -0,0 +1,68 @@
var vows = require('vows')
, assert = require('assert')
, printTestResult = require('../printTestResult.js')
, schema = require('../../index.js')


// Create a Test Suite
vows.describe('Validation Object').addBatch({
'Object': {
"original validate schema has a bug with regexp field validation.": function () {
//object should have at least one String field
var validation = schema({
"+.+" : String
});
var emptyObject = {};
assert(false, validation(emptyObject));

var emptyArray = [];
assert(false, validation(emptyArray));
},
"some fields are valid, all the rest are not": function () {
var validation = schema({
"+check.?" : Number,
"*" : null
});
var correctObject = {
check1 : 1,
check2 : 2
};
assert(true, validation(correctObject));
var incorrectObject = {
check1 : 1,
check2 : 2,
someOther : 3
};
assert(false, validation(incorrectObject));
},
"with allowed other fields": function () {
var anotherValidation = schema({
"+check.?": Number,
"*": Number
});
var o1 = {
check1: 1,
check2: 2
};
var o2 = {
check1: 1,
check2: 2,
someOther: 3
};

assert(true, anotherValidation(o1));
assert(true, anotherValidation(o2));
},
"empty object should be valid sometimes": function () {
var allowAll = schema({
"*": String
});
assert(true, allowAll({}));

var allowSome = schema({
"check": [null, String]
});
assert(true, allowSome({}));
}
}
}).export(module)

0 comments on commit da41958

Please sign in to comment.