Skip to content
This repository has been archived by the owner on Dec 19, 2022. It is now read-only.

Proper check for value of min and max #21

Merged
merged 2 commits into from
Mar 19, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
1.0.4 / 2015-03-20
==================

* Bug fix ([#20](https://github.com/TabDigital/strummer/issues/20)): `integer` and `number` matchers fail to catch invalid data when `{min: 0}` or `{max: 0}` is passed as opt.
42 changes: 29 additions & 13 deletions lib/matchers/integer.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
var s = require('../s');
var s = require('../s');
var utils = require('../utils');
var hasValue = utils.hasValue;
var isNumber = utils.isNumber;

var parseIntFromString = function (value) {
if(/^(\-|\+)?([0-9]+)$/.test(value))
Expand All @@ -7,28 +10,41 @@ var parseIntFromString = function (value) {
}

module.exports = function (opts) {
var hasMinValue = false;
var hasMaxValue = false;

if (!opts) opts = {};
if(hasValue(opts)) {
hasMinValue = hasValue(opts.min);
hasMaxValue = hasValue(opts.max);

return s(function(value) {
if(hasMinValue && !isNumber(opts.min)) {
throw new Error('Invalid minimum option: ' + opts.min);
}

if(hasMaxValue && !isNumber(opts.max)) {
throw new Error('Invalid maximum option: ' + opts.max);
}
} else {
opts = {};
}

return s(function(value) {
if (opts.parse) {
value = parseIntFromString(value);
}

if (typeof value !== 'number' || value % 1 !== 0) {
return 'should be an integer';
}
if (opts) {
if (opts.min && opts.max && (value < opts.min || value > opts.max)) {
return 'should be an integer between ' + opts.min + ' and ' + opts.max;
}
if (opts.min && value < opts.min) {
return 'should be an integer >= ' + opts.min;
}
if (opts.max && value > opts.max) {
return 'should be an integer <= ' + opts.max;
}

if (hasMinValue && hasMaxValue && (value < opts.min || value > opts.max)) {
return 'should be an integer between ' + opts.min + ' and ' + opts.max;
}
if (hasMinValue && value < opts.min) {
return 'should be an integer >= ' + opts.min;
}
if (hasMaxValue && value > opts.max) {
return 'should be an integer <= ' + opts.max;
}
});

Expand Down
41 changes: 28 additions & 13 deletions lib/matchers/number.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
var s = require('../s');
var s = require('../s');
var utils = require('../utils');
var hasValue = utils.hasValue;
var isNumber = utils.isNumber;

var parseFloatFromString = function (value) {
if(/^(\-|\+)?([0-9]+(\.[0-9]+)?)$/.test(value))
Expand All @@ -7,11 +10,25 @@ var parseFloatFromString = function (value) {
}

module.exports = function (opts) {
var hasMinValue = false;
var hasMaxValue = false;

if (!opts) opts = {};
if(hasValue(opts)) {
hasMinValue = hasValue(opts.min);
hasMaxValue = hasValue(opts.max);

return s(function(value) {
if(hasMinValue && !isNumber(opts.min)) {
throw new Error('Invalid minimum option: ' + opts.min);
}

if(hasMaxValue && !isNumber(opts.max)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small optimisation but should we do

    if (opts) {
      var hasMinValue = hasValue(opts.min);
      var hasMaxValue = hasValue(opts.max);
      if ( hasMinValue && hasMaxValue && (value < opts.min || value > opts.max)) {
        return 'should be a number between ' + opts.min + ' and ' + opts.max;
      }
      if (hasMinValue && value < opts.min) {
        return 'should be a number >= ' + opts.min;
      }
      if (hasMaxValue && value > opts.max) {
        return 'should be a number <= ' + opts.max;
      }
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nguyenchr Nice optimisation.

throw new Error('Invalid maximum option: ' + opts.max);
}
} else {
opts = {};
}

return s(function(value) {
if (opts.parse) {
value = parseFloatFromString(value);
}
Expand All @@ -20,16 +37,14 @@ module.exports = function (opts) {
return 'should be a number';
}

if (opts) {
if (opts.min && opts.max && (value < opts.min || value > opts.max)) {
return 'should be a number between ' + opts.min + ' and ' + opts.max;
}
if (opts.min && value < opts.min) {
return 'should be a number >= ' + opts.min;
}
if (opts.max && value > opts.max) {
return 'should be a number <= ' + opts.max;
}
if (hasMinValue && hasMaxValue && (value < opts.min || value > opts.max)) {
return 'should be a number between ' + opts.min + ' and ' + opts.max;
}
if (hasMinValue && value < opts.min) {
return 'should be a number >= ' + opts.min;
}
if (hasMaxValue && value > opts.max) {
return 'should be a number <= ' + opts.max;
}
});

Expand Down
12 changes: 12 additions & 0 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var hasValue = function(val){
return (typeof val !== 'undefined') && (val !== null);
}

var isNumber = function(val){
return typeof val === 'number';
}

module.exports = {
hasValue: hasValue,
isNumber: isNumber
}
17 changes: 17 additions & 0 deletions test/matchers/integer.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@ describe('integer matcher', function() {
integer({min: 3})('', 0).should.have.error(/should be an integer >= 3/);
integer({max: 3})('', 5).should.have.error(/should be an integer <= 3/);
integer({min: 3, max: 5})('', 7).should.have.error(/should be an integer between 3 and 5/);
integer({min: 0})('', -10).should.have.error(/should be an integer >= 0/);
integer({max: 0})('', 3).should.have.error(/should be an integer <= 0/);
});

it('fails for invalid min or max values', function(){
var shouldFail = function(val) {
(function(){
integer({min: val});
}).should.throw('Invalid minimum option: ' + val);

(function(){
integer({max: val});
}).should.throw('Invalid maximum option: ' + val);
}

var invalidValues = ['a', '', {}, []];
invalidValues.forEach(shouldFail);
});

it('can parse integer from string', function() {
Expand Down
17 changes: 17 additions & 0 deletions test/matchers/number.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,27 @@ describe('number matcher', function() {

it('supports min and max', function() {
number({min: 3})('', 0).should.have.error(/should be a number >= 3/);
number({min: 0})('', -10).should.have.error(/should be a number >= 0/);
number({max: 0})('', 12).should.have.error(/should be a number <= 0/);
number({max: 3})('', 5).should.have.error(/should be a number <= 3/);
number({min: 3, max: 5})('', 7).should.have.error(/should be a number between 3 and 5/);
});

it('fails for invalid min or max values', function(){
var shouldFail = function(val) {
(function(){
number({min: val});
}).should.throw('Invalid minimum option: ' + val);

(function(){
number({max: val});
}).should.throw('Invalid maximum option: ' + val);
}

var invalidValues = ['a', '', {}, []];
invalidValues.forEach(shouldFail);
});

it('can parse string into number', function() {
number({parse: true})('', 0).should.not.have.error();
number({parse: true})('', 3).should.not.have.error();
Expand Down
28 changes: 28 additions & 0 deletions test/util.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
var utils = require('../lib/utils');
var hasValue = utils.hasValue;

describe("hasValue() util function", function(){
it('Should return false when value is <null>', function(){
hasValue(null).should.be.false;
});

it('Should return false when value is <undefined>', function(){
hasValue(undefined).should.be.false;
});

it('Should return true when value is a number', function(){
hasValue(12).should.be.true;
});

it('Should return true when value is a string', function(){
hasValue('a').should.be.true;
});

it('Should return true when value is <{}>', function(){
hasValue({}).should.be.true;
});

it('Should return true when value is <"">', function(){
hasValue('').should.be.true;
});
});