Skip to content

Commit

Permalink
Merge pull request #62 from offirgolan/number-validator
Browse files Browse the repository at this point in the history
number validator
  • Loading branch information
offirgolan committed Oct 26, 2015
2 parents 938868e + 61eecd6 commit 6818d7f
Show file tree
Hide file tree
Showing 5 changed files with 328 additions and 6 deletions.
12 changes: 6 additions & 6 deletions addon/validators/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ export default Ember.Object.extend({
after: "{description} must be after {after}",
wrongDateFormat: "{description} must be in the format of {format}",
wrongLength: "{description} is the wrong length (should be {is} characters)",
notANumber: "{description} is not a number",
notANumber: "{description} must be a number",
notAnInteger: "{description} must be an integer",
greaterThan: "{description} must be greater than {min}",
greaterThanOrEqualTo: "{description} must be greater than or equal to {min}",
equalTo: "{description} must be equal to {value}",
lessThan: "{description} must be less than {max}",
lessThanOrEqualTo: "{description} must be less than or equal to {max}",
greaterThan: "{description} must be greater than {gt}",
greaterThanOrEqualTo: "{description} must be greater than or equal to {gte}",
equalTo: "{description} must be equal to {is}",
lessThan: "{description} must be less than {lt}",
lessThanOrEqualTo: "{description} must be less than or equal to {lte}",
otherThan: "{description} must be other than {value}",
odd: "{description} must be odd",
even: "{description} must be even",
Expand Down
75 changes: 75 additions & 0 deletions app/validators/number.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/

import Ember from 'ember';
import Base from 'ember-cp-validations/validators/base';

const {
isEmpty
} = Ember;

export default Base.extend({
validate(value, options) {
let numValue = Number(value);
let optionKeys = Object.keys(options);

if (typeof value === 'string' && (isEmpty(value) || !options.allowString)) {
return this.createErrorMessage('notANumber', value, options);
}

if (!this.isNumber(numValue)) {
return this.createErrorMessage('notANumber', value, options);
}

if (options.integer && !this.isInteger(numValue)) {
return this.createErrorMessage('notAnInteger', value, options);
}

for (let i = 0; i < optionKeys.length; i++) {
let type = optionKeys[i];
let m = this._validateType(type, options, numValue);
if (typeof m === 'string') {
return m;
}
}

return true;
},

_validateType(type, options, value) {
let expected = options[type];
let actual = value;

if (type === 'is' && actual !== expected) {
return this.createErrorMessage('equalTo', value, options);
} else if (type === 'lt' && actual >= expected) {
return this.createErrorMessage('lessThan', value, options);
} else if (type === 'lte' && actual > expected) {
return this.createErrorMessage('lessThanOrEqualTo', value, options);
} else if (type === 'gt' && actual <= expected) {
return this.createErrorMessage('greaterThan', value, options);
} else if (type === 'gte' && actual < expected) {
return this.createErrorMessage('greaterThanOrEqualTo', value, options);
} else if (type === 'positive' && actual < 0) {
return this.createErrorMessage('positive', value, options);
} else if (type === 'odd' && actual % 2 === 0) {
return this.createErrorMessage('odd', value, options);
} else if (type === 'even' && actual % 2 !== 0) {
return this.createErrorMessage('even', value, options);
}

return true;
},

/* Use polyfills instead of Number.isNaN or Number.isInteger to support IE & Safari */

isNumber(value) {
return typeof value === "number" && !isNaN(value);
},

isInteger(value) {
return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
}
});
24 changes: 24 additions & 0 deletions docs/docs/validators/number.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
Validates that your attributes have only numeric values.

## Options
* `allowString` (**Boolean**): If true, validator will accept string representation of a number
* `integer` (**Boolean**): Number must be an integer
* `positive` (**Boolean**): Number must be greater than 0
* `odd` (**Boolean**): Number must be odd
* `even` (**Boolean**): Number must be even
* `is` (**Number**): Number must be equal to this value
* `lt` (**Number**): Number must be less than this value
* `lte` (**Number**): Number must be less than or equal to this value
* `gt` (**Number**): Number must be greater than this value
* `gte` (**Number**): Number must be greater than or equal to this value

```javascript
// Examples
validator('number') // Simple check if the value is a number
validator('number', {
allowString: true,
integer: true,
gt: 5,
lte: 100
})
```
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pages:
- 'Inclusion': 'validators/inclusion.md'
- 'Exclusion': 'validators/exclusion.md'
- 'Length': 'validators/length.md'
- 'Number': 'validators/number.md'
- 'Date': 'validators/date.md'
- 'Format': 'validators/format.md'
- 'Dependent': 'validators/dependent.md'
Expand Down
222 changes: 222 additions & 0 deletions tests/unit/validators/number-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/**
* Copyright 2015, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/

import Ember from 'ember';
import {
moduleFor, test
}
from 'ember-qunit';

var options, validator, message;
var set = Ember.set;

moduleFor('validator:number', 'Unit | Validator | number', {
needs: ['validator:messages'],
setup: function() {
validator = this.subject();
}
});

test('no options', function(assert) {
assert.expect(2);

message = validator.validate(undefined, {});
assert.equal(message, 'This field must be a number');

message = validator.validate(22, {});
assert.equal(message, true);
});

test('allow string', function(assert) {
assert.expect(6);

options = {
allowString: true
};

message = validator.validate('22', options);
assert.equal(message, true);

message = validator.validate('22.22', options);
assert.equal(message, true);

message = validator.validate('test', options);
assert.equal(message, 'This field must be a number');

message = validator.validate('', options);
assert.equal(message, 'This field must be a number');

options.allowString = false;

message = validator.validate('22', options);
assert.equal(message, 'This field must be a number');

message = validator.validate('22.22', options);
assert.equal(message, 'This field must be a number');


});

test('integer', function(assert) {
assert.expect(3);

options = {
integer: true
};

message = validator.validate(22, options);
assert.equal(message, true);

message = validator.validate(22.22, options);
assert.equal(message, 'This field must be an integer');

message = validator.validate(-2.2, options);
assert.equal(message, 'This field must be an integer');
});

test('is', function(assert) {
assert.expect(2);

options = {
is: 22
};

message = validator.validate(1, options);
assert.equal(message, 'This field must be equal to 22');

message = validator.validate(22, options);
assert.equal(message, true);
});

test('lt', function(assert) {
assert.expect(3);

options = {
lt: 22
};

message = validator.validate(21, options);
assert.equal(message, true);

message = validator.validate(22, options);
assert.equal(message, 'This field must be less than 22');

message = validator.validate(23, options);
assert.equal(message, 'This field must be less than 22');
});

test('lte', function(assert) {
assert.expect(3);

options = {
lte: 22
};

message = validator.validate(21, options);
assert.equal(message, true);

message = validator.validate(22, options);
assert.equal(message, true);

message = validator.validate(23, options);
assert.equal(message, 'This field must be less than or equal to 22');
});

test('gt', function(assert) {
assert.expect(3);

options = {
gt: 22
};

message = validator.validate(21, options);
assert.equal(message, 'This field must be greater than 22');

message = validator.validate(22, options);
assert.equal(message, 'This field must be greater than 22');

message = validator.validate(23, options);
assert.equal(message, true);
});

test('gte', function(assert) {
assert.expect(3);

options = {
gte: 22
};

message = validator.validate(21, options);
assert.equal(message, 'This field must be greater than or equal to 22');

message = validator.validate(22, options);
assert.equal(message, true);

message = validator.validate(23, options);
assert.equal(message, true);
});

test('positive', function(assert) {
assert.expect(4);

options = {
positive: true
};

message = validator.validate(-1, options);
assert.equal(message, 'This field must be positive');

message = validator.validate(-144, options);
assert.equal(message, 'This field must be positive');

message = validator.validate(0, options);
assert.equal(message, true);

message = validator.validate(22, options);
assert.equal(message, true);
});

test('odd', function(assert) {
assert.expect(4);

options = {
odd: true
};

message = validator.validate(22, options);
assert.equal(message, 'This field must be odd');

message = validator.validate(-144, options);
assert.equal(message, 'This field must be odd');

message = validator.validate(21, options);
assert.equal(message, true);

message = validator.validate(-21, options);
assert.equal(message, true);
});

test('even', function(assert) {
assert.expect(5);

options = {
even: true
};

message = validator.validate(22, options);
assert.equal(message, true);

message = validator.validate(-22, options);
assert.equal(message, true);

message = validator.validate(22.22, options);
assert.equal(message, 'This field must be even');

message = validator.validate(21, options);
assert.equal(message, 'This field must be even');

message = validator.validate(-33, options);
assert.equal(message, 'This field must be even');
});

0 comments on commit 6818d7f

Please sign in to comment.