Skip to content
Browse files

Adds initial validations (lists)

Adds initial test framework
  • Loading branch information...
1 parent 2250c95 commit 54b0157f4ee2c3883c721a30d07d74dbe173d8ef @dresende committed Jul 23, 2013
Showing with 363 additions and 1 deletion.
  1. +5 −0 .travis.yml
  2. +4 −0 Makefile
  3. +10 −0 Readme.md
  4. +3 −0 index.js
  5. +69 −0 lib/Enforce.js
  6. +21 −0 lib/enforcements/lists.js
  7. +1 −1 package.json
  8. +9 −0 test/common.js
  9. +139 −0 test/integration/enforce.js
  10. +80 −0 test/integration/lists.js
  11. +22 −0 test/run.js
View
5 .travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - '0.6'
+ - '0.8'
+ - '0.10'
View
4 Makefile
@@ -0,0 +1,4 @@
+test:
+ node test/run
+
+.PHONY: test
View
10 Readme.md
@@ -1,3 +1,13 @@
## Data Validations
This will be the package responsible for data validations in [ORM](http://dresende.github.io/node-orm2).
+
+### Validators
+
+#### `enforce.lists.inside(Array[, msg = "outside-list" ])`
+
+Checks if the property is inside a list of items (the `Array`).
+
+#### `enforce.lists.outside(Array[, msg = "inside-list" ])`
+
+Checks if the property is not inside a list of items (the `Array`).
View
3 index.js
@@ -0,0 +1,3 @@
+exports.lists = require("./lib/enforcements/lists");
+
+exports.Enforce = require("./lib/Enforce").Enforce;
View
69 lib/Enforce.js
@@ -0,0 +1,69 @@
+var _ = require("lodash");
+
+exports.Enforce = Enforce;
+
+function Enforce(opts) {
+ this.validations = {};
+ this.options = _.extend({
+ returnAllErrors : false
+ }, opts || {});
+}
+
+Enforce.prototype.add = function (property, validator) {
+ if (typeof validator != "function") {
+ throw new Error("Missing validator (function) in Enforce.add(property, validator)");
+ }
+
+ if (!this.validations.hasOwnProperty(property)) {
+ this.validations[property] = [];
+ }
+ this.validations[property].push(validator);
+
+ return this;
+};
+
+Enforce.prototype.clear = function () {
+ this.validations = {};
+};
+
+Enforce.prototype.check = function (data, cb) {
+ var validations = [];
+ var errors = [];
+ var next = function () {
+ if (validations.length === 0) {
+ return cb(errors.length > 0 ? errors : null);
+ }
+
+ var validation = validations.shift();
+
+ validation.validator(data[validation.property], function (msg) {
+ if (msg) {
+ var err = new Error(msg);
+
+ err.property = validation.property;
+ err.value = data[validation.property];
+ err.msg = msg;
+ err.type = "validation";
+
+ if (!this.options.returnAllErrors) {
+ return cb(err);
+ }
+
+ errors.push(err);
+ }
+
+ return next();
+ }.bind(this));
+ }.bind(this);
+
+ for (var k in this.validations) {
+ for (var i = 0; i < this.validations[k].length; i++) {
+ validations.push({
+ property : k,
+ validator : this.validations[k][i]
+ });
+ }
+ }
+
+ return next();
+};
View
21 lib/enforcements/lists.js
@@ -0,0 +1,21 @@
+/**
+ * Check if a value (number or string) is
+ * in a list of values.
+ **/
+exports.inside = function (list, msg) {
+ return function (v, next) {
+ if (list.indexOf(v) >= 0) return next();
+ return next(msg || 'outside-list');
+ };
+};
+
+/**
+ * Check if a value (number or string) is
+ * not in a list of values.
+ **/
+exports.outside = function (list, msg) {
+ return function (v, next) {
+ if (list.indexOf(v) == -1) return next();
+ return next(msg || 'inside-list');
+ };
+};
View
2 package.json
@@ -13,7 +13,7 @@
"scripts" : {
"test" : "make"
},
- "main" : "./lib/Enforce",
+ "main" : "./index",
"engines" : {
"node" : "*"
},
View
9 test/common.js
@@ -0,0 +1,9 @@
+var should = require("should");
+
+exports.checkValidation = function (done, validation_err) {
+ return function (err) {
+ should.equal(err, validation_err);
+
+ return done();
+ };
+};
View
139 test/integration/enforce.js
@@ -0,0 +1,139 @@
+var should = require("should");
+var common = require("../common");
+var enforce = require("../..");
+
+describe("enforce.Enforce", function () {
+ it("should be a function", function (done) {
+ enforce.Enforce.should.be.a("function");
+
+ return done();
+ });
+ it("should create an object with .add() and .check()", function (done) {
+ var checks = new enforce.Enforce();
+
+ checks.add.should.be.a("function");
+ checks.check.should.be.a("function");
+
+ return done();
+ });
+ it("should accept options as first argument", function (done) {
+ var checks = new enforce.Enforce({
+ myOption : 123
+ });
+
+ checks.options.myOption.should.equal(123);
+
+ return done();
+ });
+});
+
+describe("new enforce.Enforce()", function () {
+ describe(".add", function () {
+ var checks = new enforce.Enforce();
+
+ it("should throw if not passing a validator", function (done) {
+ (function () {
+ checks.add("prop");
+ }).should.throwError();
+
+ (function () {
+ checks.add("prop", "validator");
+ }).should.throwError();
+
+ (function () {
+ checks.add("prop", function () {});
+ }).should.not.throwError();
+
+ return done();
+ });
+ });
+
+ describe(".clear", function () {
+ var checks = new enforce.Enforce();
+ checks.add("prop", function () {});
+
+ it("should clear all validators", function (done) {
+ Object.keys(checks.validations).length.should.be.above(0);
+
+ checks.clear();
+
+ Object.keys(checks.validations).length.should.equal(0);
+
+ return done();
+ });
+ });
+
+ describe(".check (default options)", function () {
+ it("should return no error if it's ok", function (done) {
+ var checks = new enforce.Enforce();
+
+ checks.add("prop", enforce.lists.inside([ 1, 2, 3 ]));
+ checks.add("prop", enforce.lists.inside([ 3, 4, 5 ]));
+
+ checks.check({
+ prop : 3
+ }, function (err) {
+ should.not.exist(err);
+
+ return done();
+ });
+ });
+
+ it("should return after first error", function (done) {
+ var checks = new enforce.Enforce();
+
+ checks.add("prop", enforce.lists.inside([ 1, 2, 3 ], "first-error"));
+ checks.add("prop", enforce.lists.inside([ 3, 4, 5 ], "last-error"));
+
+ checks.check({
+ prop : 6
+ }, function (err) {
+ should.exist(err);
+
+ err.msg.should.equal("first-error");
+
+ return done();
+ });
+ });
+ });
+
+ describe(".check (returnAllErrors = true)", function () {
+ it("should return no error if it's ok", function (done) {
+ var checks = new enforce.Enforce({
+ returnAllErrors : true
+ });
+
+ checks.add("prop", enforce.lists.inside([ 1, 2, 3 ]));
+ checks.add("prop", enforce.lists.inside([ 3, 4, 5 ]));
+
+ checks.check({
+ prop : 3
+ }, function (err) {
+ should.not.exist(err);
+
+ return done();
+ });
+ });
+
+ it("should return after all validations", function (done) {
+ var checks = new enforce.Enforce({
+ returnAllErrors : true
+ });
+
+ checks.add("prop", enforce.lists.inside([ 1, 2, 3 ], "first-error"));
+ checks.add("prop", enforce.lists.inside([ 3, 4, 5 ], "last-error"));
+
+ checks.check({
+ prop : 6
+ }, function (err) {
+ should.exist(err);
+ should(Array.isArray(err));
+
+ err[0].msg.should.equal("first-error");
+ err[1].msg.should.equal("last-error");
+
+ return done();
+ });
+ });
+ });
+});
View
80 test/integration/lists.js
@@ -0,0 +1,80 @@
+var should = require("should");
+var common = require("../common");
+var enforce = require("../..");
+
+describe("enforce.lists", function () {
+ it("should have .inside()", function (done) {
+ enforce.lists.inside.should.be.a("function");
+
+ return done();
+ });
+ it("should have .outside()", function (done) {
+ enforce.lists.outside.should.be.a("function");
+
+ return done();
+ });
+});
+
+describe("enforce.lists.inside([ 1, 2, 3 ])", function () {
+ var validator = enforce.lists.inside([ 1, 2, 3 ]);
+
+ it("should pass 1", function (done) {
+ validator(1, common.checkValidation(done));
+ });
+
+ it("should pass 3", function (done) {
+ validator(3, common.checkValidation(done));
+ });
+
+ it("should not pass -1", function (done) {
+ validator(-1, common.checkValidation(done, 'outside-list'));
+ });
+
+ it("should not pass '1'", function (done) {
+ validator('1', common.checkValidation(done, 'outside-list'));
+ });
+
+ it("should not pass []", function (done) {
+ validator([], common.checkValidation(done, 'outside-list'));
+ });
+
+ describe("width custom error", function () {
+ var validator = enforce.lists.inside([ 1, 2, 3 ], 'custom-error');
+
+ it("should not pass -1 with 'custom-error'", function (done) {
+ validator(-1, common.checkValidation(done, 'custom-error'));
+ });
+ });
+});
+
+describe("enforce.lists.outside([ 1, 2, 3 ])", function () {
+ var validator = enforce.lists.outside([ 1, 2, 3 ]);
+
+ it("should pass 4", function (done) {
+ validator(4, common.checkValidation(done));
+ });
+
+ it("should pass -2", function (done) {
+ validator(-2, common.checkValidation(done));
+ });
+
+ it("should pass ''", function (done) {
+ validator('', common.checkValidation(done));
+ });
+
+ it("should pass null", function (done) {
+ validator(null, common.checkValidation(done));
+ });
+
+ it("should not pass 2", function (done) {
+ validator(2, common.checkValidation(done, 'inside-list'));
+ });
+
+ describe("width custom error", function () {
+ var validator = enforce.lists.outside([ 1, 2, 3 ], 'custom-error');
+
+ it("should not pass 2 with 'custom-error'", function (done) {
+ validator(2, common.checkValidation(done, 'custom-error'));
+ });
+ });
+});
View
22 test/run.js
@@ -0,0 +1,22 @@
+var Mocha = require('mocha');
+var fs = require('fs');
+var path = require('path');
+var location = path.normalize(path.join(__dirname, "integration"));
+var mocha = new Mocha({
+ reporter: "spec"
+});
+
+runTests();
+
+function runTests() {
+ fs.readdirSync(location).filter(function (file) {
+ return file.substr(-3) === '.js';
+ }).forEach(function (file) {
+ mocha.addFile(
+ path.join(location, file)
+ );
+ });
+ mocha.run(function (failures) {
+ process.exit(failures);
+ });
+}

0 comments on commit 54b0157

Please sign in to comment.
Something went wrong with that request. Please try again.