Skip to content

Commit

Permalink
Implement and assert on multiple types.
Browse files Browse the repository at this point in the history
Such that the `type` rule property may now be an array of type string
identifiers (or function references) and comparison is performed with
logical or.

If the value is not one of the types in the array an error is raised.

Closes #46.
  • Loading branch information
tmpfs committed Sep 17, 2015
1 parent f2e60cb commit 6db76c4
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 4 deletions.
40 changes: 40 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,46 @@ function validate(source, opts, cb) {
rule.type = typeof(source);
}

if(Array.isArray(rule.type)) {
rule.test = function(cb) {
var types = this.rule.type.slice(0)
, i
, type
, length = this.errors.length
, invalid;

for(i = 0;i < types.length;i++) {
type = types[i];
delete this.rule.Type;
if(typeof type === 'function') {
this.rule.Type = type;
}
this.rule.type = type;
this.type();
}

invalid = (this.errors.length - length) === types.length;
// remove raised errors
this.errors = this.errors.slice(0, length);

// all of the type tests failed
if(invalid) {
this.raise(
this.reasons.type,
this.messages.types.multiple,
this.field,
types.map(function(type) {
if(typeof(type) === 'function') {
return type.name || 'function (anonymous)';
}
return type;
}).join(', ')
)
}
cb();
}
}

if(typeof rule === 'function') {
rule.test = rule;
}else if(typeof rule.test !== 'function') {
Expand Down
3 changes: 2 additions & 1 deletion messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ var messages = {
boolean: '%s is not a %s',
integer: '%s is not an %s',
float: '%s is not a %s',
regexp: '%s is not a valid %s'
regexp: '%s is not a valid %s',
multiple: '%s is not one of the allowed types %s'
},
function: {
len: '%s must have exactly %s arguments',
Expand Down
6 changes: 3 additions & 3 deletions plugin/util/type.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ module.exports = function() {
, Type = this.rule.Type
, invalid = false;

if(Array.isArray(id)) {
console.log('compare multiple types with logical or');
// instanceof comparison on `type` as function
}else if(typeof(Type) === 'function') {
if(typeof(Type) === 'function') {
if(!(this.value instanceof Type)) {
this.raise(
this.reasons.instance,
Expand Down Expand Up @@ -48,6 +46,8 @@ module.exports = function() {
}else if(id === 'integer') {
invalid = typeof(this.value) !== 'number'
|| Number(this.value) !== parseInt(this.value);
// TODO: rename method -> function so that it can share the
// TODO: conditional below
}else if(id === 'method') {
invalid = typeof(this.value) !== 'function';
// straight typeof test
Expand Down
32 changes: 32 additions & 0 deletions test/spec/multiple-types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
var expect = require('chai').expect
, Schema = require('../../index');

describe('async-validate:', function() {

function Component(){};

var descriptor = {
prop: {type: [Boolean, 'string', Component, function(){}]},
}

it('should error on invalid type with multiple types array', function(done) {
var schema = new Schema(descriptor);
schema.validate({prop: []}, function(err, res) {
expect(res.errors.length).to.eql(1);
expect(res.errors[0].message).to.eql(
'prop is not one of the allowed types Boolean, '
+ 'string, Component, function (anonymous)');
done();
});
});

it('should validate with multiple types array', function(done) {
var schema = new Schema(descriptor);
schema.validate({prop: 'foo'}, function(err, res) {
expect(err).to.eql(null);
expect(res).to.eql(null);
done();
});
});

});

0 comments on commit 6db76c4

Please sign in to comment.