Permalink
Browse files

doc fixups, get rid of concept of tests -- they're validations

  • Loading branch information...
1 parent 6af5a21 commit 4694fca6b205ed351c6b743ce6a0ac49e6849a73 @bronson committed Oct 4, 2011
Showing with 70 additions and 61 deletions.
  1. +26 −21 README.md
  2. +39 −39 lib/valid.js
  3. +5 −1 test/valid.test.js
View
@@ -20,16 +20,20 @@ A lightweight, chaining validation library.
var Schema = {
Name: Valid.notBlank(),
- Numbers: Valid.array(Valid.integer()).len(2,5),
- State: /^[A-Z][A-Z]$/,
- Country: "US"
+ Numbers: Valid.array(Valid.integer()).len(2,5), // an array of 2, 3, 4, or 5 integers
+ Address: {
+ State: /^[A-Z][A-Z]$/, // shortcut for Valid.match(/^[A-Z][A-Z]$/)
+ Country: "US"
+ }
};
var data = {
Name: "Jed",
Numbers: [1, 9, 25],
- State: "CA",
- Country: "US"
+ Address: {
+ State: "CA",
+ Country: "US"
+ }
}
Valid.json(Schema).verify(data);
@@ -72,20 +76,21 @@ for JSON validations (see _Errors_ below).
This is probably incomplete.
See [valid.js](https://github.com/bronson/valid/blob/master/lib/valid.js).
-- equal(a[,b...]), notEqual(...), oneOf(arrayOrObject)
-- defined(), undef(), undefined()
-- nil(), null(), notNull()
-- exists(), noexisty() (!)
-- array([test]), len(min,max), empty()
-- boolean(), true(), false()
-- number(), integer(), mod(x[,rem]), even(), odd(), max(n), min(n)
-- string([test]), len(min,max), blank(), notBlank()
-- match(regex[,modifiers]), nomatch(regex[,modifiers])
-- eq(n), lt(n), le(n), ge(n), gt(n), ne(n)
-- nop(), fail([message]), messageFor(test,message), todo([test])
-- and(test[,test...]), or(test[,test...]), not(test,message)
-- json(schema)
-
+- Presence: defined(), undef(), undefined\*(), nil(), null\*(), notNull()
+- Equality: equal(a[,b...]), notEqual(...), oneOf(arrayOrObject), in\*(arrayOrObject)
+- Comparison: eq(n), lt(n), le(n), ge(n), gt(n), ne(n)
+- Numbers: number(), integer(), mod(x[,rem]), even(), odd()
+- Booleans: boolean(), isTrue(), true\*(), isFalse(), false\*()
+- Arrays: array([validationForEachItem]), len(min,max), empty()
+- Strings: string(), len(min,max), blank(), notBlank()
+- Regexps: match(regex[,modifiers]), nomatch(regex[,modifiers])
+- Logic: and(test[,test...]), or(test[,test...]), not(test,message)
+- Utilities: nop(), fail([message]), messageFor(test,message), todo([test])
+- JSON: json(schema)
+
+\*: These are JavaScript keywords. While `Valid.undefined()` will work
+with a lot of interpreters, it won't work everywhere.
+Each keyword validation has a more compatible alternative: Valid.undef(), Valid.nil(), etc.
# Errors
@@ -108,7 +113,7 @@ the value that failed to validate.
# Extending Valid
-To define your own tests, just end the chain with "define()"
+To define your own validations, just end the chain with "define()"
and add it to the root object:
```javascript
@@ -117,7 +122,7 @@ and add it to the root object:
Valid.integer().latitude().verify(20); // success!
```
-You can also add tests that take parameters:
+You can also add validations that take parameters:
```javascript
Valid.mod10 = function(rem) { return this.mod(10,rem) }
View
@@ -25,31 +25,31 @@ Valid.GetChain = function GetChain() {
return this;
};
-// Adds the given test to the current Chain.
-// If data is supplied, it's added to the passed-in test to help introspect when debugging.
-Valid.AddTest = function AddTest(test, data) {
+// Adds the given validation to the current Chain.
+// Data is optional but can help identify the validation when debugging.
+Valid.AddValidation = function AddValidation(test, data) {
var self = this.GetChain();
if(self._queue === undefined) self._queue = [];
if(data) test.data = data;
self._queue.push(test);
return self;
};
-// Supply a function that that returns undefined on success or an error message on failure, produces a full, chainable test.
-// The first arg passed to your your function is the value to test, the rest are the args passed when adding the test.
-// i.e. Valid.t = SimpleTest(fn(){...}); Valid.t(4,2).check(9) would call your function with arguments 9, 4, 2.
-Valid.SimpleTest = function SimpleTest(fn) {
+// Supply a function that that returns undefined on success or an error message on failure, produces a full, chainable validation.
+// The first arg passed to your your function is the value to test, the rest are the args passed when declaring the validation.
+// i.e. Valid.t = SimpleValidation(fn(){...}); Valid.t(4,2).check(9) would call your function with arguments 9, 4, 2.
+Valid.SimpleValidation = function SimpleValidation(fn) {
return function() {
var args = Array.prototype.slice.call(arguments, 0);
- return this.AddTest( function SimpleTest(value) {
+ return this.AddValidation( function SimpleValidation(value) {
return fn.apply(this, [value].concat(args));
}, args);
};
};
-// Run all the tests in the given queue
+// Run all the validations in the given queue
Valid.ValidateQueue = function ValidateQueue(queue, value) {
- if(!queue || queue.length < 1) return "no tests!";
+ if(!queue || queue.length < 1) return "no validations!";
for(var i=0; i<queue.length; i++) {
var error = queue[i].call(this, value);
if(error === Valid) return; // indicates early success, used by optional()
@@ -64,8 +64,8 @@ Valid.Escape = function Escape(value) {
};
-// Allows you to reuse a chain as as a chainable test:
-// Valid.isFour = Valid.equal(4).define(); // define the isFour test
+// Turns a Chain object into a callable Validation.
+// Valid.isFour = Valid.equal(4).define(); // define the isFour validation
// Valid.integer().isFour().test(4); // success!
// If you get this error then you forgot to call define() on your chain:
// Property 'myfunc' of object function Valid() { } is not a function
@@ -81,7 +81,7 @@ Valid.define = function define() {
return function() {
var self = this.GetChain();
for(var i=0; i<queue.length; i++) {
- self.AddTest(queue[i]);
+ self.AddValidation(queue[i]);
}
return self;
};
@@ -114,16 +114,16 @@ Valid.verify = function assert(value) {
};
-// core tests
+// core validations
-Valid.nop = Valid.SimpleTest(function Nop(val) { });
-Valid.fail = Valid.SimpleTest(function Fail(val,msg) { return msg || "failed"; });
-Valid.mod = Valid.SimpleTest(function mod(val,by,rem) { if(val%by !== (rem||0)) return "mod "+by+" is "+(val%by)+" not "+rem; });
-Valid.optional = Valid.SimpleTest(function Optional(value) { if(value === null || value === undefined) return Valid; });
+Valid.nop = Valid.SimpleValidation(function Nop(val) { });
+Valid.fail = Valid.SimpleValidation(function Fail(val,msg) { return msg || "failed"; });
+Valid.mod = Valid.SimpleValidation(function mod(val,by,rem) { if(val%by !== (rem||0)) return "mod "+by+" is "+(val%by)+" not "+rem; });
+Valid.optional = Valid.SimpleValidation(function Optional(value) { if(value === null || value === undefined) return Valid; });
-Valid.equal = Valid.SimpleTest(function Equal(value) {
+Valid.equal = Valid.SimpleValidation(function Equal(value) {
// Here is the old equal, not sure supporting multiple values is worth the additional complexity...
- // Valid.equal = Valid.SimpleTest(function Equal(val,want) { if(val !== want) return "is not equal to "+Valid.Escape(want); });
+ // Valid.equal = Valid.SimpleValidation(function Equal(val,want) { if(val !== want) return "is not equal to "+Valid.Escape(want); });
if(arguments.length === 1) return "equal needs at least one argument";
var opts = [];
for(var i=1; i<arguments.length; i++) {
@@ -135,18 +135,18 @@ Valid.equal = Valid.SimpleTest(function Equal(value) {
return "is not " + opts.join(", ") + " or " + lastopt;
});
-Valid.oneOf = Valid.SimpleTest(function OneOf(value,collection) {
+Valid.oneOf = Valid.SimpleValidation(function OneOf(value,collection) {
if(collection === null || collection === undefined) return "oneOf needs a collection";
if(value in collection) return;
return "is not one of the options";
});
-Valid.type = Valid.SimpleTest(function Type(value,type) {
+Valid.type = Valid.SimpleValidation(function Type(value,type) {
if(typeof type !== 'string') return "type requires a string argument, not "+(typeof type);
if(typeof value !== type) return "is of type " + (typeof value) + " not " + type;
});
-Valid.array = Valid.SimpleTest(function Arry(value, test) {
+Valid.array = Valid.SimpleValidation(function Arry(value, test) {
if(!Array.isArray(value)) return "is not an array";
if(test !== undefined) {
for(var i=0; i<value.length; i++) {
@@ -156,7 +156,7 @@ Valid.array = Valid.SimpleTest(function Arry(value, test) {
}
});
-Valid.len = Valid.SimpleTest(function Len(value,min,max) {
+Valid.len = Valid.SimpleValidation(function Len(value,min,max) {
if(typeof value === 'null' || typeof value === 'undefined' || typeof value.length === 'undefined') return "doesn't have a length field";
if(typeof value.length !== 'number') return "length field is of type " + (typeof value.length) + ", not number";
// now we can read the property without risking throwing an exception
@@ -166,20 +166,20 @@ Valid.len = Valid.SimpleTest(function Len(value,min,max) {
}
});
-Valid.messageFor = Valid.SimpleTest(function Msg(value, test, message) {
+Valid.messageFor = Valid.SimpleValidation(function Msg(value, test, message) {
var error = this.ValidateQueue(test._queue, value);
if(error) return message;
});
-Valid.not = Valid.SimpleTest(function Not(value, test, message) {
+Valid.not = Valid.SimpleValidation(function Not(value, test, message) {
var error = this.ValidateQueue(test._queue, value);
if(!error) return message || "test should have failed";
});
// seems somewhat useless since V.a().b() is the same as V.and(V.a(),V.b())
Valid.and = function and() {
var chains = arguments;
- return this.AddTest( function And(value) {
+ return this.AddValidation( function And(value) {
for(var i=0; i<chains.length; i++) {
var error = this.ValidateQueue(chains[i]._queue, value);
if(error) return error;
@@ -189,7 +189,7 @@ Valid.and = function and() {
Valid.or = function or() {
var chains = arguments;
- return this.AddTest(function Or(value) {
+ return this.AddValidation(function Or(value) {
var errors = [];
for(var i=0; i<chains.length; i++) {
var error = this.ValidateQueue(chains[i]._queue, value);
@@ -202,14 +202,14 @@ Valid.or = function or() {
Valid.match = function match(pattern, modifiers) {
if(typeof pattern !== 'function') pattern = new RegExp(pattern, modifiers);
- return this.string().AddTest( function Match(value) {
+ return this.string().AddValidation( function Match(value) {
if(!value.match(pattern)) return "does not match " + pattern;
}, pattern);
};
-// composite tests
+// composite validations
Valid.undef = Valid.equal(undefined).define();
Valid.defined = Valid.not(Valid.undef(), "is undefined").define();
@@ -219,6 +219,8 @@ Valid.noexisty = Valid.equal(undefined, null).define();
Valid.exists = Valid.not(Valid.noexisty(), "does not exist").define();
Valid.empty = Valid.messageFor(Valid.optional().len(0,0), "is not empty").define();
Valid.boolean = Valid.type('boolean').define();
+Valid.isTrue = Valid.equal(true).define();
+Valid.isFalse = Valid.equal(false).define();
Valid.number = Valid.type('number').define();
Valid.integer = Valid.number().messageFor(Valid.mod(1), "is not an integer").define();
Valid.even = Valid.number().messageFor(Valid.mod(2), "is not even").define();
@@ -230,11 +232,9 @@ Valid.object = Valid.type('object').define();
// reserved words, calling them with dot notation may cause problems with crappy JS implementations
Valid['undefined'] = Valid.undef;
Valid['null'] = Valid.nil;
-Valid['true'] = Valid.equal(true).define();
-Valid['false'] = Valid.equal(false).define();
-Valid['function'] = Valid.type('function').define();
+Valid['true'] = Valid.isTrue;
+Valid['false'] = Valid.isFalse;
Valid['in'] = Valid.oneOf;
-Valid.length = Valid.len;
// composites that take arguments
Valid.todo = function(name) { return this.fail((name ? name : "this") + " is still todo"); };
@@ -244,10 +244,10 @@ Valid.nomatch = function(pat,mods) { var match = this.match(pat,mods); return
// comparisons
Valid.eq = Valid.equal;
Valid.ne = Valid.notEqual;
-Valid.lt = Valid.SimpleTest(function lt(val,than) { if(val >= than) return "is not less than " + Valid.Escape(than); });
-Valid.le = Valid.SimpleTest(function le(val,than) { if(val > than) return "is not less than or equal to " + Valid.Escape(than); });
-Valid.gt = Valid.SimpleTest(function gt(val,than) { if(val <= than) return "is not greater than " + Valid.Escape(than); });
-Valid.ge = Valid.SimpleTest(function ge(val,than) { if(val < than) return "is not greater than or equal to " + Valid.Escape(than); });
+Valid.lt = Valid.SimpleValidation(function lt(val,than) { if(val >= than) return "is not less than " + Valid.Escape(than); });
+Valid.le = Valid.SimpleValidation(function le(val,than) { if(val > than) return "is not less than or equal to " + Valid.Escape(than); });
+Valid.gt = Valid.SimpleValidation(function gt(val,than) { if(val <= than) return "is not greater than " + Valid.Escape(than); });
+Valid.ge = Valid.SimpleValidation(function ge(val,than) { if(val < than) return "is not greater than or equal to " + Valid.Escape(than); });
Valid.min = Valid.ge;
Valid.max = Valid.le;
@@ -337,7 +337,7 @@ Valid.JsonField = function(path, value, schema) {
Valid.json = function json(schema) {
- return this.AddTest(function Json(value, maxErrors) {
+ return this.AddValidation(function Json(value, maxErrors) {
this._errors = {};
this._errorCount = 0;
this._maxErrors = maxErrors || 20;
View
@@ -34,7 +34,7 @@ if(error !== "5 is not equal to 4") throw "verify() failure threw: " + error;
// pathological cases
-Valid.assert("any value", "no tests!");
+Valid.assert("any value", "no validations!");
Valid.nop().assert("any value"); // no-op always succeeds
Valid.fail("die!").assert("anything", "die!"); // fail always fails
@@ -104,6 +104,10 @@ Valid.type(123).assert(123, "type requires a string argument, not number");
Valid.boolean().assert(true);
Valid.boolean().assert(false);
Valid.boolean().assert(undefined, "is of type undefined not boolean");
+Valid.isTrue().assert(true);
+Valid.isTrue().assert(false, "is not equal to true");
+Valid.isFalse().assert(false);
+Valid.isFalse().assert(true, "is not equal to false");
Valid['true']().assert(true);
Valid['true']().assert(false, "is not equal to true");
Valid['false']().assert(false);

0 comments on commit 4694fca

Please sign in to comment.