diff --git a/lib/validations.js b/lib/validations.js index 3455edf7..41f919b8 100644 --- a/lib/validations.js +++ b/lib/validations.js @@ -287,7 +287,7 @@ function validateLength(attr, conf, err, options) { function validateNumericality(attr, conf, err, options) { if (nullCheck.call(this, attr, conf, err)) return; - if (typeof this[attr] !== 'number') { + if (typeof this[attr] !== 'number' || isNaN(this[attr])) { return err('number'); } if (conf.int && this[attr] !== Math.round(this[attr])) { @@ -633,16 +633,26 @@ var defaultMessages = { uniqueness: 'is not unique', }; +/** + * Checks if attribute is undefined or null. Calls err function with 'blank' or 'null'. + * See defaultMessages. You can affect this behaviour with conf.allowBlank and conf.allowNull. + * @param {String} attr Property name of attribute + * @param {Object} conf conf object for validator + * @param {Function} err + * @return {Boolean} returns true if attribute is null or blank + */ function nullCheck(attr, conf, err) { - if (this[attr] == null) { - if (!conf.allowNull) { - err('null'); + // First determine if attribute is defined + if (typeof this[attr] === 'undefined') { + if (!conf.allowBlank) { + err('blank'); } return true; } else { - if (blank(this[attr])) { - if (!conf.allowBlank) { - err('blank'); + // Now check if attribute is null + if (this[attr] === null) { + if (!conf.allowNull) { + err('null'); } return true; } diff --git a/test/validations.test.js b/test/validations.test.js index daed9985..fd79f613 100644 --- a/test/validations.test.js +++ b/test/validations.test.js @@ -558,7 +558,65 @@ describe('validations', function() { }); describe('numericality', function() { - it('should validate numericality'); + it('passes when given numeric values', function() { + User.validatesNumericalityOf('age'); + var user = new User({age: 10}); + user.isValid().should.be.true(); + }); + + it('fails when given non-numeric values', function() { + User.validatesNumericalityOf('age'); + var user = new User({age: 'notanumber'}); + user.isValid().should.be.false(); + user.errors.should.eql({age: ['is not a number']}); + }); + + it('fails when given undefined values', function() { + User.validatesNumericalityOf('age'); + var u = new User({}); + u.isValid().should.be.false(); + u.errors.should.eql({age: ['is blank']}); + }); + + it('skips undefined values when allowBlank option is true', function() { + User.validatesNumericalityOf('age', {allowBlank: true}); + var user = new User({}); + user.isValid().should.be.true(); + }); + + it('fails when given non-numeric values when allowBlank option is true', function() { + User.validatesNumericalityOf('age', {allowBlank: true}); + var user = new User({age: 'test'}); + user.isValid().should.be.false(); + user.errors.should.eql({age: ['is not a number']}); + + }); + + it('fails when given null values', function() { + User.validatesNumericalityOf('age'); + var user = new User({age: null}); + user.isValid().should.be.false(); + user.errors.should.eql({age: ['is null']}); + }); + + it('passes when given null values when allowNull option is true', function() { + User.validatesNumericalityOf('age', {allowNull: true}); + var user = new User({age: null}); + user.isValid().should.be.true(); + }); + + it('passes when given float values', function() { + User.validatesNumericalityOf('age'); + var user = new User({age: 13.37}); + user.isValid().should.be.true(); + }); + + it('fails when given non-integer values when int option is true', function() { + User.validatesNumericalityOf('age', {int: true}); + var user = new User({age: 13.37}); + user.isValid().should.be.false(); + user.errors.should.eql({age: ['is not an integer']}); + }); }); describe('inclusion', function() {