mirror of
https://github.com/zhigang1992/deployd.git
synced 2026-05-27 14:30:50 +08:00
router rebuild
This commit is contained in:
12
README.md
12
README.md
@@ -23,19 +23,21 @@ realtime bridge
|
||||
- be client agnostic (usable from browser, servers, mobile apps, etc)
|
||||
- be a good web citizen / support native web best practices
|
||||
- be a good node citizen / use node best practices
|
||||
- can be hosted by modern cloud platforms
|
||||
- support extension through node modules and npm
|
||||
- follow the [ways of node](http://www.mikealrogers.com/posts/the-way-of-node.html)
|
||||
- follow the [12 factor methodology](http://www.12factor.net/)
|
||||
|
||||
|
||||
## modules
|
||||
|
||||
**core**
|
||||
|
||||
- resource - base module, mountable at a URL
|
||||
- router - determines a resource based on a URL
|
||||
- collection - allows users to query, save, and delete JSON objects
|
||||
- users collection - allows users to register / login / logout
|
||||
- ??? - allow users to listen and emit events
|
||||
- file system - allows users to upload / download / stream files
|
||||
- router - determines a resource based on a URL
|
||||
- emitter - global message bus / event emitter
|
||||
- sessions - manage authentication of users
|
||||
- resources - internal access to mounted resources
|
||||
@@ -54,6 +56,12 @@ realtime bridge
|
||||
|
||||
Consult the [documentation](http://deployd.github.com/deployd) or contact `ritchie at deployd com`.
|
||||
|
||||
## changelog
|
||||
|
||||
### 0.5
|
||||
|
||||
- removed `property.optional` in favor of `property.required`
|
||||
|
||||
## license
|
||||
|
||||
Copyright 2012 deployd, llc
|
||||
|
||||
12
TODO.md
Normal file
12
TODO.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# high
|
||||
|
||||
# medium
|
||||
|
||||
- dates should be numbers in the database so they can be sorted
|
||||
- dates should be JS date objects in events
|
||||
- dates should be transfered as JSON dates over http
|
||||
|
||||
# low
|
||||
|
||||
- _id should be id
|
||||
|
||||
106
lib/db.js
Normal file
106
lib/db.js
Normal file
@@ -0,0 +1,106 @@
|
||||
var db = module.exports = {}
|
||||
, util = require('util')
|
||||
, EventEmitter = require('events').EventEmitter
|
||||
, mongodb = require('mongodb');
|
||||
|
||||
db.connect = function (options, fn) {
|
||||
var db = new Db(options);
|
||||
db.open(fn);
|
||||
return db;
|
||||
}
|
||||
|
||||
function Db(options) {
|
||||
this.options = options;
|
||||
}
|
||||
util.inherits(Db, EventEmitter);
|
||||
db.Db = Db;
|
||||
|
||||
Db.prototype.createStore = function (namespace) {
|
||||
return new Store(namespace, this);
|
||||
}
|
||||
|
||||
Db.prototype.open = function (fn) {
|
||||
var self = this
|
||||
, mdb = new mongodb.Db(this.options.name, new mongodb.Server(this.options.host, this.options.port));
|
||||
|
||||
self.connecting = true;
|
||||
self._mdb = mdb;
|
||||
mdb.open(function (err) {
|
||||
self.connecting = false;
|
||||
if(err) return fn && fn(err);
|
||||
self.emit('connected');
|
||||
})
|
||||
}
|
||||
|
||||
function Store(namespace, db) {
|
||||
this.namespace = namespace;
|
||||
this._db = db;
|
||||
}
|
||||
|
||||
function collection(store, fn) {
|
||||
var db = store._db
|
||||
, mdb = db._mdb;
|
||||
|
||||
function execute(err) {
|
||||
if(err) return fn(err);
|
||||
|
||||
mdb.collection(store.namespace, function (err, collection) {
|
||||
if(err || !collection) return fn(err || Error('collection was undefined or an error occured'));
|
||||
|
||||
fn(null, collection)
|
||||
});
|
||||
}
|
||||
|
||||
if(db.connecting) {
|
||||
db.once('connected', execute);
|
||||
} else {
|
||||
execute();
|
||||
}
|
||||
};
|
||||
|
||||
Store.prototype.insert = function (object, fn) {
|
||||
collection(this, function (err, col) {
|
||||
col.insert(object, function (err, result) {
|
||||
if(Array.isArray(result) && !Array.isArray(object)) result = result[0];
|
||||
fn(err, result);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Store.prototype.find = function (query, fn) {
|
||||
if(typeof query == 'function') {
|
||||
fn = query;
|
||||
query = {};
|
||||
}
|
||||
collection(this, function (err, col) {
|
||||
col.find(query).toArray(function (err, arr) {
|
||||
if(arr.length === 0) arr = undefined;
|
||||
fn(err, arr);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
Store.prototype.first = function (query, fn) {
|
||||
collection(this, function (err, col) {
|
||||
col.findOne(query, fn);
|
||||
});
|
||||
};
|
||||
|
||||
Store.prototype.update = function (query, object, fn) {
|
||||
collection(this, function (err, col) {
|
||||
col.update(query, object, fn);
|
||||
});
|
||||
};
|
||||
|
||||
Store.prototype.remove = function (query, fn) {
|
||||
collection(this, function (err, col) {
|
||||
col.remove(query, fn);
|
||||
});
|
||||
};
|
||||
|
||||
Store.prototype.rename = function (namespace, fn) {
|
||||
collection(this, function (err, col) {
|
||||
col.rename(namespace, fn);
|
||||
});
|
||||
};
|
||||
|
||||
16
lib/http.js
Normal file
16
lib/http.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var http = require('http')
|
||||
, Router = require('./router')
|
||||
, db = require('./db')
|
||||
, resources = require('./resources');
|
||||
|
||||
function Server(options) {
|
||||
var server = http.createServer(options.host, options.port)
|
||||
, db = db.connect(options.db)
|
||||
, router = new Router(resources.build(db.createStore('resources')));
|
||||
|
||||
server.on('request', router.route);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
function Resource() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Export
|
||||
*/
|
||||
|
||||
module.exports = Resource;
|
||||
44
lib/resources.js
Normal file
44
lib/resources.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
exports.build = function (store) {
|
||||
var definitions = define(__dirname);
|
||||
|
||||
store.find = function (query, fn) {
|
||||
if(typeof query == 'function') {
|
||||
fn = query;
|
||||
query = {};
|
||||
}
|
||||
|
||||
store.__proto__.find.call(store, query, function (err, resources) {
|
||||
if(err) return fn(err);
|
||||
// build resources from data
|
||||
var result = [];
|
||||
if(resources) {
|
||||
resources.forEach(function (resource) {
|
||||
result.push(new definitions[resource.type](resource));
|
||||
})
|
||||
}
|
||||
|
||||
fn(err, result);
|
||||
})
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
function define(dir) {
|
||||
var definitions = {};
|
||||
|
||||
fs.readdirSync(dir + '/resources').forEach(function (path) {
|
||||
if(~path.indexOf('.js')) {
|
||||
var constructor = require(__dirname + '/resources/' + path);
|
||||
definitions[constructor.name] = constructor;
|
||||
}
|
||||
});
|
||||
|
||||
return definitions;
|
||||
}
|
||||
78
lib/resources/collection.js
Normal file
78
lib/resources/collection.js
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var validation = require('validation');
|
||||
|
||||
function Collection(settings, req, res) {
|
||||
this.req = req;
|
||||
this.res = res;
|
||||
this.properties = settings.properties;
|
||||
}
|
||||
|
||||
Collection.prototype.authorize = function () {
|
||||
var req = this.req
|
||||
, query = req.query;
|
||||
|
||||
if(req.user && req.user.root) return;
|
||||
if(!(query && query._id)) {
|
||||
switch(req.method) {
|
||||
case 'PUT':
|
||||
case 'DELETE':
|
||||
return 'An _id must be included when modifying a Collection.';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collection.prototype.validate = function (body) {
|
||||
var keys = Object.keys(this.properties)
|
||||
, props = this.properties
|
||||
, errors = {};
|
||||
|
||||
keys.forEach(function (key) {
|
||||
var prop = props[key]
|
||||
, val = body[key]
|
||||
, type = prop.type || 'string';
|
||||
|
||||
if(validation.exists(val)) {
|
||||
if(!validation.isType(val, type)) {
|
||||
errors[key] = 'must be a ' + type;
|
||||
}
|
||||
} else if(prop.required) {
|
||||
errors[key] = 'is required';
|
||||
}
|
||||
});
|
||||
|
||||
if(Object.keys(errors).length) return errors;
|
||||
}
|
||||
|
||||
Collection.prototype.sanitize = function (body) {
|
||||
var sanitized = {}
|
||||
, props = this.properties
|
||||
, keys = Object.keys(props);
|
||||
|
||||
keys.forEach(function (key) {
|
||||
var prop = props[key]
|
||||
, expected = prop.type
|
||||
, val = body[key]
|
||||
, actual = typeof val;
|
||||
|
||||
// skip properties that dont exist
|
||||
if(!prop) return;
|
||||
|
||||
if(expected == actual) {
|
||||
sanitized[key] = val;
|
||||
} else if(expected == 'number' && actual == 'string') {
|
||||
sanitized[key] = parseInt(val);
|
||||
}
|
||||
});
|
||||
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export
|
||||
*/
|
||||
|
||||
module.exports = Collection;
|
||||
25
lib/router.js
Normal file
25
lib/router.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var db = require('./db');
|
||||
|
||||
function Router(resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
||||
Router.prototype.route = function (req, res) {
|
||||
var router = this;
|
||||
|
||||
this.resources.find(function (err, resources) {
|
||||
var handler;
|
||||
resources.forEach(function (resource) {
|
||||
if(resource.handle(req, res)) {
|
||||
handler = resource;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!handler) res.error('resource not found', 404);
|
||||
});
|
||||
})
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
/**
|
||||
* Validates the given value against the specified type.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @param {string} type
|
||||
* @return {Boolean} true if the validation passes, otherwise false
|
||||
* @api public
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* validation.isType('foobar', 'string')
|
||||
* validation.isType(7, 'number')
|
||||
* validation.isType(true, 'boolean')
|
||||
* validation.isType(new Date().getTime(), 'date')
|
||||
* validation.isType({}, 'object')
|
||||
* validation.isType([], 'array')
|
||||
*
|
||||
*/
|
||||
|
||||
exports.isType = function (value, type) {
|
||||
if(typeof type != 'string') throw Error('bad arguments when calling validation.isValid');
|
||||
|
||||
switch(type) {
|
||||
case 'date':
|
||||
if(!value) return false;
|
||||
try {
|
||||
value = new Date(value);
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return value instanceof Date && isFinite(value);
|
||||
break;
|
||||
case 'object':
|
||||
return !!(value && toString.call(value) === '[object Object]' && 'isPrototypeOf' in value);
|
||||
break;
|
||||
case 'array':
|
||||
return Array.isArray(value);
|
||||
break;
|
||||
case 'number':
|
||||
if(value === Infinity || isNaN(value)) return false;
|
||||
default:
|
||||
return typeof value == type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the given value exists.
|
||||
*
|
||||
* @param {Object} value
|
||||
* @return {Boolean} true if the value exists, otherwise false
|
||||
* @api public
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* validation.exists('foobar') // true
|
||||
* validation.exists(0) // true
|
||||
* validation.exists(null) // false
|
||||
* validation.exists(undefined) // false
|
||||
*
|
||||
*/
|
||||
|
||||
exports.exists = function (value) {
|
||||
return !!(value || value === 0);
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
var Collection = require('../lib/resources/collection');
|
||||
|
||||
describe('collection', function(){
|
||||
describe('.validate(req)', function(){
|
||||
it('should validate the request', function() {
|
||||
var r = new Collection({
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var errs = r.validate({title: 'foobar'});
|
||||
|
||||
expect(errs).to.not.exist;
|
||||
})
|
||||
|
||||
it('should fail to validate the invalid request', function() {
|
||||
var r = new Collection({
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var errs = r.validate({title: 7});
|
||||
|
||||
expect(errs).to.eql({'title': 'must be a string'});
|
||||
})
|
||||
|
||||
it('should fail to validate the invalid request with multiple errors', function() {
|
||||
var r = new Collection({
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
required: true
|
||||
},
|
||||
age: {
|
||||
type: 'number',
|
||||
required: true
|
||||
},
|
||||
created: {
|
||||
type: 'date'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var errs = r.validate({title: 7, created: 'foo'});
|
||||
|
||||
expect(errs).to.eql({title: 'must be a string', age: 'is required', created: 'must be a date'});
|
||||
})
|
||||
})
|
||||
|
||||
describe('.sanitize(body)', function(){
|
||||
it('should remove properties outside the schema', function() {
|
||||
var r = new Collection({
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var sanitized = r.sanitize({foo: 7, bar: 8, title: 'foo'});
|
||||
|
||||
expect(sanitized.foo).to.not.exist;
|
||||
expect(sanitized.bar).to.not.exist;
|
||||
expect(sanitized.title).to.equal('foo');
|
||||
})
|
||||
|
||||
it('should convert int strings to numbers', function() {
|
||||
var r = new Collection({
|
||||
properties: {
|
||||
age: {
|
||||
type: 'number'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var sanitized = r.sanitize({age: '22'});
|
||||
expect(sanitized.age).to.equal(22);
|
||||
})
|
||||
})
|
||||
|
||||
describe('.authorize()', function(){
|
||||
it('should allow users to GET Collections', function(done) {
|
||||
freq('/foo', {}, function (req, res) {
|
||||
var r = new Collection({}, req, res);
|
||||
var errs = r.authorize();
|
||||
done(errs);
|
||||
})
|
||||
})
|
||||
|
||||
it('should not allow users to PUT Collections without an _id', function(done) {
|
||||
freq('/foo', {method: 'PUT'}, function (req, res) {
|
||||
var r = new Collection({}, req, res);
|
||||
var errs = r.authorize();
|
||||
expect(errs).to.exist;
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should not allow users to DELETE Collections without an _id', function(done) {
|
||||
freq('/foo', {method: 'DELETE'}, function (req, res) {
|
||||
var r = new Collection({}, req, res);
|
||||
var errs = r.authorize();
|
||||
expect(errs).to.exist;
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
132
test/db.unit.js
132
test/db.unit.js
@@ -0,0 +1,132 @@
|
||||
var db = require('../lib/db')
|
||||
, TEST_DB = {name: 'test-db', host: 'localhost', port: 27017}
|
||||
, tester = db.connect(TEST_DB)
|
||||
, store = tester.createStore('test-store');
|
||||
|
||||
beforeEach(function(done){
|
||||
store.remove(function () {
|
||||
store.find(function (err, result) {
|
||||
expect(err).to.not.exist;
|
||||
expect(result).to.not.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('db', function(){
|
||||
describe('.connect(options)', function(){
|
||||
it('should connect to the database', function(done) {
|
||||
var tester = db.connect(TEST_DB);
|
||||
|
||||
tester.on('connected', function () {
|
||||
done();
|
||||
});
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('store', function(){
|
||||
|
||||
describe('.find(query, fn)', function(){
|
||||
it('should not find anything when the store is empty', function(done) {
|
||||
store.find(function (err, empty) {
|
||||
expect(empty).to.not.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
|
||||
it('should pass the query to the underline database', function(done) {
|
||||
store.insert([{i:1},{i:2},{i:3}], function () {
|
||||
store.find({i: {$lt: 3}}, function (err, result) {
|
||||
expect(result).to.exist;
|
||||
expect(result).to.have.length(2);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.remove(query, fn)', function(){
|
||||
it('should remove all the objects that match the query', function(done) {
|
||||
store.insert([{i:1},{i:2},{i:3}], function () {
|
||||
store.remove({i: {$lt: 3}}, function (err, result) {
|
||||
expect(result).to.not.exist;
|
||||
store.find(function (err, result) {
|
||||
expect(result).to.have.length(1);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('should remove all the objects', function(done) {
|
||||
store.insert([{i:1},{i:2},{i:3}], function () {
|
||||
store.remove(function (err, result) {
|
||||
expect(result).to.not.exist;
|
||||
store.find(function (err, result) {
|
||||
expect(result).to.not.exist;
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.insert(namespace, object, fn)', function(){
|
||||
it('should insert the given object into the namespace', function(done) {
|
||||
store.insert({testing: 123}, function (err, result) {
|
||||
expect(result._id).to.exist;
|
||||
expect(result.testing).to.equal(123);
|
||||
done();
|
||||
})
|
||||
})
|
||||
|
||||
it('should insert the given array into the namespace', function(done) {
|
||||
store.insert([{a:1}, {b:2}], function (err, result) {
|
||||
expect(Array.isArray(result)).to.equal(true);
|
||||
expect(result[0]._id).to.exist;
|
||||
expect(result[0].a).to.equal(1);
|
||||
expect(result[1]._id).to.exist;
|
||||
expect(result[1].b).to.equal(2);
|
||||
expect(result).to.have.length(2);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.update(query, updates, fn)', function(){
|
||||
it('should update only the properties provided', function(done) {
|
||||
store.insert({foo: 'bar'}, function (err, result) {
|
||||
expect(err).to.not.exist;
|
||||
var query = {_id: result._id};
|
||||
store.update(query, {foo: 'baz'}, function (err) {
|
||||
expect(err).to.not.exist;
|
||||
store.first(query, function (err, result) {
|
||||
expect(result.foo).to.equal('baz');
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('.rename(namespace, fn)', function(){
|
||||
it('should rename the underlying database representation of the store', function(done) {
|
||||
store.insert([{i:1},{i:2},{i:3}], function () {
|
||||
store.rename('foo-store', function () {
|
||||
store.find({i: {$lt: 3}}, function (err, result) {
|
||||
expect(result).to.exist;
|
||||
expect(result).to.have.length(2);
|
||||
store.rename('test-store', function () {
|
||||
store.find({i: {$lt: 3}}, function (err, result) {
|
||||
expect(result).to.exist;
|
||||
expect(result).to.have.length(2);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,24 @@
|
||||
var resources = require('../lib/resources')
|
||||
, db = require('../lib/db').connect({name: 'test-db', host: 'localhost', port: 27017})
|
||||
, store = db.createStore('resources')
|
||||
, testCollection = {type: 'Collection', path: '/my-objects', properties: {title: {type: 'string'}}}
|
||||
, Collection = require('../lib/resources/collection');
|
||||
|
||||
beforeEach(function(done){
|
||||
store.remove(function (err) {
|
||||
store.insert(testCollection, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('resources', function(){
|
||||
describe('.build(store)', function(){
|
||||
it('should return a set of resource instances', function(done) {
|
||||
resources.build(store).find(function (err, resources) {
|
||||
expect(resources).to.have.length(1);
|
||||
expect(resources[0].properties).to.be.a('object');
|
||||
expect(resources[0] instanceof Collection).to.equal(true);
|
||||
done(err);
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1 +1,21 @@
|
||||
expect = require('chai').expect;
|
||||
/**
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
expect = require('chai').expect;
|
||||
request = require('request');
|
||||
http = require('http');
|
||||
TEST_DB = {name: 'test-db', host: 'localhost', port: 27017};
|
||||
|
||||
// request mock
|
||||
freq = function(url, options, fn) {
|
||||
options.url = 'http://localhost:7777' + url;
|
||||
var s = http.createServer(function (req, res) {
|
||||
fn(req, res);
|
||||
s.close();
|
||||
})
|
||||
.listen(7777)
|
||||
.on('listening', function () {
|
||||
request(options);
|
||||
})
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
var validation = require('../lib/validation');
|
||||
|
||||
describe('validation', function() {
|
||||
describe('.isValid(value, description)', function () {
|
||||
function example(type, value, valid) {
|
||||
var v = validation.isType(value, type);
|
||||
if(v != valid) {
|
||||
console.log(type, value, valid, v);
|
||||
}
|
||||
expect(v).to.equal(valid);
|
||||
}
|
||||
|
||||
it('should validate the given property as a number', function() {
|
||||
example('number', 10, true);
|
||||
example('number', 1, true);
|
||||
example('number', 100000000000000000, true);
|
||||
example('number', -10000000000000000, true);
|
||||
example('number', Infinity, false);
|
||||
example('number', '10', false);
|
||||
example('number', '10.0', false);
|
||||
example('number', "10", false);
|
||||
example('number', new Date(), false);
|
||||
example('number', {}, false);
|
||||
example('number', null, false);
|
||||
example('number', undefined, false);
|
||||
example('number', /hello/, false);
|
||||
example('number', NaN, false);
|
||||
})
|
||||
|
||||
it('should validate the given property as a string', function() {
|
||||
example('string', 'test', true);
|
||||
example('string', "another test", true);
|
||||
example('string', 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', true);
|
||||
example('string', '<html>', true);
|
||||
example('string', 1, false);
|
||||
example('string', {}, false);
|
||||
example('string', null, false);
|
||||
example('string', undefined, false);
|
||||
example('string', new Date(), false);
|
||||
example('string', function() {}, false);
|
||||
example('string', NaN, false);
|
||||
})
|
||||
|
||||
it('should validate the given property as a date', function() {
|
||||
example('date', new Date(), true);
|
||||
example('date', new Date().toString(), true);
|
||||
example('date', new Date().getTime(), true);
|
||||
example('date', 'blah', false);
|
||||
example('date', /regex/, false);
|
||||
example('date', function() {}, false);
|
||||
example('date', null, false);
|
||||
example('date', undefined, false);
|
||||
example('date', NaN, false);
|
||||
})
|
||||
|
||||
it('should validate the given property as a boolean', function() {
|
||||
example('boolean', true, true);
|
||||
example('boolean', false, true);
|
||||
example('boolean', 0, false);
|
||||
example('boolean', 1, false);
|
||||
example('boolean', 'true', false);
|
||||
example('boolean', 'false', false);
|
||||
example('boolean', null, false);
|
||||
})
|
||||
|
||||
it('should validate the given property as an object', function() {
|
||||
example('object', {}, true);
|
||||
example('object', {length: 7}, true);
|
||||
example('object', {foo: 'bar'}, true);
|
||||
example('object', [], false);
|
||||
example('object', '{}', false);
|
||||
example('object', function() {}, false);
|
||||
example('object', undefined, false);
|
||||
example('object', null, false);
|
||||
example('object', NaN, false);
|
||||
example('object', 'foo', false);
|
||||
example('object', /test/, false);
|
||||
example('object', Infinity, false);
|
||||
example('object', Array, false);
|
||||
})
|
||||
|
||||
it('should validate the given property as an array', function() {
|
||||
example('array', [], true);
|
||||
example('array', [1,2,3], true);
|
||||
example('array', {length: 7}, false);
|
||||
example('array', {}, false);
|
||||
example('array', arguments, false);
|
||||
})
|
||||
|
||||
it('should validate the given property exists', function() {
|
||||
function required(value, exists) {
|
||||
var e = validation.exists(value);
|
||||
expect(e).to.equal(exists);
|
||||
}
|
||||
|
||||
required('foobar', true);
|
||||
required(function() {}, true);
|
||||
required(-1, true);
|
||||
required(0.000000000000000000000001, true);
|
||||
required(/foo/, true);
|
||||
required(null, false);
|
||||
required(undefined, false);
|
||||
required(NaN, false);
|
||||
required(NaN, false);
|
||||
required(0, true);
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user