Skip to content

Commit

Permalink
[added] number methods less, more, notEqual
Browse files Browse the repository at this point in the history
  • Loading branch information
A11oW committed Aug 30, 2016
1 parent dab47a9 commit f2a0b75
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 74 deletions.
3 changes: 3 additions & 0 deletions src/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ export let string = {
export let number = {
min: '${path} must be greater than or equal to ${min}',
max: '${path} must be less than or equal to ${max}',
less: '${path} must be less than ${less}',
more: '${path} must be greater than ${more}',
notEqual: '${path} must be not equal to ${notEqual}',
positive: '${path} must be a positive number',
negative: '${path} must be a negative number',
integer: '${path} must be an integer',
Expand Down
185 changes: 111 additions & 74 deletions src/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,86 +9,123 @@ let isNaN = value => value != +value
let isInteger = val => isAbsent(val) || val === (val | 0)

export default function NumberSchema() {
if ( !(this instanceof NumberSchema))
return new NumberSchema()
if ( !(this instanceof NumberSchema))
return new NumberSchema()

MixedSchema.call(this, { type: 'number' })
MixedSchema.call(this, { type: 'number' })

this.withMutation(() => {
this.transform(function(value) {
if (this.isType(value)) return value
this.withMutation(() => {
this.transform(function(value) {
if (this.isType(value)) return value

let parsed = parseFloat(value);
if (this.isType(parsed)) return parsed
let parsed = parseFloat(value);
if (this.isType(parsed)) return parsed

return NaN;
})
})
return NaN;
})
})
}

inherits(NumberSchema, MixedSchema, {

_typeCheck(value) {
if (value instanceof Number)
value = value.valueOf();

return typeof value === 'number' && !isNaN(value)
},

min(min, msg) {
return this.test({
name: 'min',
exclusive: true,
params: { min },
message: msg || locale.min,
test(value) {
return isAbsent(value) || value >= this.resolve(min)
}
})
},

max(max, msg) {
return this.test({
name: 'max',
exclusive: true,
params: { max },
message: msg || locale.max,
test(value) {
return isAbsent(value) || value <= this.resolve(max)
}
})
},

positive(msg) {
return this.min(0, msg || locale.positive)
},

negative(msg) {
return this.max(0, msg || locale.negative)
},

integer(msg) {
msg = msg || locale.integer;

return this.test('integer', msg, isInteger)
},

truncate() {
return this.transform(value =>
!isAbsent(value) ? (value | 0) : value)
},

round(method) {
var avail = ['ceil', 'floor', 'round', 'trunc']
method = (method && method.toLowerCase()) || 'round'

// this exists for symemtry with the new Math.trunc
if (method === 'trunc')
return this.truncate()

if (avail.indexOf(method.toLowerCase()) === -1)
throw new TypeError('Only valid options for round() are: ' + avail.join(', '))

return this.transform(value => !isAbsent(value) ? Math[method](value) : value)
}
_typeCheck(value) {
if (value instanceof Number)
value = value.valueOf();

return typeof value === 'number' && !isNaN(value)
},

min(min, msg) {
return this.test({
name: 'min',
exclusive: true,
params: { min },
message: msg || locale.min,
test(value) {
return isAbsent(value) || value >= this.resolve(min)
}
})
},

max(max, msg) {
return this.test({
name: 'max',
exclusive: true,
params: { max },
message: msg || locale.max,
test(value) {
return isAbsent(value) || value <= this.resolve(max)
}
})
},

less(less, msg) {
return this.test({
name: 'less',
exclusive: true,
params: { less },
message: msg || locale.less,
test(value) {
return isAbsent(value) || value < this.resolve(less)
}
})
},


more(more, msg) {
return this.test({
name: 'more',
exclusive: true,
params: { more },
message: msg || locale.more,
test(value) {
return isAbsent(value) || value > this.resolve(more)
}
})
},

notEqual(notEqual, msg) {
return this.test({
name: 'notEqual',
exclusive: true,
params: { notEqual },
message: msg || locale.notEqual,
test(value) {
return isAbsent(value) || value !== this.resolve(notEqual)
}
})
},

positive(msg) {
return this.min(0, msg || locale.positive)
},

negative(msg) {
return this.max(0, msg || locale.negative)
},

integer(msg) {
msg = msg || locale.integer;

return this.test('integer', msg, isInteger)
},

truncate() {
return this.transform(value =>
!isAbsent(value) ? (value | 0) : value)
},

round(method) {
var avail = ['ceil', 'floor', 'round', 'trunc']
method = (method && method.toLowerCase()) || 'round'

// this exists for symemtry with the new Math.trunc
if (method === 'trunc')
return this.truncate()

if (avail.indexOf(method.toLowerCase()) === -1)
throw new TypeError('Only valid options for round() are: ' + avail.join(', '))

return this.transform(value => !isAbsent(value) ? Math[method](value) : value)
}
})
53 changes: 53 additions & 0 deletions test/number.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,59 @@ describe('Number types', function() {
})
})

describe('less', () => {
var schema = number().less(5);

TestHelpers.validateAll(schema, {
valid: [
4,
-10,
[null, schema.nullable()]
],
invalid: [
5,
7,
null,
[14, schema.less(10).less(14)]
]
})
})

describe('more', () => {
var schema = number().more(5);

TestHelpers.validateAll(schema, {
valid: [
6,
56445435,
[null, schema.nullable()]
],
invalid: [
5,
-10,
null,
[64, schema.more(52).more(74)]
]
})
})

describe('notEqual', () => {
var schema = number().notEqual(5);

TestHelpers.validateAll(schema, {
valid: [
6,
56445435,
[null, schema.nullable()]
],
invalid: [
5,
null,
[52, schema.notEqual(52).notEqual(74)]
]
})
})

describe('integer', ()=> {
TestHelpers.validateAll(
number().integer(),
Expand Down

0 comments on commit f2a0b75

Please sign in to comment.