diff options
Diffstat (limited to 'node_modules/revalidator')
-rw-r--r-- | node_modules/revalidator/.npmignore | 2 | ||||
-rw-r--r-- | node_modules/revalidator/.travis.yml | 11 | ||||
-rw-r--r-- | node_modules/revalidator/CHANGELOG.md | 25 | ||||
-rw-r--r-- | node_modules/revalidator/LICENSE | 179 | ||||
-rw-r--r-- | node_modules/revalidator/README.md | 301 | ||||
-rw-r--r-- | node_modules/revalidator/example/webservice.js | 204 | ||||
-rw-r--r-- | node_modules/revalidator/lib/revalidator.js | 427 | ||||
-rw-r--r-- | node_modules/revalidator/package.json | 63 | ||||
-rw-r--r-- | node_modules/revalidator/test/validator-test.js | 421 |
9 files changed, 1633 insertions, 0 deletions
diff --git a/node_modules/revalidator/.npmignore b/node_modules/revalidator/.npmignore new file mode 100644 index 0000000..5171c54 --- /dev/null +++ b/node_modules/revalidator/.npmignore @@ -0,0 +1,2 @@ +node_modules +npm-debug.log
\ No newline at end of file diff --git a/node_modules/revalidator/.travis.yml b/node_modules/revalidator/.travis.yml new file mode 100644 index 0000000..04d6dd9 --- /dev/null +++ b/node_modules/revalidator/.travis.yml @@ -0,0 +1,11 @@ +language: node_js +node_js: + - "0.8" + - "0.10" + - "0.11" + +notifications: + email: + - travis@nodejitsu.com + irc: "irc.freenode.org#nodejitsu" + diff --git a/node_modules/revalidator/CHANGELOG.md b/node_modules/revalidator/CHANGELOG.md new file mode 100644 index 0000000..8befb22 --- /dev/null +++ b/node_modules/revalidator/CHANGELOG.md @@ -0,0 +1,25 @@ + +0.1.3 / 2012-10-17 +================== + + * Fixed case problem with types + +0.1.2 / 2012-06-27 +================== + + * Added host-name String format + * Added support for additionalProperties + * Added few default validation messages for formats + +0.1.1 / 2012-04-16 +================== + + * Added default and custom error message support + * Added suport for conform function + * Updated date-time format + +0.1.0 / 2011-11-09 +================= + + * Initial release + diff --git a/node_modules/revalidator/LICENSE b/node_modules/revalidator/LICENSE new file mode 100644 index 0000000..a83d179 --- /dev/null +++ b/node_modules/revalidator/LICENSE @@ -0,0 +1,179 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright (c) 2009-2010 Alexis Sellier, Charlie Robbins, Nodejitsu Inc. diff --git a/node_modules/revalidator/README.md b/node_modules/revalidator/README.md new file mode 100644 index 0000000..be6601b --- /dev/null +++ b/node_modules/revalidator/README.md @@ -0,0 +1,301 @@ +# revalidator [![Build Status](https://secure.travis-ci.org/flatiron/revalidator.png)](http://travis-ci.org/flatiron/revalidator) + +A cross-browser / node.js validator used by resourceful and flatiron. Revalidator has [JSONSchema](http://tools.ietf.org/html/draft-zyp-json-schema-04) compatibility as primary goal. + +## Example +The core of `revalidator` is simple and succinct: `revalidator.validate(obj, schema)`: + +``` js + var revalidator = require('revalidator'); + + console.dir(revalidator.validate(someObject, { + properties: { + url: { + description: 'the url the object should be stored at', + type: 'string', + pattern: '^/[^#%&*{}\\:<>?\/+]+$', + required: true + }, + challenge: { + description: 'a means of protecting data (insufficient for production, used as example)', + type: 'string', + minLength: 5 + }, + body: { + description: 'what to store at the url', + type: 'any', + default: null + } + } + })); +``` + +This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation. + +``` js + { + valid: true // or false + errors: [/* Array of errors if valid is false */] + } +``` + +In the browser, the validation function is exposed on `window.validate` by simply including `revalidator.js`. + +## Installation + +### Installing npm (node package manager) +``` bash + $ curl http://npmjs.org/install.sh | sh +``` + +### Installing revalidator +``` bash + $ [sudo] npm install revalidator +``` + +## Usage + +`revalidator` takes json-schema as input to validate objects. + +### revalidator.validate (obj, schema, options) + +This will return with a value indicating if the `obj` conforms to the `schema`. If it does not, a descriptive object will be returned containing the errors encountered with validation. + +``` js +{ + valid: true // or false + errors: [/* Array of errors if valid is false */] +} +``` + +#### Available Options + +* __validateFormats__: Enforce format constraints (_default true_) +* __validateFormatsStrict__: When `validateFormats` is _true_ treat unrecognized formats as validation errors (_default false_) +* __validateFormatExtensions__: When `validateFormats` is _true_ also validate formats defined in `validate.formatExtensions` (_default true_) +* __cast__: Enforce casting of some types (for integers/numbers are only supported) when it's possible, e.g. `"42" => 42`, but `"forty2" => "forty2"` for the `integer` type. + +### Schema +For a property an `value` is that which is given as input for validation where as an `expected value` is the value of the below fields + +#### required +If true, the value should not be undefined + +```js +{ required: true } +``` + +#### allowEmpty +If false, the value must not be an empty string + +```js +{ allowEmpty: false } +``` + +#### type +The `type of value` should be equal to the expected value + +```js +{ type: 'string' } +{ type: 'number' } +{ type: 'integer' } +{ type: 'array' } +{ type: 'boolean' } +{ type: 'object' } +{ type: 'null' } +{ type: 'any' } +{ type: ['boolean', 'string'] } +``` + +#### pattern +The expected value regex needs to be satisfied by the value + +```js +{ pattern: /^[a-z]+$/ } +``` + +#### maxLength +The length of value must be greater than or equal to expected value + +```js +{ maxLength: 8 } +``` + +#### minLength +The length of value must be lesser than or equal to expected value + +```js +{ minLength: 8 } +``` + +#### minimum +Value must be greater than or equal to the expected value + +```js +{ minimum: 10 } +``` + +#### maximum +Value must be lesser than or equal to the expected value + +```js +{ maximum: 10 } +``` + +#### allowEmpty +Value may not be empty + +```js +{ allowEmpty: false } +``` + +#### exclusiveMinimum +Value must be greater than expected value + +```js +{ exclusiveMinimum: 9 } +``` + +### exclusiveMaximum +Value must be lesser than expected value + +```js +{ exclusiveMaximum: 11 } +``` + +#### divisibleBy +Value must be divisible by expected value + +```js +{ divisibleBy: 5 } +{ divisibleBy: 0.5 } +``` + +#### minItems +Value must contain more then expected value number of items + +```js +{ minItems: 2 } +``` + +#### maxItems +Value must contains less then expected value number of items + +```js +{ maxItems: 5 } +``` + +#### uniqueItems +Value must hold a unique set of values + +```js +{ uniqueItems: true } +``` + +#### enum +Value must be present in the array of expected value + +```js +{ enum: ['month', 'year'] } +``` + +#### format +Value must be a valid format + +```js +{ format: 'url' } +{ format: 'email' } +{ format: 'ip-address' } +{ format: 'ipv6' } +{ format: 'date-time' } +{ format: 'date' } +{ format: 'time' } +{ format: 'color' } +{ format: 'host-name' } +{ format: 'utc-millisec' } +{ format: 'regex' } +``` + +#### conform +Value must conform to constraint denoted by expected value + +```js +{ conform: function (v) { + if (v%3==1) return true; + return false; + } +} +``` + +#### dependencies +Value is valid only if the dependent value is valid + +```js +{ + town: { required: true, dependencies: 'country' }, + country: { maxLength: 3, required: true } +} +``` + +### Nested Schema +We also allow nested schema + +```js +{ + properties: { + title: { + type: 'string', + maxLength: 140, + required: true + }, + author: { + type: 'object', + required: true, + properties: { + name: { + type: 'string', + required: true + }, + email: { + type: 'string', + format: 'email' + } + } + } + } +} +``` + +### Custom Messages +We also allow custom message for different constraints + +```js +{ + type: 'string', + format: 'url' + messages: { + type: 'Not a string type', + format: 'Expected format is a url' + } +``` + +```js +{ + conform: function () { ... }, + message: 'This can be used as a global message' +} +``` + +## Tests +All tests are written with [vows][0] and should be run with [npm][1]: + +``` bash + $ npm test +``` + +#### Author: [Charlie Robbins](http://nodejitsu.com), [Alexis Sellier](http://cloudhead.io) +#### Contributors: [Fedor Indutny](http://github.com/indutny), [Bradley Meck](http://github.com/bmeck), [Laurie Harper](http://laurie.holoweb.net/) +#### License: Apache 2.0 + +[0]: http://vowsjs.org +[1]: http://npmjs.org diff --git a/node_modules/revalidator/example/webservice.js b/node_modules/revalidator/example/webservice.js new file mode 100644 index 0000000..33d5f0e --- /dev/null +++ b/node_modules/revalidator/example/webservice.js @@ -0,0 +1,204 @@ +// +// (C) 2011, Nodejitsu Inc. +// MIT License +// +// A simple web service for storing JSON data via REST +// +// GET - View Object +// POST - Create Object +// PUT - Update Object +// DELETE - Delete Object +// + +var revalidator = require('../'), + http = require('http'), +// +// Keep our objects in a simple memory store +// + memoryStore = {}, +// +// Set up our request schema +// + schema = { + properties: { + url: { + description: 'the url the object should be stored at', + type: 'string', + pattern: '^/[^#%&*{}\\:<>?\/+]+$', + required: true + }, + challenge: { + description: 'a means of protecting data (insufficient for production, used as example)', + type: 'string', + minLength: 5 + }, + body: { + description: 'what to store at the url', + type: 'any', + default: null + } + } + } + +var server = http.createServer(function validateRestRequest (req, res) { + req.method = req.method.toUpperCase(); + + // + // Log the requests + // + console.log(req.method, req.url); + + // + // Buffer the request so it can be parsed as JSON + // + var requestBody = []; + req.on('data', function addDataToBody (data) { + requestBody.push(data); + }); + + // + // Once the request has ended work with the body + // + req.on('end', function dealWithRest () { + + // + // Parse the JSON + // + requestBody = requestBody.join(''); + if ({POST: 1, PUT: 1}[req.method]) { + try { + requestBody = JSON.parse(requestBody); + } + catch (e) { + res.writeHead(400); + res.end(e); + return; + } + } + else { + requestBody = {}; + } + + // + // If this was sent to a url but the body url was not declared + // Make sure the body get the requested url so that our schema + // validates before we work on it + // + if (!requestBody.url) { + requestBody.url = req.url; + } + + // + // Don't let users override the main API endpoint + // + if (requestBody.url === '/') { + res.writeHead(400); + res.end('Cannot override the API endpoint "/"'); + return; + } + + // + // See if our request and target are out of sync + // This lets us double check the url we are about to take up + // if we choose to send the request to the url directly + // + if (req.url !== '/' && requestBody.url !== req.url) { + res.writeHead(400); + res.end('Requested url and actual url do not match'); + return; + } + + // + // Validate the schema + // + var validation = revalidator.validate(requestBody, schema); + if (!validation.valid) { + res.writeHead(400); + res.end(validation.errors.join('\n')); + return; + } + + // + // Grab the current value from storage and + // check if it is a valid state for REST + // + var storedValue = memoryStore[requestBody.url]; + if (req.method === 'POST') { + if (storedValue) { + res.writeHead(400); + res.end('ALREADY EXISTS'); + return; + } + } + else if (!storedValue) { + res.writeHead(404); + res.end('DOES NOT EXIST'); + return; + } + + // + // Check our challenge + // + if (storedValue && requestBody.challenge != storedValue.challenge) { + res.writeHead(403); + res.end('NOT AUTHORIZED'); + return; + } + + // + // Since revalidator only checks and does not manipulate + // our object we need to set up the defaults our selves + // For an easier solution to this please look at Flatiron's + // `Resourceful` project + // + if (requestBody.body === undefined) { + requestBody.body = schema.properties.body.default; + } + + // + // Use REST to determine how to manipulate the stored + // values + // + switch (req.method) { + + case "GET": + res.writeHead(200); + var result = storedValue.body; + res.end(JSON.stringify(result)); + return; + + case "POST": + res.writeHead(201); + res.end(); + memoryStore[requestBody.url] = requestBody; + return; + + case "DELETE": + delete memoryStore[requestBody.url]; + res.writeHead(200); + res.end(); + return; + + case "PUT": + memoryStore[requestBody.url] = requestBody; + res.writeHead(200); + res.end(); + return; + + default: + res.writeHead(400); + res.end('Invalid Http Verb'); + return; + } + }); +}) +// +// Listen to various ports depending on environment we are being run on +// +server.listen(process.env.PORT || process.env.C9_PORT || 1337, function reportListening () { + + console.log('JSON REST Service listening on port', this.address().port); + console.log('Requests can be sent via REST to "/" if they conform to the following schema:'); + console.log(JSON.stringify(schema, null, ' ')); + +});
\ No newline at end of file diff --git a/node_modules/revalidator/lib/revalidator.js b/node_modules/revalidator/lib/revalidator.js new file mode 100644 index 0000000..ad65814 --- /dev/null +++ b/node_modules/revalidator/lib/revalidator.js @@ -0,0 +1,427 @@ +(function (exports) { + exports.validate = validate; + exports.mixin = mixin; + + // + // ### function validate (object, schema, options) + // #### {Object} object the object to validate. + // #### {Object} schema (optional) the JSON Schema to validate against. + // #### {Object} options (optional) options controlling the validation + // process. See {@link #validate.defaults) for details. + // Validate <code>object</code> against a JSON Schema. + // If <code>object</code> is self-describing (i.e. has a + // <code>$schema</code> property), it will also be validated + // against the referenced schema. [TODO]: This behaviour bay be + // suppressed by setting the {@link #validate.options.???} + // option to <code>???</code>.[/TODO] + // + // If <code>schema</code> is not specified, and <code>object</code> + // is not self-describing, validation always passes. + // + // <strong>Note:</strong> in order to pass options but no schema, + // <code>schema</code> <em>must</em> be specified in the call to + // <code>validate()</code>; otherwise, <code>options</code> will + // be interpreted as the schema. <code>schema</code> may be passed + // as <code>null</code>, <code>undefinded</code>, or the empty object + // (<code>{}</code>) in this case. + // + function validate(object, schema, options) { + options = mixin({}, options, validate.defaults); + var errors = []; + + validateObject(object, schema, options, errors); + + // + // TODO: self-described validation + // if (! options.selfDescribing) { ... } + // + + return { + valid: !(errors.length), + errors: errors + }; + }; + + /** + * Default validation options. Defaults can be overridden by + * passing an 'options' hash to {@link #validate}. They can + * also be set globally be changing the values in + * <code>validate.defaults</code> directly. + */ + validate.defaults = { + /** + * <p> + * Enforce 'format' constraints. + * </p><p> + * <em>Default: <code>true</code></em> + * </p> + */ + validateFormats: true, + /** + * <p> + * When {@link #validateFormats} is <code>true</code>, + * treat unrecognized formats as validation errors. + * </p><p> + * <em>Default: <code>false</code></em> + * </p> + * + * @see validation.formats for default supported formats. + */ + validateFormatsStrict: false, + /** + * <p> + * When {@link #validateFormats} is <code>true</code>, + * also validate formats defined in {@link #validate.formatExtensions}. + * </p><p> + * <em>Default: <code>true</code></em> + * </p> + */ + validateFormatExtensions: true + }; + + /** + * Default messages to include with validation errors. + */ + validate.messages = { + required: "is required", + allowEmpty: "must not be empty", + minLength: "is too short (minimum is %{expected} characters)", + maxLength: "is too long (maximum is %{expected} characters)", + pattern: "invalid input", + minimum: "must be greater than or equal to %{expected}", + maximum: "must be less than or equal to %{expected}", + exclusiveMinimum: "must be greater than %{expected}", + exclusiveMaximum: "must be less than %{expected}", + divisibleBy: "must be divisible by %{expected}", + minItems: "must contain more than %{expected} items", + maxItems: "must contain less than %{expected} items", + uniqueItems: "must hold a unique set of values", + format: "is not a valid %{expected}", + conform: "must conform to given constraint", + type: "must be of %{expected} type" + }; + validate.messages['enum'] = "must be present in given enumerator"; + + /** + * + */ + validate.formats = { + 'email': /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i, + 'ip-address': /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i, + 'ipv6': /^([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4}$/, + 'date-time': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:.\d{1,3})?Z$/, + 'date': /^\d{4}-\d{2}-\d{2}$/, + 'time': /^\d{2}:\d{2}:\d{2}$/, + 'color': /^#[a-z0-9]{6}|#[a-z0-9]{3}|(?:rgb\(\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*,\s*(?:[+-]?\d+%?)\s*\))aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow$/i, + //'style': (not supported) + //'phone': (not supported) + //'uri': (not supported) + 'host-name': /^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])/, + 'utc-millisec': { + test: function (value) { + return typeof(value) === 'number' && value >= 0; + } + }, + 'regex': { + test: function (value) { + try { new RegExp(value) } + catch (e) { return false } + + return true; + } + } + }; + + /** + * + */ + validate.formatExtensions = { + 'url': /^(https?|ftp|git):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i + }; + + function mixin(obj) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue } + + if (typeof(source) !== 'object') { + throw new TypeError('mixin non-object'); + } + + for (var p in source) { + if (source.hasOwnProperty(p)) { + obj[p] = source[p]; + } + } + } + + return obj; + }; + + function validateObject(object, schema, options, errors) { + var props, allProps = Object.keys(object), + visitedProps = []; + + // see 5.2 + if (schema.properties) { + props = schema.properties; + for (var p in props) { + if (props.hasOwnProperty(p)) { + visitedProps.push(p); + validateProperty(object, object[p], p, props[p], options, errors); + } + } + } + + // see 5.3 + if (schema.patternProperties) { + props = schema.patternProperties; + for (var p in props) { + if (props.hasOwnProperty(p)) { + var re = new RegExp(p); + + // Find all object properties that are matching `re` + for (var k in object) { + if (object.hasOwnProperty(k)) { + visitedProps.push(k); + if (re.exec(k) !== null) { + validateProperty(object, object[k], p, props[p], options, errors); + } + } + } + } + } + } + + // see 5.4 + if (undefined !== schema.additionalProperties) { + var i, l; + + var unvisitedProps = allProps.filter(function(k){ + return -1 === visitedProps.indexOf(k); + }); + + // Prevent additional properties; each unvisited property is therefore an error + if (schema.additionalProperties === false && unvisitedProps.length > 0) { + for (i = 0, l = unvisitedProps.length; i < l; i++) { + error("additionalProperties", unvisitedProps[i], object[unvisitedProps[i]], false, errors); + } + } + // additionalProperties is a schema and validate unvisited properties against that schema + else if (typeof schema.additionalProperties == "object" && unvisitedProps.length > 0) { + for (i = 0, l = unvisitedProps.length; i < l; i++) { + validateProperty(object, object[unvisitedProps[i]], unvisitedProps[i], schema.unvisitedProperties, options, errors); + } + } + } + + }; + + function validateProperty(object, value, property, schema, options, errors) { + var format, + valid, + spec, + type; + + function constrain(name, value, assert) { + if (schema[name] !== undefined && !assert(value, schema[name])) { + error(name, property, value, schema, errors); + } + } + + if (value === undefined) { + if (schema.required && schema.type !== 'any') { + return error('required', property, undefined, schema, errors); + } else { + return; + } + } + + if (options.cast) { + if (('integer' === schema.type || 'number' === schema.type) && value == +value) { + value = +value; + object[property] = value; + } + + if ('boolean' === schema.type) { + if ('true' === value || '1' === value || 1 === value) { + value = true; + object[property] = value; + } + + if ('false' === value || '0' === value || 0 === value) { + value = false; + object[property] = value; + } + } + } + + if (schema.format && options.validateFormats) { + format = schema.format; + + if (options.validateFormatExtensions) { spec = validate.formatExtensions[format] } + if (!spec) { spec = validate.formats[format] } + if (!spec) { + if (options.validateFormatsStrict) { + return error('format', property, value, schema, errors); + } + } + else { + if (!spec.test(value)) { + return error('format', property, value, schema, errors); + } + } + } + + if (schema['enum'] && schema['enum'].indexOf(value) === -1) { + error('enum', property, value, schema, errors); + } + + // Dependencies (see 5.8) + if (typeof schema.dependencies === 'string' && + object[schema.dependencies] === undefined) { + error('dependencies', property, null, schema, errors); + } + + if (isArray(schema.dependencies)) { + for (var i = 0, l = schema.dependencies.length; i < l; i++) { + if (object[schema.dependencies[i]] === undefined) { + error('dependencies', property, null, schema, errors); + } + } + } + + if (typeof schema.dependencies === 'object') { + validateObject(object, schema.dependencies, options, errors); + } + + checkType(value, schema.type, function(err, type) { + if (err) return error('type', property, typeof value, schema, errors); + + constrain('conform', value, function (a, e) { return e(a, object) }); + + switch (type || (isArray(value) ? 'array' : typeof value)) { + case 'string': + constrain('allowEmpty', value, function (a, e) { return e ? e : a !== '' }); + constrain('minLength', value.length, function (a, e) { return a >= e }); + constrain('maxLength', value.length, function (a, e) { return a <= e }); + constrain('pattern', value, function (a, e) { + e = typeof e === 'string' + ? e = new RegExp(e) + : e; + return e.test(a) + }); + break; + case 'integer': + case 'number': + constrain('minimum', value, function (a, e) { return a >= e }); + constrain('maximum', value, function (a, e) { return a <= e }); + constrain('exclusiveMinimum', value, function (a, e) { return a > e }); + constrain('exclusiveMaximum', value, function (a, e) { return a < e }); + constrain('divisibleBy', value, function (a, e) { + var multiplier = Math.max((a - Math.floor(a)).toString().length - 2, (e - Math.floor(e)).toString().length - 2); + multiplier = multiplier > 0 ? Math.pow(10, multiplier) : 1; + return (a * multiplier) % (e * multiplier) === 0 + }); + break; + case 'array': + constrain('items', value, function (a, e) { + for (var i = 0, l = a.length; i < l; i++) { + validateProperty(object, a[i], property, e, options, errors); + } + return true; + }); + constrain('minItems', value, function (a, e) { return a.length >= e }); + constrain('maxItems', value, function (a, e) { return a.length <= e }); + constrain('uniqueItems', value, function (a) { + var h = {}; + + for (var i = 0, l = a.length; i < l; i++) { + var key = JSON.stringify(a[i]); + if (h[key]) return false; + h[key] = true; + } + + return true; + }); + break; + case 'object': + // Recursive validation + if (schema.properties || schema.patternProperties || schema.additionalProperties) { + validateObject(value, schema, options, errors); + } + break; + } + }); + }; + + function checkType(val, type, callback) { + var result = false, + types = isArray(type) ? type : [type]; + + // No type - no check + if (type === undefined) return callback(null, type); + + // Go through available types + // And fine first matching + for (var i = 0, l = types.length; i < l; i++) { + type = types[i].toLowerCase().trim(); + if (type === 'string' ? typeof val === 'string' : + type === 'array' ? isArray(val) : + type === 'object' ? val && typeof val === 'object' && + !isArray(val) : + type === 'number' ? typeof val === 'number' : + type === 'integer' ? typeof val === 'number' && ~~val === val : + type === 'null' ? val === null : + type === 'boolean'? typeof val === 'boolean' : + type === 'date' ? isDate(val) : + type === 'any' ? typeof val !== 'undefined' : false) { + return callback(null, type); + } + }; + + callback(true); + }; + + function error(attribute, property, actual, schema, errors) { + var lookup = { expected: schema[attribute], actual: actual, attribute: attribute, property: property }; + var message = schema.messages && schema.messages[attribute] || schema.message || validate.messages[attribute] || "no default message"; + message = message.replace(/%\{([a-z]+)\}/ig, function (_, match) { return lookup[match.toLowerCase()] || ''; }); + errors.push({ + attribute: attribute, + property: property, + expected: schema[attribute], + actual: actual, + message: message + }); + }; + + function isArray(value) { + var s = typeof value; + if (s === 'object') { + if (value) { + if (typeof value.length === 'number' && + !(value.propertyIsEnumerable('length')) && + typeof value.splice === 'function') { + return true; + } + } + } + return false; + } + + function isDate(value) { + var s = typeof value; + if (s === 'object') { + if (value) { + if (typeof value.getTime === 'function') { + return true; + } + } + } + + return false; + } + +})(typeof module === 'object' && module && module.exports ? module.exports : window); diff --git a/node_modules/revalidator/package.json b/node_modules/revalidator/package.json new file mode 100644 index 0000000..ee318b9 --- /dev/null +++ b/node_modules/revalidator/package.json @@ -0,0 +1,63 @@ +{ + "_from": "revalidator@0.1.x", + "_id": "revalidator@0.1.8", + "_inBundle": false, + "_integrity": "sha1-/s5hv6DBtSoga9axgZgYS91SOjs=", + "_location": "/revalidator", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "revalidator@0.1.x", + "name": "revalidator", + "escapedName": "revalidator", + "rawSpec": "0.1.x", + "saveSpec": null, + "fetchSpec": "0.1.x" + }, + "_requiredBy": [ + "/prompt" + ], + "_resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "_shasum": "fece61bfa0c1b52a206bd6b18198184bdd523a3b", + "_spec": "revalidator@0.1.x", + "_where": "/data/dev/Projets/Bingoloto Remote/node_modules/prompt", + "author": { + "name": "Nodejitsu Inc.", + "email": "info@nodejitsu.com" + }, + "bugs": { + "url": "https://github.com/flatiron/revalidator/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "A cross-browser / node.js validator used by resourceful", + "devDependencies": { + "vows": "0.7.0" + }, + "engines": { + "node": ">= 0.4.0" + }, + "homepage": "https://github.com/flatiron/revalidator#readme", + "license": "Apache 2.0", + "main": "./lib/revalidator", + "maintainers": [ + { + "name": "indexzero", + "email": "charlie@nodejitsu.com" + }, + { + "name": "indutny", + "email": "fedor.indutny@gmail.com" + } + ], + "name": "revalidator", + "repository": { + "type": "git", + "url": "git+ssh://git@github.com/flatiron/revalidator.git" + }, + "scripts": { + "test": "vows test/*-test.js --spec" + }, + "version": "0.1.8" +} diff --git a/node_modules/revalidator/test/validator-test.js b/node_modules/revalidator/test/validator-test.js new file mode 100644 index 0000000..6d962c2 --- /dev/null +++ b/node_modules/revalidator/test/validator-test.js @@ -0,0 +1,421 @@ +var assert = require('assert'), + vows = require('vows'), + revalidator = require('../lib/revalidator'); + +function clone(object) { + return Object.keys(object).reduce(function (obj, k) { + obj[k] = object[k]; + return obj; + }, {}); +}; + + +function assertInvalid(res) { + assert.isObject(res); + assert.strictEqual(res.valid, false); +} + +function assertValid(res) { + assert.isObject(res); + assert.strictEqual(res.valid, true); +} + +function assertHasError(attr, field) { + return function (res) { + assert.notEqual(res.errors.length, 0); + assert.ok(res.errors.some(function (e) { + return e.attribute === attr && (field ? e.property === field : true); + })); + }; +} + +function assertHasErrorMsg(attr, msg) { + return function (res) { + assert.notEqual(res.errors.length, 0); + assert.ok(res.errors.some(function (e) { + return e.attribute === attr && e.message === msg; + })); + }; +} + +function assertValidates(passingValue, failingValue, attributes) { + var schema = { + name: 'Resource', + properties: { field: {} } + }; + + var failing; + + if (!attributes) { + attributes = failingValue; + failing = false; + } else { + failing = true; + } + + var attr = Object.keys(attributes)[0]; + revalidator.mixin(schema.properties.field, attributes); + + var result = { + "when the object conforms": { + topic: function () { + return revalidator.validate({ field: passingValue }, schema); + }, + "return an object with `valid` set to true": assertValid + } + }; + + if (failing) { + result["when the object does not conform"] ={ + topic: function () { + return revalidator.validate({ field: failingValue }, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and an error concerning the attribute": assertHasError(Object.keys(attributes)[0], 'field') + }; + }; + + return result; +} + +vows.describe('revalidator', { + "Validating": { + "with <type>:'string'": assertValidates ('hello', 42, { type: "string" }), + "with <type>:'number'": assertValidates (42, 'hello', { type: "number" }), + "with <type>:'integer'": assertValidates (42, 42.5, { type: "integer" }), + "with <type>:'array'": assertValidates ([4, 2], 'hi', { type: "array" }), + "with <type>:'object'": assertValidates ({}, [], { type: "object" }), + "with <type>:'boolean'": assertValidates (false, 42, { type: "boolean" }), + "with <types>:bool,num": assertValidates (false, 'hello', { type: ["boolean", "number"] }), + "with <types>:bool,num": assertValidates (544, null, { type: ["boolean", "number"] }), + "with <type>:'null'": assertValidates (null, false, { type: "null" }), + "with <type>:'any'": assertValidates (9, { type: "any" }), + "with <type>:'date'": assertValidates (new Date(), 'hello', { type: "date" }), + "with <pattern>": assertValidates ("kaboom", "42", { pattern: /^[a-z]+$/ }), + "with <maxLength>": assertValidates ("boom", "kaboom", { maxLength: 4 }), + "with <minLength>": assertValidates ("kaboom", "boom", { minLength: 6 }), + "with <allowEmpty>": assertValidates ("hello", "", { allowEmpty: false }), + "with <minimum>": assertValidates ( 512, 43, { minimum: 473 }), + "with <maximum>": assertValidates ( 512, 1949, { maximum: 678 }), + "with <divisibleBy>": assertValidates ( 10, 9, { divisibleBy: 5 }), + "with <divisibleBy> decimal": assertValidates ( 0.2, 0.009, { divisibleBy: 0.01 }), + "with <enum>": assertValidates ("orange", "cigar", { enum: ["orange", "apple", "pear"] }), + "with <format>:'url'": assertValidates ('http://test.com/', 'hello', { format: 'url' }), + "with <dependencies>": { + topic: { + properties: { + town: { dependencies: "country" }, + country: { } + } + }, + "when the object conforms": { + topic: function (schema) { + return revalidator.validate({ town: "luna", country: "moon" }, schema); + }, + "return an object with `valid` set to true": assertValid + }, + "when the object does not conform": { + topic: function (schema) { + return revalidator.validate({ town: "luna" }, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and an error concerning the attribute": assertHasError('dependencies') + } + }, + "with <dependencies> as array": { + topic: { + properties: { + town: { dependencies: ["country", "planet"] }, + country: { }, + planet: { } + } + }, + "when the object conforms": { + topic: function (schema) { + return revalidator.validate({ town: "luna", country: "moon", planet: "mars" }, schema); + }, + "return an object with `valid` set to true": assertValid + }, + "when the object does not conform": { + topic: function (schema) { + return revalidator.validate({ town: "luna", planet: "mars" }, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and an error concerning the attribute": assertHasError('dependencies') + } + }, + "with <dependencies> as schema": { + topic: { + properties: { + town: { + type: 'string', + dependencies: { + properties: { x: { type: "number" } } + } + }, + country: { } + } + }, + "when the object conforms": { + topic: function (schema) { + return revalidator.validate({ town: "luna", x: 1 }, schema); + }, + "return an object with `valid` set to true": assertValid, + }, + "when the object does not conform": { + topic: function (schema) { + return revalidator.validate({ town: "luna", x: 'no' }, schema); + }, + "return an object with `valid` set to false": assertInvalid + } + }, + "with <type>:'integer' and": { + "<minimum> constraints": assertValidates ( 512, 43, { minimum: 473, type: 'integer' }), + "<maximum> constraints": assertValidates ( 512, 1949, { maximum: 678, type: 'integer' }), + "<divisibleBy> constraints": assertValidates ( 10, 9, { divisibleBy: 5, type: 'integer' }) + }, + "with <additionalProperties>:false": { + topic: { + properties: { + town: { type: 'string' } + }, + additionalProperties: false + }, + "when the object conforms": { + topic: function (schema) { + return revalidator.validate({ town: "luna" }, schema); + }, + "return an object with `valid` set to true": assertValid + }, + "when the object does not conform": { + topic: function (schema) { + return revalidator.validate({ town: "luna", area: 'park' }, schema); + }, + "return an object with `valid` set to false": assertInvalid + } + } + } +}).addBatch({ + "A schema": { + topic: { + name: 'Article', + properties: { + title: { + type: 'string', + maxLength: 140, + conditions: { + optional: function () { + return !this.published; + } + } + }, + date: { type: 'string', format: 'date', messages: { format: "must be a valid %{expected} and nothing else" } }, + body: { type: 'string' }, + tags: { + type: 'array', + uniqueItems: true, + minItems: 2, + items: { + type: 'string', + pattern: /[a-z ]+/ + } + }, + tuple: { + type: 'array', + minItems: 2, + maxItems: 2, + items: { + type: ['string', 'number'] + } + }, + author: { type: 'string', pattern: /^[\w ]+$/i, required: true, messages: { required: "is essential for survival" } }, + published: { type: 'boolean', 'default': false }, + category: { type: 'string' }, + palindrome: {type: 'string', conform: function(val) { + return val == val.split("").reverse().join(""); } + }, + name: { type: 'string', default: '', conform: function(val, data) { + return (val === data.author); } + } + }, + patternProperties: { + '^_': { + type: 'boolean', default: false + } + } + }, + "and an object": { + topic: { + title: 'Gimme some Gurus', + date: '2012-02-04', + body: "And I will pwn your codex.", + tags: ['energy drinks', 'code'], + tuple: ['string0', 103], + author: 'cloudhead', + published: true, + category: 'misc', + palindrome: 'dennis sinned', + name: 'cloudhead', + _flag: true + }, + "can be validated with `revalidator.validate`": { + "and if it conforms": { + topic: function (object, schema) { + return revalidator.validate(object, schema); + }, + "return an object with the `valid` property set to true": assertValid, + "return an object with the `errors` property as an empty array": function (res) { + assert.isArray(res.errors); + assert.isEmpty(res.errors); + } + }, + "and if it has a missing required property": { + topic: function (object, schema) { + object = clone(object); + delete object.author; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and an error concerning the 'required' attribute": assertHasError('required'), + "and the error message defined": assertHasErrorMsg('required', "is essential for survival") + }, + "and if it has a missing non-required property": { + topic: function (object, schema) { + object = clone(object); + delete object.category; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertValid + }, + "and if it has a incorrect pattern property": { + topic: function (object, schema) { + object = clone(object); + object._additionalFlag = 'text'; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid + }, + "and if it has a incorrect unique array property": { + topic: function (object, schema) { + object = clone(object); + object.tags = ['a', 'a']; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid + }, + "and if it has a incorrect array property (wrong values)": { + topic: function (object, schema) { + object = clone(object); + object.tags = ['a', '____']; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid + }, + "and if it has a incorrect array property (< minItems)": { + topic: function (object, schema) { + object = clone(object); + object.tags = ['x']; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid + }, + "and if it has a incorrect format (date)": { + topic: function (object, schema) { + object = clone(object); + object.date = 'bad date'; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and the error message defined": assertHasErrorMsg('format', "must be a valid date and nothing else") + }, + "and if it is not a palindrome (conform function)": { + topic: function (object, schema) { + object = clone(object); + object.palindrome = 'bad palindrome'; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid + }, + "and if it didn't validate a pattern": { + topic: function (object, schema) { + object = clone(object); + object.author = 'email@address.com'; + return revalidator.validate(object, schema); + }, + "return an object with `valid` set to false": assertInvalid, + "and an error concerning the 'pattern' attribute": assertHasError('pattern') + }, + } + }, + "with <cast> option": { + topic: { + properties: { + answer: { type: "integer" }, + is_ready: { type: "boolean" } + } + }, + "and <integer> property": { + "is castable string": { + topic: function (schema) { + return revalidator.validate({ answer: "42" }, schema, { cast: true }); + }, + "return an object with `valid` set to true": assertValid + }, + "is uncastable string": { + topic: function (schema) { + return revalidator.validate({ answer: "forty2" }, schema, { cast: true }); + }, + "return an object with `valid` set to false": assertInvalid + }, + "is casted to integer": { + topic: function (schema) { + var object = { answer: "42" }; + revalidator.validate(object, schema, { cast: true }); + return object; + }, + "return an object with `answer` set to 42": function(res) { assert.strictEqual(res.answer, 42) } + } + }, + "and <boolean> property": { + "is castable 'true/false' string": { + topic: function (schema) { + return revalidator.validate({ is_ready: "true" }, schema, { cast: true }); + }, + "return an object with `valid` set to true": assertValid + }, + "is castable '1/0' string": { + topic: function (schema) { + return revalidator.validate({ is_ready: "1" }, schema, { cast: true }); + }, + "return an object with `valid` set to true": assertValid + }, + "is castable `1/0` integer": { + topic: function (schema) { + return revalidator.validate({ is_ready: 1 }, schema, { cast: true }); + }, + "return an object with `valid` set to true": assertValid + }, + "is uncastable string": { + topic: function (schema) { + return revalidator.validate({ is_ready: "not yet" }, schema, { cast: true }); + }, + "return an object with `valid` set to false": assertInvalid + }, + "is uncastable number": { + topic: function (schema) { + return revalidator.validate({ is_ready: 42 }, schema, { cast: true }); + }, + "return an object with `valid` set to false": assertInvalid + }, + "is casted to boolean": { + topic: function (schema) { + var object = { is_ready: "true" }; + revalidator.validate(object, schema, { cast: true }); + return object; + }, + "return an object with `is_ready` set to true": function(res) { assert.strictEqual(res.is_ready, true) } + } + } + } + } +}).export(module); |