UNPKG

zater-cep

Version:

ZAter cep correios e via cep

1,693 lines (1,317 loc) 49.5 kB
// Load modules var Lab = require('lab'); var Code = require('code'); var Joi = require('../lib'); var Helper = require('./helper'); // Declare internals var internals = {}; // Test shortcuts var lab = exports.lab = Lab.script(); var describe = lab.describe; var it = lab.it; var expect = Code.expect; describe('Joi', function () { it('validates object', function (done) { var schema = Joi.object({ a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }).without('a', 'none'); var obj = { a: 1, b: 'a', c: 'joe@example.com' }; schema.validate(obj, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('keeps schema immutable', function (done) { var a = Joi.string(); var b = a.valid('b'); Helper.validate(a, [ ['a', true], ['b', true], [5, false] ], function () { Helper.validate(b, [ ['a', false], ['b', true], [5, false] ], done); }); }); it('validates null', function (done) { Joi.string().validate(null, function (err, value) { expect(err).to.exist(); expect(err.annotate()).to.equal('{\n \u001b[41m\"value\"\u001b[0m\u001b[31m [1]: -- missing --\u001b[0m\n}\n\u001b[31m\n[1] "value" must be a string\u001b[0m'); done(); }); }); it('validates null schema', function (done) { Helper.validate(null, [ ['a', false], [null, true] ], done); }); it('validates number literal', function (done) { Helper.validate(5, [ [6, false], [5, true] ], done); }); it('validates string literal', function (done) { Helper.validate('5', [ ['6', false], ['5', true] ], done); }); it('validates boolean literal', function (done) { Helper.validate(true, [ [false, false], [true, true] ], done); }); it('validates date literal', function (done) { var now = Date.now(); Helper.validate(new Date(now), [ [new Date(now), true], [now, true], [now * 2, false] ], done); }); it('validates complex literal', function (done) { var schema = ['key', 5, { a: true, b: [/^a/, 'boom'] }]; Helper.validate(schema, [ ['key', true], [5, true], ['other', false], [6, false], [{ c: 5 }, false], [{}, true], [{ b: 'abc' }, true], [{ a: true, b: 'boom' }, true], [{ a: 5, b: 'a' }, false] ], done); }); it('validates a compiled complex literal', function (done) { var schema = Joi.compile(['key', 5, { a: true, b: [/^a/, 'boom'] }]); Helper.validate(schema, [ ['key', true], [5, true], ['other', false], [6, false], [{ c: 5 }, false], [{}, true], [{ b: 'abc' }, true], [{ a: true, b: 'boom' }, true], [{ a: 5, b: 'a' }, false] ], done); }); it('validates regex directly', function (done) { Joi.compile(/^5$/).validate('5', function (err, value) { expect(err).to.not.exist(); Joi.compile(/.{2}/).validate('6', function (err2, value2) { expect(err2).to.exist(); done(); }); }); }); it('validated with', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string() }).with('txt', 'upc'); Joi.validate({ txt: 'a' }, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"txt" missing required peer "upc"'); Helper.validate(schema, [ [{ upc: 'test' }, true], [{ txt: 'test' }, false], [{ txt: 'test', upc: null }, false], [{ txt: 'test', upc: '' }, false], [{ txt: 'test', upc: undefined }, false], [{ txt: 'test', upc: 'test' }, true] ], done); }); }); it('validated without', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string() }).without('txt', 'upc'); Joi.validate({ txt: 'a', upc: 'b' }, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"txt" conflict with forbidden peer "upc"'); Helper.validate(schema, [ [{ upc: 'test' }, true], [{ txt: 'test' }, true], [{ txt: 'test', upc: null }, false], [{ txt: 'test', upc: '' }, false], [{ txt: 'test', upc: undefined }, true], [{ txt: 'test', upc: 'test' }, false] ], done); }); }); it('validates xor', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string() }).xor('txt', 'upc'); Joi.validate({}, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"value" must contain at least one of [txt, upc]'); Helper.validate(schema, [ [{ upc: null }, false], [{ upc: 'test' }, true], [{ txt: null }, false], [{ txt: 'test' }, true], [{ txt: 'test', upc: null }, false], [{ txt: 'test', upc: '' }, false], [{ txt: '', upc: 'test' }, false], [{ txt: null, upc: 'test' }, false], [{ txt: undefined, upc: 'test' }, true], [{ txt: 'test', upc: undefined }, true], [{ txt: 'test', upc: '' }, false], [{ txt: 'test', upc: null }, false], [{ txt: '', upc: undefined }, false], [{ txt: '', upc: '' }, false], [{ txt: 'test', upc: 'test' }, false] ], done); }); }); it('validates multiple peers xor', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string(), code: Joi.string() }).xor('txt', 'upc', 'code'); Helper.validate(schema, [ [{ upc: 'test' }, true], [{ txt: 'test' }, true], [{}, false] ], done); }); it('validates xor with number types', function (done) { var schema = Joi.object({ code: Joi.number(), upc: Joi.number() }).xor('code', 'upc'); Helper.validate(schema, [ [{ upc: 123 }, true], [{ code: 456 }, true], [{ code: 456, upc: 123 }, false], [{}, false] ], done); }); it('validates xor when empty value of peer allowed', function (done) { var schema = Joi.object({ code: Joi.string(), upc: Joi.string().allow('') }).xor('code', 'upc'); Helper.validate(schema, [ [{ upc: '' }, true], [{ upc: '123' }, true], [{ code: '456' }, true], [{ code: '456', upc: '' }, false], [{}, false] ], done); }); it('validates or', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string().allow(null, ''), code: Joi.number() }).or('txt', 'upc', 'code'); Joi.validate({}, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"value" must contain at least one of [txt, upc, code]'); Helper.validate(schema, [ [{ upc: null }, true], [{ upc: 'test' }, true], [{ txt: null }, false], [{ txt: 'test' }, true], [{ code: null }, false], [{ code: 123 }, true], [{ txt: 'test', upc: null }, true], [{ txt: 'test', upc: '' }, true], [{ txt: '', upc: 'test' }, false], [{ txt: null, upc: 'test' }, false], [{ txt: undefined, upc: 'test' }, true], [{ txt: 'test', upc: undefined }, true], [{ txt: 'test', upc: '' }, true], [{ txt: 'test', upc: null }, true], [{ txt: '', upc: undefined }, false], [{ txt: '', upc: undefined, code: 999 }, false], [{ txt: '', upc: undefined, code: undefined }, false], [{ txt: '', upc: '' }, false], [{ txt: 'test', upc: 'test' }, true], [{ txt: 'test', upc: 'test', code: 322 }, true] ], done); }); }); it('validates and', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string().allow(null, ''), code: Joi.number() }).and('txt', 'upc', 'code'); Joi.validate({ txt: 'x' }, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"value" contains [txt] without its required peers [upc, code]'); Helper.validate(schema, [ [{}, true], [{ upc: null }, false], [{ upc: 'test' }, false], [{ txt: null }, false], [{ txt: 'test' }, false], [{ code: null }, false], [{ code: 123 }, false], [{ txt: 'test', upc: null }, false], [{ txt: 'test', upc: '' }, false], [{ txt: '', upc: 'test' }, false], [{ txt: null, upc: 'test' }, false], [{ txt: undefined, upc: 'test' }, false], [{ txt: 'test', upc: undefined }, false], [{ txt: 'test', upc: '' }, false], [{ txt: 'test', upc: null }, false], [{ txt: '', upc: undefined }, false], [{ txt: '', upc: undefined, code: 999 }, false], [{ txt: '', upc: undefined, code: undefined }, false], [{ txt: '', upc: '' }, false], [{ txt: 'test', upc: 'test' }, false], [{ txt: 'test', upc: 'test', code: 322 }, true], [{ txt: 'test', upc: null, code: 322 }, true] ], done); }); }); it('validates nand()', function (done) { var schema = Joi.object({ txt: Joi.string(), upc: Joi.string().allow(null, ''), code: Joi.number() }).nand('txt', 'upc', 'code'); Joi.validate({ txt: 'x', upc: 'y', code: 123 }, schema, { abortEarly: false }, function (err, value) { expect(err.message).to.equal('"txt" must not exist simultaneously with [upc, code]'); Helper.validate(schema, [ [{}, true], [{ upc: null }, true], [{ upc: 'test' }, true], [{ txt: 'test' }, true], [{ code: 123 }, true], [{ txt: 'test', upc: null }, true], [{ txt: 'test', upc: '' }, true], [{ txt: undefined, upc: 'test' }, true], [{ txt: 'test', upc: undefined }, true], [{ txt: 'test', upc: '' }, true], [{ txt: 'test', upc: null }, true], [{ txt: 'test', upc: undefined, code: 999 }, true], [{ txt: 'test', upc: 'test' }, true], [{ txt: 'test', upc: 'test', code: 322 }, false], [{ txt: 'test', upc: null, code: 322 }, false] ], done); }); }); it('validates an array of valid types', function (done) { var schema = Joi.object({ auth: [ Joi.object({ mode: Joi.string().valid('required', 'optional', 'try').allow(null) }).allow(null), Joi.string(), Joi.boolean() ] }); schema.validate({ auth: { mode: 'none' } }, function (err, value) { expect(err).to.exist(); expect(err.message).to.equal('child "auth" fails because [child "mode" fails because ["mode" must be one of [required, optional, try, null]], "auth" must be a string, "auth" must be a boolean]'); Helper.validate(schema, [ [{ auth: { mode: 'try' } }, true], [{ something: undefined }, false], [{ auth: { something: undefined } }, false], [{ auth: null }, true], [{ auth: undefined }, true], [{}, true], [{ auth: true }, true], [{ auth: 123 }, false] ], done); }); }); it('validates alternatives', function (done) { var schema = Joi.object({ auth: Joi.alternatives( Joi.object({ mode: Joi.string().valid('required', 'optional', 'try').allow(null) }).allow(null), Joi.string(), Joi.boolean() ) }); schema.validate({ auth: { mode: 'none' } }, function (err, value) { expect(err).to.exist(); expect(err.message).to.equal('child "auth" fails because [child "mode" fails because ["mode" must be one of [required, optional, try, null]], "auth" must be a string, "auth" must be a boolean]'); Helper.validate(schema, [ [{ auth: { mode: 'try' } }, true], [{ something: undefined }, false], [{ auth: { something: undefined } }, false], [{ auth: null }, true], [{ auth: undefined }, true], [{}, true], [{ auth: true }, true], [{ auth: 123 }, false] ], done); }); }); it('validates required alternatives', function (done) { var schema = { a: Joi.alternatives( Joi.string().required(), Joi.boolean().required() ) }; Helper.validate(schema, [ [{ a: null }, false], [{ a: undefined }, true], [{}, true], [{ a: true }, true], [{ a: 'true' }, true], [{ a: 123 }, false], [{ a: { c: 1 } }, false], [{ b: undefined }, false] ], done); }); it('validates required [] alternatives', function (done) { var schema = { a: [ Joi.string().required(), Joi.boolean().required() ] }; Helper.validate(schema, [ [{ a: null }, false], [{ a: undefined }, true], [{}, true], [{ a: true }, true], [{ a: 'true' }, true], [{ a: 123 }, false], [{ a: { c: 1 } }, false], [{ b: undefined }, false] ], done); }); it('validates an array of string with valid', function (done) { var schema = { brand: Joi.array().items(Joi.string().valid('amex', 'visa')) }; Helper.validate(schema, [ [{ brand: ['amex'] }, true], [{ brand: ['visa', 'mc'] }, false] ], done); }); it('validates pre and post convert value', function (done) { var schema = Joi.number().valid(5); Helper.validate(schema, [ [5, true], ['5', true] ], done); }); it('does not change object when validation fails', function (done) { var schema = Joi.object({ a: Joi.number().valid(2) }); var obj = { a: '5' }; schema.validate(obj, function (err, value) { expect(err).to.exist(); expect(value.a).to.equal('5'); done(); }); }); it('does not set optional keys when missing', function (done) { var schema = Joi.object({ a: Joi.number() }); var obj = {}; schema.validate(obj, function (err, value) { expect(err).to.not.exist(); expect(value.hasOwnProperty('a')).to.equal(false); done(); }); }); it('invalidates pre and post convert value', function (done) { var schema = Joi.number().invalid(5); Helper.validate(schema, [ [5, false], ['5', false] ], done); }); it('invalidates missing peers', function (done) { var schema = Joi.object({ username: Joi.string(), password: Joi.string() }).with('username', 'password').without('password', 'access_token'); schema.validate({ username: 'bob' }, function (err, value) { expect(err).to.exist(); done(); }); }); it('validates config where the root item is a joi type', function (done) { Joi.boolean().allow(null).validate(true, function (err, value) { expect(err).to.be.null(); Joi.object().validate({ auth: { mode: 'try' } }, function (err2, value2) { expect(err2).to.be.null(); Joi.object().validate(true, function (err3, value3) { expect(err3.message).to.contain('"value" must be an object'); Joi.string().validate(true, function (err4, value4) { expect(err4.message).to.contain('"value" must be a string'); Joi.string().email().validate('test@test.com', function (err5, value5) { expect(err5).to.be.null(); Joi.object({ param: Joi.string().required() }).validate({ param: 'item' }, function (err6, value6) { expect(err6).to.be.null(); done(); }); }); }); }); }); }); }); it('converts string to number', function (done) { var schema = Joi.object({ a: Joi.number() }); var input = { a: '5' }; schema.validate(input, function (err, value) { expect(err).to.be.null(); expect(value.a).to.equal(5); expect(input.a).to.equal('5'); done(); }); }); it('allows unknown keys in objects if no schema was given', function (done) { Joi.object().validate({ foo: 'bar' }, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('fails on unknown keys in objects if a schema was given', function (done) { Joi.object({}).validate({ foo: 'bar' }, function (err, value) { expect(err).to.exist(); expect(err.message).to.equal('"foo" is not allowed'); Joi.compile({}).validate({ foo: 'bar' }, function (err2, value2) { expect(err2).to.exist(); expect(err2.message).to.equal('"foo" is not allowed'); Joi.compile({ other: Joi.number() }).validate({ foo: 'bar' }, function (err3, value3) { expect(err3).to.exist(); expect(err3.message).to.equal('"foo" is not allowed'); done(); }); }); }); }); it('validates an unknown option', function (done) { var config = { auth: Joi.object({ mode: Joi.string().valid('required', 'optional', 'try').allow(null) }).allow(null) }; Joi.compile(config).validate({ auth: { unknown: true } }, function (err, value) { expect(err).to.not.be.null(); expect(err.message).to.contain('"unknown" is not allowed'); Joi.compile(config).validate({ something: false }, function (err2, value2) { expect(err2).to.not.be.null(); expect(err2.message).to.contain('"something" is not allowed'); done(); }); }); }); it('validates required key with multiple options', function (done) { var config = { module: Joi.alternatives([ Joi.object({ compile: Joi.func().required(), execute: Joi.func() }), Joi.string() ]).required() }; Joi.compile(config).validate({}, function (err, value) { expect(err).to.exist(); expect(err.message).to.contain('"module" is required'); Joi.compile(config).validate({ module: 'test' }, function (err2, value2) { expect(err2).to.be.null(); Joi.compile(config).validate({ module: {} }, function (err3, value3) { expect(err3).to.not.be.null(); expect(err3.message).to.contain('"compile" is required'); expect(err3.message).to.contain('"module" must be a string'); Joi.compile(config).validate({ module: { compile: function () { } } }, function (err4, value4) { expect(err4).to.be.null(); done(); }); }); }); }); }); it('validates key with required alternatives', function (done) { var config = { module: Joi.alt().try( Joi.object({ compile: Joi.func().required(), execute: Joi.func() }).required(), Joi.string().required() ) }; Joi.compile(config).validate({}, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('validates required key with alternatives', function (done) { var config = { module: Joi.alt().try( Joi.object({ compile: Joi.func().required(), execute: Joi.func() }), Joi.string() ).required() }; Joi.compile(config).validate({}, function (err, value) { expect(err).to.exist(); expect(err.message).to.contain('"module" is required'); done(); }); }); it('does not require optional numbers', function (done) { var config = { position: Joi.number(), suggestion: Joi.string() }; Joi.compile(config).validate({ suggestion: 'something' }, function (err, value) { expect(err).to.be.null(); Joi.compile(config).validate({ position: 1 }, function (err2, value2) { expect(err2).to.be.null(); done(); }); }); }); it('does not require optional objects', function (done) { var config = { position: Joi.number(), suggestion: Joi.object() }; Joi.compile(config).validate({ suggestion: {} }, function (err, value) { expect(err).to.be.null(); Joi.compile(config).validate({ position: 1 }, function (err2, value2) { expect(err2).to.be.null(); done(); }); }); }); it('validates object successfully when config has an array of types', function (done) { var schema = { f: [Joi.number(), Joi.boolean()], g: [Joi.string(), Joi.object()] }; var obj = { f: true, g: 'test' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('validates object successfully when config allows for optional key and key is missing', function (done) { var schema = { h: Joi.number(), i: Joi.string(), j: Joi.object() }; var obj = { h: 12, i: 'test' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('fails validation', function (done) { var schema = { a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }; var obj = { a: 10, b: 'a', c: 'joe@example.com' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when the wrong types are supplied', function (done) { var schema = { a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }; var obj = { a: 'a', b: 'a', c: 'joe@example.com' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when missing a required parameter', function (done) { var obj = { c: 10 }; Joi.compile({ a: Joi.string().required() }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when missing a required parameter within an object config', function (done) { var obj = { a: {} }; Joi.compile({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when parameter is required to be an object but is given as string', function (done) { var obj = { a: 'a string' }; Joi.compile({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('validates when parameter is required to be an object and is given correctly as a json string', function (done) { var schema = { a: Joi.object({ b: Joi.string().required() }) }; var input = { a: '{"b":"string"}' }; Joi.validate(input, schema, function (err, value) { expect(err).to.not.exist(); expect(input.a).to.equal('{"b":"string"}'); expect(value.a.b).to.equal('string'); done(); }); }); it('fails validation when parameter is required to be an object but is given as a json string that is incorrect (number instead of string)', function (done) { var obj = { a: '{"b":2}' }; Joi.object({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when parameter is required to be an Array but is given as string', function (done) { var obj = { a: 'an array' }; Joi.object({ a: Joi.array() }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('validates when parameter is required to be an Array and is given correctly as a json string', function (done) { var obj = { a: '[1,2]' }; Joi.object({ a: Joi.array() }).validate(obj, function (err, value) { expect(err).to.be.null(); done(); }); }); it('fails validation when parameter is required to be an Array but is given as a json that is incorrect (object instead of array)', function (done) { var obj = { a: '{"b":2}' }; Joi.object({ a: Joi.object({ b: Joi.string().required() }) }).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when config is an array and fails', function (done) { var schema = { d: [Joi.string(), Joi.boolean()], e: [Joi.number(), Joi.object()] }; var obj = { d: 10, e: 'a' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation when config is an array and fails with extra keys', function (done) { var schema = { d: [Joi.string(), Joi.boolean()], e: [Joi.number(), Joi.object()] }; var obj = { a: 10, b: 'a' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('fails validation with extra keys', function (done) { var schema = { a: Joi.number() }; var obj = { a: 1, b: 'a' }; Joi.compile(schema).validate(obj, function (err, value) { expect(err).to.exist(); done(); }); }); it('validates missing optional key with string condition', function (done) { var schema = { key: Joi.string().alphanum(false).min(8) }; Joi.compile(schema).validate({}, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('validates with extra keys and remove them when stripUnknown is set', function (done) { var schema = { a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }; var obj = { a: 1, b: 'a', d: 'c' }; Joi.validate(obj, schema, { stripUnknown: true, allowUnknown: true }, function (err, value) { expect(err).to.be.null(); expect(value).to.deep.equal({ a: 1, b: 'a' }); done(); }); }); it('validates dependencies when stripUnknown is set', function (done) { var schema = Joi.object({ a: Joi.number(), b: Joi.string() }).and('a', 'b'); var obj = { a: 1, foo: 'bar' }; Joi.validate(obj, schema, { stripUnknown: true }, function (err, value) { expect(err).to.exist(); expect(err.message).to.equal('"value" contains [a] without its required peers [b]'); done(); }); }); it('fails to validate with incorrect property when asked to strip unkown keys without aborting early', function (done) { var schema = { a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }; var obj = { a: 1, b: 'f', d: 'c' }; Joi.validate(obj, schema, { stripUnknown: true, abortEarly: false }, function (err, value) { expect(err).to.exist(); done(); }); }); it('should pass validation with extra keys when allowUnknown is set', function (done) { var schema = { a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c'), c: Joi.string().email().optional() }; var obj = { a: 1, b: 'a', d: 'c' }; Joi.validate(obj, schema, { allowUnknown: true }, function (err, value) { expect(err).to.be.null(); expect(value).to.deep.equal({ a: 1, b: 'a', d: 'c' }); done(); }); }); it('should pass validation with extra keys set', function (done) { var localConfig = Joi.object({ a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c') }).options({ allowUnknown: true }); var obj = { a: 1, b: 'a', d: 'c' }; localConfig.validate(obj, function (err, value) { expect(err).to.be.null(); expect(value).to.deep.equal({ a: 1, b: 'a', d: 'c' }); localConfig.validate(value, function (err2, value2) { expect(err2).to.be.null(); expect(value2).to.deep.equal({ a: 1, b: 'a', d: 'c' }); done(); }); }); }); it('should pass validation with extra keys and remove them when skipExtraKeys is set locally', function (done) { var localConfig = Joi.object({ a: Joi.number().min(0).max(3), b: Joi.string().valid('a', 'b', 'c') }).options({ stripUnknown: true, allowUnknown: true }); var obj = { a: 1, b: 'a', d: 'c' }; localConfig.validate(obj, function (err, value) { expect(err).to.be.null(); expect(value).to.deep.equal({ a: 1, b: 'a' }); localConfig.validate(value, function (err2, value2) { expect(err2).to.be.null(); expect(value2).to.deep.equal({ a: 1, b: 'a' }); done(); }); }); }); it('should work when the skipFunctions setting is enabled', function (done) { var schema = Joi.object({ username: Joi.string() }).options({ skipFunctions: true }); var input = { username: 'test', func: function () { } }; Joi.validate(input, schema, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('should work when the skipFunctions setting is disabled', function (done) { var schema = { username: Joi.string() }; var input = { username: 'test', func: function () { } }; Joi.validate(input, schema, { skipFunctions: false }, function (err, value) { expect(err).to.exist(); expect(err.message).to.contain('"func" is not allowed'); done(); }); }); it('should not convert values when convert is false', function (done) { var schema = { arr: Joi.array().items(Joi.string()) }; var input = { arr: 'foo' }; Joi.validate(input, schema, { convert: false }, function (err, value) { expect(err).to.exist(); done(); }); }); it('full errors when abortEarly is false', function (done) { var schema = { a: Joi.string(), b: Joi.string() }; var input = { a: 1, b: 2 }; Joi.validate(input, schema, function (errOne, valueOne) { Joi.validate(input, schema, { abortEarly: false }, function (errFull, valueFull) { expect(errOne).to.exist(); expect(errFull).to.exist(); expect(errFull.details.length).to.be.greaterThan(errOne.details.length); done(); }); }); }); it('errors multiple times when abortEarly is false in a complex object', function (done) { var schema = Joi.object({ test: Joi.array().items(Joi.object().keys({ foo: Joi.string().required().max(3), bar: Joi.string().max(5) })), test2: Joi.object({ test3: Joi.array().items(Joi.object().keys({ foo: Joi.string().required().max(3), bar: Joi.string().max(5), baz: Joi.object({ test4: Joi.array().items(Joi.object().keys({ foo: Joi.string().required().max(3), bar: Joi.string().max(5) })) }) })) }) }); var input = { test: [{ foo: 'test1', bar: 'testfailed' }], test2: { test3: [{ foo: '123' }, { foo: 'test1', bar: 'testfailed' }, { foo: '123', baz: { test4: [{ foo: 'test1', baz: '123' }] } }] } }; Joi.validate(input, schema, { abortEarly: false }, function (err, value) { expect(err).to.exist(); expect(err.details).to.have.length(6); expect(err.details).to.deep.equal([{ message: '"foo" length must be less than or equal to 3 characters long', path: 'test.0.foo', type: 'string.max', context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } }, { message: '"bar" length must be less than or equal to 5 characters long', path: 'test.0.bar', type: 'string.max', context: { limit: 5, value: 'testfailed', key: 'bar', encoding: undefined } }, { message: '"foo" length must be less than or equal to 3 characters long', path: 'test2.test3.1.foo', type: 'string.max', context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } }, { message: '"bar" length must be less than or equal to 5 characters long', path: 'test2.test3.1.bar', type: 'string.max', context: { limit: 5, value: 'testfailed', key: 'bar', encoding: undefined } }, { message: '"foo" length must be less than or equal to 3 characters long', path: 'test2.test3.2.baz.test4.0.foo', type: 'string.max', context: { limit: 3, value: 'test1', key: 'foo', encoding: undefined } }, { message: '"baz" is not allowed', path: 'test2.test3.2.baz.test4.0.baz', type: 'object.allowUnknown', context: { key: 'baz' } }]); done(); }); }); it('validates using the root any object', function (done) { var any = Joi; any.validate('abc', function (err, value) { expect(err).to.not.exist(); done(); }); }); it('validates using the root any object (no callback)', function (done) { var any = Joi; var result = any.validate('abc'); expect(result.error).to.not.exist(); expect(result.value).to.equal('abc'); done(); }); it('accepts no options', function (done) { Joi.validate('test', Joi.string(), function (err, value) { expect(err).to.not.exist(); done(); }); }); it('accepts no options (no callback)', function (done) { var result = Joi.validate('test', Joi.string()); expect(result.error).to.not.exist(); expect(result.value).to.equal('test'); done(); }); it('accepts options', function (done) { Joi.validate('5', Joi.number(), { convert: false }, function (err, value) { expect(err).to.exist(); done(); }); }); it('accepts options (no callback)', function (done) { var result = Joi.validate('5', Joi.number(), { convert: false }); expect(result.error).to.exist(); done(); }); it('accepts null options', function (done) { Joi.validate('test', Joi.string(), null, function (err, value) { expect(err).to.not.exist(); done(); }); }); it('accepts undefined options', function (done) { Joi.validate('test', Joi.string(), undefined, function (err, value) { expect(err).to.not.exist(); done(); }); }); describe('#describe', function () { var defaultFn = function () { return 'test'; }; defaultFn.description = 'testing'; var defaultDescribedFn = function () { return 'test'; }; var defaultRef = Joi.ref('xor'); var schema = Joi.object({ sub: { email: Joi.string().email(), date: Joi.date(), child: Joi.object({ alphanum: Joi.string().alphanum() }) }, min: [Joi.number(), Joi.string().min(3)], max: Joi.string().max(3), required: Joi.string().required(), xor: Joi.string(), renamed: Joi.string().valid('456'), notEmpty: Joi.string().required().description('a').notes('b').tags('c'), empty: Joi.string().empty('').strip(), defaultRef: Joi.string().default(defaultRef, 'not here'), defaultFn: Joi.string().default(defaultFn, 'not here'), defaultDescribedFn: Joi.string().default(defaultDescribedFn, 'described test') }).rename('renamed', 'required').without('required', 'xor').without('xor', 'required'); var result = { type: 'object', children: { sub: { type: 'object', children: { email: { type: 'string', invalids: [''], rules: [{ name: 'email' }] }, date: { type: 'date' }, child: { type: 'object', children: { alphanum: { type: 'string', invalids: [''], rules: [{ name: 'alphanum' }] } } } } }, min: { type: 'alternatives', alternatives: [ { type: 'number', invalids: [Infinity, -Infinity] }, { type: 'string', invalids: [''], rules: [{ name: 'min', arg: 3 }] } ] }, max: { type: 'string', invalids: [''], rules: [{ name: 'max', arg: 3 }] }, required: { type: 'string', flags: { presence: 'required' }, invalids: [''] }, xor: { type: 'string', invalids: [''] }, renamed: { type: 'string', flags: { allowOnly: true }, valids: ['456'], invalids: [''] }, notEmpty: { type: 'string', flags: { presence: 'required' }, description: 'a', notes: ['b'], tags: ['c'], invalids: [''] }, empty: { type: 'string', flags: { empty: { type: 'string', flags: { allowOnly: true }, valids: [''] }, strip: true }, invalids: [''] }, defaultRef: { type: 'string', flags: { default: defaultRef }, invalids: [''] }, defaultFn: { type: 'string', flags: { default: defaultFn }, invalids: [''] }, defaultDescribedFn: { type: 'string', flags: { default: defaultDescribedFn }, invalids: [''] } }, dependencies: [ { type: 'without', key: 'required', peers: ['xor'] }, { type: 'without', key: 'xor', peers: ['required'] } ] }; it('describes schema (direct)', function (done) { var description = schema.describe(); expect(description).to.deep.equal(result); expect(description.children.defaultRef.flags.default.description).to.not.exist(); expect(description.children.defaultFn.flags.default.description).to.equal('testing'); expect(description.children.defaultDescribedFn.flags.default.description).to.equal('described test'); done(); }); it('describes schema (root)', function (done) { var description = Joi.describe(schema); expect(description).to.deep.equal(result); done(); }); it('describes schema (any)', function (done) { var any = Joi; var description = any.describe(); expect(description).to.deep.equal({ type: 'any' }); done(); }); it('describes schema without invalids', function (done) { var description = Joi.allow(null).describe(); expect(description.invalids).to.not.exist(); done(); }); }); describe('#assert', function () { it('does not have a return value', function (done) { var result; expect(function () { result = Joi.assert('4', Joi.number()); }).to.not.throw(); expect(result).to.not.exist(); done(); }); }); describe('#attempt', function () { it('throws on invalid value', function (done) { expect(function () { Joi.attempt('x', Joi.number()); }).to.throw('"x"\n\u001b[31m\n[1] "value" must be a number\u001b[0m'); done(); }); it('does not throw on valid value', function (done) { expect(function () { Joi.attempt('4', Joi.number()); }).to.not.throw(); done(); }); it('returns validated structure', function (done) { var valid; expect(function () { valid = Joi.attempt('4', Joi.number()); }).to.not.throw(); expect(valid).to.equal(4); done(); }); it('throws on invalid value with message', function (done) { expect(function () { Joi.attempt('x', Joi.number(), 'the reason is'); }).to.throw('the reason is "x"\n\u001b[31m\n[1] "value" must be a number\u001b[0m'); done(); }); it('throws on invalid value with message as error', function (done) { expect(function () { Joi.attempt('x', Joi.number(), new Error('invalid value')); }).to.throw('invalid value'); done(); }); }); describe('#compile', function () { it('throws an error on invalid value', function (done) { expect(function () { Joi.compile(undefined); }).to.throw(Error, 'Invalid schema content: '); done(); }); it('shows path to errors in object', function (done) { var schema = { a: { b: { c: { d: undefined } } } }; expect(function () { Joi.compile(schema); }).to.throw(Error, 'Invalid schema content: (a.b.c.d)'); done(); }); }); });