add browser tests, use webmake for compiling into browser module
This commit is contained in:
parent
cac6b7edc2
commit
918e86d79a
|
@ -0,0 +1,507 @@
|
|||
// This file was generated by modules-webmake (modules for web) project
|
||||
// see: https://github.com/medikoo/modules-webmake
|
||||
|
||||
window.schema = (function (modules) {
|
||||
var getModule, getRequire, require;
|
||||
getModule = (function (wrap) {
|
||||
return function (scope, tree, path, fullpath) {
|
||||
var name, dir, exports = {}, module = { exports: exports }, fn, isDir;
|
||||
path = path.split('/');
|
||||
name = path.pop();
|
||||
if (!name) {
|
||||
isDir = true;
|
||||
name = path.pop();
|
||||
}
|
||||
if ((name === '.') || (name === '..')) {
|
||||
path.push(name);
|
||||
name = '';
|
||||
}
|
||||
while ((dir = path.shift())) {
|
||||
if (dir === '..') {
|
||||
scope = tree.pop();
|
||||
} else if (dir !== '.') {
|
||||
tree.push(scope);
|
||||
scope = scope[dir];
|
||||
}
|
||||
}
|
||||
if (name) {
|
||||
if (!isDir && scope[name + '.js']) {
|
||||
name += '.js';
|
||||
}
|
||||
if (typeof scope[name] === 'object') {
|
||||
tree.push(scope);
|
||||
scope = scope[name];
|
||||
name = 'index.js';
|
||||
}
|
||||
} else {
|
||||
name = 'index.js';
|
||||
}
|
||||
fn = scope[name];
|
||||
if (!fn) {
|
||||
throw new Error("Could not find module '" + fullpath + "'");
|
||||
}
|
||||
scope[name] = wrap(module);
|
||||
fn.call(exports, exports, module, getRequire(scope, tree));
|
||||
return module.exports;
|
||||
};
|
||||
}(function (cmodule) {
|
||||
return function (ignore, module) {
|
||||
module.exports = cmodule.exports;
|
||||
};
|
||||
}));
|
||||
require = function (scope, tree, fullpath) {
|
||||
var name, path = fullpath, t = fullpath.charAt(0);
|
||||
if (t === '/') {
|
||||
path = path.slice(1);
|
||||
scope = modules['/'];
|
||||
tree = [];
|
||||
} else if (t !== '.') {
|
||||
name = path.split('/', 1)[0];
|
||||
scope = modules[name];
|
||||
tree = [];
|
||||
path = path.slice(name.length + 1) || scope[':mainpath:'];
|
||||
}
|
||||
return getModule(scope, tree, path, fullpath);
|
||||
};
|
||||
getRequire = function (scope, tree) {
|
||||
return function (path) {
|
||||
return require(scope, [].concat(tree), path);
|
||||
};
|
||||
};
|
||||
return getRequire(modules, []);
|
||||
})
|
||||
({
|
||||
"schemajs": {
|
||||
"lib": {
|
||||
"rules.js": function (exports, module, require) {
|
||||
var Rules = function(param, rules)
|
||||
{
|
||||
this.param = param;
|
||||
this.rules = rules;
|
||||
};
|
||||
|
||||
Rules.prototype.Error = function(message, rule, value)
|
||||
{
|
||||
switch(typeof(this.rules.error))
|
||||
{
|
||||
case 'string':
|
||||
message = this.rules.error;
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
|
||||
if(this.rules.error[rule])
|
||||
{
|
||||
message = this.rules.error[rule];
|
||||
}
|
||||
else if(this.rules.error['default'])
|
||||
{
|
||||
message = this.rules.error['default'];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if(_.isString(value))
|
||||
message = message.replace(/%v/, value.toString());
|
||||
|
||||
if(_.isString(rule))
|
||||
message = message.replace(/%r/, rule);
|
||||
|
||||
return message.replace(/%p/, this.param).replace(/%v/, "value").replace(/%r/, "rule");
|
||||
};
|
||||
|
||||
Rules.prototype.apply = function(value)
|
||||
{
|
||||
if(_.isEmpty(value) && !_.isUndefined(this.rules['default']))
|
||||
{
|
||||
value = this.rules['default'];
|
||||
}
|
||||
|
||||
if(this.rules.required)
|
||||
{
|
||||
if(this.rules.required && _.isUndefined(value))
|
||||
{
|
||||
throw this.Error("%p is a required parameter", "required", value);
|
||||
}
|
||||
}
|
||||
// if value is not required and is undefined, no more rules need to be run
|
||||
else if(_.isUndefined(value))
|
||||
return value;
|
||||
|
||||
if(this.rules.filters)
|
||||
{
|
||||
value = this.filter(value);
|
||||
}
|
||||
|
||||
if(this.rules.type)
|
||||
{
|
||||
if(typeof(this.rules.type) == "string" && typeof(is[this.rules.type]) == "function")
|
||||
{
|
||||
if(!is[this.rules.type](value))
|
||||
throw this.Error("%p is not a " + this.rules.type, "type", value);
|
||||
}
|
||||
else if(typeof(this.rules.type == "function"))
|
||||
{
|
||||
if(!this.rules.type(value))
|
||||
throw this.Error("%p is not a valid type", "type", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw this.Error("%p is not a valid type", "type", value);
|
||||
}
|
||||
}
|
||||
|
||||
if(this.rules.properties)
|
||||
{
|
||||
this.check(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
Rules.prototype.filter = function(value)
|
||||
{
|
||||
switch(typeof(this.rules.filters))
|
||||
{
|
||||
case 'function':
|
||||
value = this.rules.filters(value);
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
|
||||
if(typeof(filters[this.rules.filters]) === 'function')
|
||||
{
|
||||
value = filters[this.rules.filters](value);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
|
||||
if(_.isArray(this.rules.filters))
|
||||
{
|
||||
this.rules.filters.forEach(function(filter) { value = filters[filter](value); });
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
Rules.prototype.check = function(value)
|
||||
{
|
||||
switch(typeof(this.rules.properties))
|
||||
{
|
||||
case 'function':
|
||||
|
||||
if(!this.rules.properties(value))
|
||||
throw this.Error("%p is not valid");
|
||||
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
|
||||
var properties = _.keys(this.rules.properties);
|
||||
|
||||
for(var i = 0; i < properties.length; i++)
|
||||
{
|
||||
var property = properties[i];
|
||||
|
||||
if(typeof(checks[property]) === "function")
|
||||
{
|
||||
var args = this.rules.properties[property];
|
||||
|
||||
if(!checks[property].apply(null, [value, args]))
|
||||
throw this.Error("%p failed %r with %v", property);
|
||||
}
|
||||
else if(typeof(this.rules.properties[property]) === "function")
|
||||
{
|
||||
if(!this.rules.properties[property].apply(null, [value]))
|
||||
throw this.Error("%p failed on %r with %v", property);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
var checks =
|
||||
{
|
||||
'max': function(value, length)
|
||||
{
|
||||
if(_.isArray(value) || typeof(value) == "string")
|
||||
{
|
||||
return value.length <= length;
|
||||
}
|
||||
else if(typeof(value) == "number")
|
||||
{
|
||||
return value <= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
'min': function(value, length)
|
||||
{
|
||||
if(_.isArray(value) || typeof(value) == "string")
|
||||
{
|
||||
return value.length >= length;
|
||||
}
|
||||
else if(typeof(value) == "number")
|
||||
{
|
||||
return value >= length;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
'regex': function(value, regex)
|
||||
{
|
||||
return regex.test(value);
|
||||
},
|
||||
|
||||
'in': function(value, list)
|
||||
{
|
||||
return list.indexOf(value) != -1;
|
||||
}
|
||||
};
|
||||
|
||||
var is =
|
||||
{
|
||||
'string+': function(value)
|
||||
{
|
||||
return typeof(value) == 'string' && value.length && !(/^\s+$/.test(value));
|
||||
},
|
||||
|
||||
'string': function(value)
|
||||
{
|
||||
return typeof(value) == 'string';
|
||||
},
|
||||
|
||||
'alphanum': function(value)
|
||||
{
|
||||
return (/^[a-zA-Z0-9]+$/i).test(value) && typeof(value) == 'string';
|
||||
},
|
||||
|
||||
'alpha': function(value)
|
||||
{
|
||||
return (/^[a-zA-Z]+$/i).test(value);
|
||||
},
|
||||
|
||||
'object': function(value)
|
||||
{
|
||||
return typeof(value) == 'object' && !_.isArray(value);
|
||||
},
|
||||
|
||||
'array': function(value)
|
||||
{
|
||||
return _.isArray(value);
|
||||
},
|
||||
|
||||
'date': function(value)
|
||||
{
|
||||
// getTime() allows us to check if date is valid
|
||||
return _.isDate(value) && !isNaN(value.getTime());
|
||||
},
|
||||
|
||||
'number': function(value)
|
||||
{
|
||||
return typeof(value) == 'number' && !isNaN(value);
|
||||
},
|
||||
|
||||
'int': function(value)
|
||||
{
|
||||
return typeof(value) == 'number' && value % 1 === 0 && !isNaN(value);
|
||||
},
|
||||
|
||||
'boolean': function(value)
|
||||
{
|
||||
return _.isBoolean(value);
|
||||
},
|
||||
|
||||
'float': function(value)
|
||||
{
|
||||
return typeof(value) == 'number' && !isNaN(value);
|
||||
},
|
||||
|
||||
'email': function(value)
|
||||
{
|
||||
return (/[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[a-zA-Z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-]*[a-zA-Z0-9])?/).test(value);
|
||||
},
|
||||
|
||||
'url': function(value)
|
||||
{
|
||||
return (/^(http(s)?:\/\/)?([\w\-]+\.{1})*(([\w\-]*){1}(\.{1}[A-Za-z]{2,4}){1}){1}(\:{1}\d*)?([\?\/|\#]+[\@\~\;\+\'\#\,\.\%\-\/\&\?\=\w\$\s]*)*$/i).test(value);
|
||||
},
|
||||
|
||||
'zipcode': function(value)
|
||||
{
|
||||
return (/\d{5}/).test(value);
|
||||
}
|
||||
};
|
||||
|
||||
var filters =
|
||||
{
|
||||
'toInt': function(value)
|
||||
{
|
||||
return parseInt(value, 10);
|
||||
},
|
||||
|
||||
'toFloat': function(value)
|
||||
{
|
||||
return parseFloat(value, 10);
|
||||
},
|
||||
|
||||
'toString': function(value)
|
||||
{
|
||||
return value.toString();
|
||||
},
|
||||
|
||||
'toDate': function(value)
|
||||
{
|
||||
return new Date(value);
|
||||
},
|
||||
|
||||
'toBoolean': function(value)
|
||||
{
|
||||
if(value === 1 || value === true || /true|on|yes|1/.test(value))
|
||||
return true;
|
||||
else if(value === 0 || value === false || /false|off|no|0/.test(value))
|
||||
return false;
|
||||
else
|
||||
return value;
|
||||
},
|
||||
|
||||
'trim': function(value)
|
||||
{
|
||||
return _.isString(value) ? value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : value;
|
||||
},
|
||||
|
||||
'lowercase': function(value)
|
||||
{
|
||||
return _.isString(value) ? value.toLowerCase() : value;
|
||||
},
|
||||
|
||||
'uppercase': function(value)
|
||||
{
|
||||
return _.isString(value) ? value.toUpperCase() : value;
|
||||
}
|
||||
};
|
||||
|
||||
exports.create = function(param, rules) { return new Rules(param, rules); };
|
||||
exports.types = is;
|
||||
exports.filters = filters;
|
||||
exports.properties = checks;
|
||||
},
|
||||
"schema.js": function (exports, module, require) {
|
||||
var rules = require('./rules.js');
|
||||
|
||||
var Schema = function(schema)
|
||||
{
|
||||
this.schema = schema;
|
||||
};
|
||||
|
||||
Schema.prototype.validate = function(data)
|
||||
{
|
||||
var params = _.keys(this.schema);
|
||||
var errors = {};
|
||||
var values = {};
|
||||
var value;
|
||||
var get = typeof(data) == "function" ? data : function(p) { return data[p]; };
|
||||
|
||||
for(var i = 0; i < params.length; i++)
|
||||
{
|
||||
var schema = this.schema[params[i]];
|
||||
|
||||
try
|
||||
{
|
||||
// if undefined, don't store it.
|
||||
value = rules.create(params[i], schema).apply(get(params[i]));
|
||||
|
||||
if(!_.isUndefined(value))
|
||||
{
|
||||
values[params[i]] = value;
|
||||
}
|
||||
|
||||
// does this rule contain embedded schemas
|
||||
if(typeof(schema.schema) == "object" && !_.isArray(schema.schema) && _.keys(schema.schema).length && !_.isUndefined(values[params[i]]))
|
||||
{
|
||||
if(schema.type == "object")
|
||||
{
|
||||
_.keys(schema.schema).forEach(function(param)
|
||||
{
|
||||
try
|
||||
{
|
||||
// if undefined, don't store it
|
||||
value = rules.create(params[i] + "." + param, schema.schema[param]).apply(get(params[i])[param]);
|
||||
|
||||
if(!_.isUndefined(value))
|
||||
{
|
||||
values[params[i]][param] = value;
|
||||
}
|
||||
}
|
||||
catch(error)
|
||||
{
|
||||
if(!errors[params[i]] || typeof(errors[params[i]]) != 'object')
|
||||
errors[params[i]] = {};
|
||||
|
||||
errors[params[i]][param] = error;
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(schema.type == "array")
|
||||
{
|
||||
values[params[i]].forEach(function(value, index)
|
||||
{
|
||||
try
|
||||
{
|
||||
// if not required and undefined, don't store in values!
|
||||
values[params[i]][index] = rules.create(params[i] + "[" + index + "]", schema.schema).apply(value);
|
||||
}
|
||||
catch(error)
|
||||
{
|
||||
if(!_.isArray(errors[params[i]]))
|
||||
errors[params[i]] = [];
|
||||
|
||||
errors[params[i]][index] = error;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(error)
|
||||
{
|
||||
errors[params[i]] = error;
|
||||
}
|
||||
}
|
||||
|
||||
return {data:values, errors:errors, valid:_.keys(errors).length === 0};
|
||||
};
|
||||
|
||||
exports.types = rules.types;
|
||||
exports.test = function(value, schema) { return (new Schema({input:schema})).validate({input:value}); };
|
||||
exports.properties = rules.properties;
|
||||
exports.filters = rules.filters;
|
||||
exports.create = function(schema) { return new Schema(schema); };
|
||||
exports.middleware = function(schema)
|
||||
{
|
||||
return function(req, res, next)
|
||||
{
|
||||
req.form = new Schema(schema).validate(req.route.method == "post" ? req.body : req.query);
|
||||
next();
|
||||
};
|
||||
};
|
||||
}
|
||||
},
|
||||
"schema.js": function (exports, module, require) {
|
||||
module.exports = require("./lib/schema.js");
|
||||
}
|
||||
}
|
||||
})
|
||||
("schemajs/schema");
|
|
@ -0,0 +1,30 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>schemajs browser tests</title>
|
||||
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" type="text/css" charset="utf-8">
|
||||
<script src="../node_modules/mocha/mocha.js"></script>
|
||||
<script src="../node_modules/chai/chai.js"></script>
|
||||
<script>mocha.setup('bdd')</script>
|
||||
|
||||
<!-- include required modules -->
|
||||
<script src="../node_modules/underscore/underscore.js"></script>
|
||||
<script src="../dist/schema-browser.js"></script>
|
||||
|
||||
<!-- include individual tests -->
|
||||
<script src="complex.js"></script>
|
||||
<script src="default.js"></script>
|
||||
<script src="error.js"></script>
|
||||
<script src="filters.js"></script>
|
||||
<script src="properties.js"></script>
|
||||
<script src="required.js"></script>
|
||||
<script src="types.js"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="mocha"></div>
|
||||
<script type="text/javascript">
|
||||
mocha.run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,7 +1,8 @@
|
|||
describe("complex schemas", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("arrays", function()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
describe("default schemas", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("default values", function()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
describe("schema errors", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("basic error", function()
|
||||
{
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
describe("filter schemas", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("toInt filter", function()
|
||||
{
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
describe("filter schemas", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("minimum string length property", function()
|
||||
{
|
||||
var schema = schemajs.create(
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
describe("required schemas", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("required", function()
|
||||
{
|
||||
var schema = schemajs.create(
|
||||
{
|
||||
input: {type:'string', required:true},
|
||||
output: {type:'string'},
|
||||
output: {type:'string'}
|
||||
});
|
||||
var input1 = schema.validate({input: 'username'});
|
||||
var input2 = schema.validate({});
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
describe("schema types", function()
|
||||
{
|
||||
var schemajs = require('../schema');
|
||||
var expect = require('chai').expect;
|
||||
|
||||
/*jshint expr:true*/
|
||||
var schemajs = (typeof window === 'undefined') ? require('../schema') : window.schema;
|
||||
var expect = (typeof window === 'undefined') ? require('chai').expect : window.chai.expect;
|
||||
|
||||
it("string", function()
|
||||
{
|
||||
var schema = schemajs.create(
|
||||
|
|
Reference in New Issue