UNPKG

node-restify-validation

Version:

```diff -Maintener wanted ``` Validation for REST Services built with [node-restify](https://github.com/mcavage/node-restify) in node.js

299 lines (274 loc) 11.4 kB
/* * The MIT License * * Copyright 2017 Stepan Riha. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ var _ = require('lodash'); var index = require('../../lib/index'); describe('Model', function () { var validationReq; var timeStamp = new Date(); beforeEach(function () { validationReq = { params: {num: '-123.5'}, query: { flag: 'true', scores: ['1', '2', '100'], int: '123', decimal: '234.56' }, body: { from: timeStamp.toISOString(), to: timeStamp.valueOf(), ts: String(timeStamp.valueOf()), dict: { 'First': 'January', 'Second': 'February', 'Third': 'March' } } }; }); describe('validatorModels', function () { var options = { validatorModels: index.validatorModels, errorsAsArray: true }; _.forEach([ // Configured validatorModels ['isBoolean', true, 'true', true], ['isDate', true, '2018-03-17', new Date('2018-03-17')], ['isDecimal', true, '123.45', 123.45], ['isDivisibleBy', 5, "10", 10], ['isFloat', true, '123.45', 123.45], ['isInt', true, '-12345', -12345], ['isNatural', true, '12345', 12345], // Without validatorModels ['contains', 'es', 'test'], ['equals', 'test', 'test'], ['is', 'test', 'test'], ['isAfter', '2018-03-17', '2018-03-18'], ['isAlpha', true, 'test'], ['isAlphanumeric', true, 'test123'], ['isBefore', '2018-03-17', '2018-03-16'], ['isCreditCard', true, '4012888888881881'], ['isEmail', true, 'bob@example.com'], ['isHexColor', true, '#aabbcc'], ['isHexadecimal', true, '01234567abcdef'], ['isIP', true, '127.0.0.1'], ['isIPNet', true, '127.0.0.1/27'], ['isIPv4', true, '127.0.0.1'], ['isIPv6', true, '2001:0db8:85a3:0000:0000:8a2e:0370:7334'], ['isIn', ['test'], 'test'], ['isLowercase', true, 'test'], ['isNumeric', true, '12345'], ['isUUID', true, 'bf18cbf6-0cfd-4cc4-8625-a3a150c81e4b'], ['isUUIDv3', true, '6fa459ea-ee8a-3ca4-894e-db77e160355e'], ['isUUIDv4', true, '5d05b396-2ccf-4c6d-bf8b-844191aa3c1b'], ['isUppercase', true, 'TEST'], ['isUrl', true, 'http://example.com'], ['max', 10, '5'], ['min', 1, '5'], ['not', 'test', 'TEST'], ['notContains', 'se', 'test'], ['notIn', ['TEST'], 'test'], ['notRegex', /TEST/, 'test'], ['regex', /test/, 'test'] ], function (test) { var validator = test[0], conf = test[1], value = test[2], expected = _.isUndefined(test[3]) ? value : test[3]; var validatorDescription = ('{ ' + validator + ': ' + JSON.stringify(conf, function(key, val) { return (val instanceof RegExp) ? "REGEX:" + val.toString() : val; }) + ' }').replace(/\"REGEX:(\/.*\/)\"/, "$1"); if (value === expected) { it(validatorDescription + ' keeps ' + JSON.stringify(value) + ' unchanged', testValidator(validator, conf, value, expected)); } else { it(validatorDescription + ' maps ' + JSON.stringify(value) + ' to ' + JSON.stringify(expected), testValidator(validator, conf, value, expected)); } }); function testValidator(validator, conf, value, expected) { return function () { var validationModel = { queries: { value: {} } }; validationModel.queries.value[validator] = conf; var req = { query: {value: value} }; var validationResult = index.validation.process(validationModel, req, options); validationResult.length.should.equal(0); req.query.value.should.deepEqual(expected); } } }); describe('option: validatorModels object', function () { var validationPlugin = index.validationPlugin({ errorsAsArray: true, validatorModels: { isDecimal: Number, isBoolean: function (val) { return val === 'true'; } } }); var validationModel = { queries: { decimal: {isDecimal: true}, flag: {isBoolean: true}, int: {isInt: true} } }; it('should apply validatorModels', function () { validationReq.route = { validation: validationModel }; validationPlugin(validationReq, {}, function () { validationReq.query.decimal.should.equal(234.56); validationReq.query.flag.should.equal(true); validationReq.query.int.should.equal('123'); }); }); }); describe('option: validatorModels array', function () { var validationPlugin = index.validationPlugin({ errorsAsArray: true, validatorModels: [{ isDecimal: Number }, { isBoolean: function (val) { return val === 'true'; } }] }); var validationModel = { queries: { decimal: {isDecimal: true}, flag: {isBoolean: true}, int: {isInt: true} } }; it('should apply validatorModels', function () { validationReq.route = { validation: validationModel }; validationPlugin(validationReq, {}, function () { validationReq.query.decimal.should.equal(234.56); validationReq.query.flag.should.equal(true); validationReq.query.int.should.equal('123'); }); }); }); describe("not specified", function () { it('if no validatorModels, should keep original value', function () { var validationModel = { resources: { num: {isDecimal: true} } }; var validationResult = index.validation.process(validationModel, validationReq, {errorsAsArray: true}); validationResult.length.should.equal(0); validationReq.params.num.should.equal('-123.5'); }); it('if validatorModels, should use model', function () { var validationModel = { resources: { num: {isDecimal: true} } }; var validationResult = index.validation.process(validationModel, validationReq, { errorsAsArray: true, validatorModels: {isDecimal: Number} }); validationResult.length.should.equal(0); validationReq.params.num.should.equal(-123.5); }); }); describe("when validation fails", function () { it('should keep original value', function () { var validationModel = { resources: { num: {isNatural: true, model: Number} } }; var validationResult = index.validation.process(validationModel, validationReq, {errorsAsArray: true}); validationResult.length.should.equal(1); validationReq.params.num.should.equal('-123.5'); }); }); describe("when validation passes", function () { it('should use model value', function () { function DateModel(value) { return new Date(Number(value) || value); } var validationModel = { resources: { num: {model: Number, isFloat: true} }, queries: { flag: {model: Boolean}, scores: { isArray: { element: {model: Number} } } }, content: { from: {model: DateModel}, to: {model: DateModel}, ts: {model: DateModel}, dict: { isDictionary: { key: { model: function(s) { return s.toLowerCase(); }}, value: { model: function(s) { return s.toUpperCase(); }} } } } }; // Keys should become lower case var expectedDictionaryKeys = _.map(_.keys(validationReq.body.dict), function(s) { return s.toLowerCase(); }); // Values should become upper case var expectedDictionaryValues = _.map(_.values(validationReq.body.dict), function(s) { return s.toUpperCase(); }); var validationResult = index.validation.process(validationModel, validationReq, { errorsAsArray: true, validatorModels: { isFloat: function () { throw new Error("Should not be called"); } } }); validationResult.length.should.equal(0); validationReq.params.num.should.equal(-123.5); validationReq.query.flag.should.equal(true); validationReq.query.scores.should.deepEqual([1, 2, 100]); validationReq.body.from.should.deepEqual(timeStamp); validationReq.body.to.should.deepEqual(timeStamp); validationReq.body.ts.should.deepEqual(timeStamp); _.keys(validationReq.body.dict).should.deepEqual(expectedDictionaryKeys); _.values(validationReq.body.dict).should.deepEqual(expectedDictionaryValues); }); }); });