UNPKG

zater-cep

Version:

ZAter cep correios e via cep

1,363 lines (1,066 loc) 117 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('string', function () { it('fails on boolean', function (done) { var schema = Joi.string(); Helper.validate(schema, [ [true, false], [false, false] ], done); }); describe('#valid', function () { it('should throw error on input not matching type', function (done) { expect(function () { Joi.string().valid({}); }).to.throw(); done(); }); it('should not throw on input matching type', function (done) { expect(function () { Joi.string().valid('joi'); }).to.not.throw(); done(); }); it('validates case sensitive values', function (done) { Helper.validate(Joi.string().valid('a', 'b'), [ ['a', true], ['b', true], ['A', false], ['B', false] ], done); }); it('validates case insensitive values', function (done) { Helper.validate(Joi.string().valid('a', 'b').insensitive(), [ ['a', true], ['b', true], ['A', true], ['B', true], [4, false] ], done); }); it('validates case insensitive values with non-strings', function (done) { Helper.validate(Joi.string().valid('a', 'b', 5).insensitive(), [ ['a', true], ['b', true], ['A', true], ['B', true], [4, false], [5, true] ], done); }); }); describe('#invalid', function () { it('should throw error on input not matching type', function (done) { expect(function () { Joi.string().invalid({}); }).to.throw(); done(); }); it('should not throw on input matching type', function (done) { expect(function () { Joi.string().invalid('joi'); }).to.not.throw(); done(); }); it('invalidates case sensitive values', function (done) { Helper.validate(Joi.string().invalid('a', 'b'), [ ['a', false], ['b', false], ['A', true], ['B', true] ], done); }); it('invalidates case insensitive values', function (done) { Helper.validate(Joi.string().invalid('a', 'b').insensitive(), [ ['a', false], ['b', false], ['A', false], ['B', false] ], done); }); }); describe('#min', function () { it('throws when limit is not a number', function (done) { expect(function () { Joi.string().min('a'); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not an integer', function (done) { expect(function () { Joi.string().min(1.2); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not a positive integer', function (done) { expect(function () { Joi.string().min(-1); }).to.throw('limit must be a positive integer or reference'); done(); }); it('enforces a limit using byte count', function (done) { var schema = Joi.string().min(2, 'utf8'); Helper.validate(schema, [ ['\u00bd', true], ['a', false] ], done); }); it('accepts references as min length', function (done) { var schema = Joi.object({ a: Joi.number(), b: Joi.string().min(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 2, b: '\u00bd' }, true], [{ a: 2, b: 'a' }, false], [{ a: 2, b: 'a' }, false, null, 'child "b" fails because ["b" length must be at least 2 characters long]'] ], done); }); it('accepts context references as min length', function (done) { var schema = Joi.object({ b: Joi.string().min(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, true, { context: { a: 2 } }], [{ b: 'a' }, false, { context: { a: 2 } }], [{ b: 'a' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be at least 2 characters long]'] ], done); }); it('errors if reference is not a number', function (done) { var schema = Joi.object({ a: Joi.any(), b: Joi.string().min(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); it('errors if context reference is not a number', function (done) { var schema = Joi.object({ b: Joi.string().min(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); }); describe('#max', function () { it('throws when limit is not a number', function (done) { expect(function () { Joi.string().max('a'); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not an integer', function (done) { expect(function () { Joi.string().max(1.2); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not a positive integer', function (done) { expect(function () { Joi.string().max(-1); }).to.throw('limit must be a positive integer or reference'); done(); }); it('enforces a limit using byte count', function (done) { var schema = Joi.string().max(1, 'utf8'); Helper.validate(schema, [ ['\u00bd', false], ['a', true] ], done); }); it('accepts references as min length', function (done) { var schema = Joi.object({ a: Joi.number(), b: Joi.string().max(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 2, b: '\u00bd' }, true], [{ a: 2, b: 'three' }, false], [{ a: 2, b: 'three' }, false, null, 'child "b" fails because ["b" length must be less than or equal to 2 characters long]'] ], done); }); it('accepts context references as min length', function (done) { var schema = Joi.object({ b: Joi.string().max(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, true, { context: { a: 2 } }], [{ b: 'three' }, false, { context: { a: 2 } }], [{ b: 'three' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be less than or equal to 2 characters long]'] ], done); }); it('errors if reference is not a number', function (done) { var schema = Joi.object({ a: Joi.any(), b: Joi.string().max(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); it('errors if context reference is not a number', function (done) { var schema = Joi.object({ b: Joi.string().max(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); }); describe('#creditCard', function () { it('should validate credit card', function (done) { var t = Joi.string().creditCard(); t.validate('4111111111111112', function (err, value) { expect(err.message).to.equal('"value" must be a credit card'); Helper.validate(t, [ ['378734493671000', true], // american express ['371449635398431', true], // american express ['378282246310005', true], // american express ['341111111111111', true], // american express ['5610591081018250', true], // australian bank ['5019717010103742', true], // dankort pbs ['38520000023237', true], // diners club ['30569309025904', true], // diners club ['6011000990139424', true], // discover ['6011111111111117', true], // discover ['6011601160116611', true], // discover ['3566002020360505', true], // jbc ['3530111333300000', true], // jbc ['5105105105105100', true], // mastercard ['5555555555554444', true], // mastercard ['5431111111111111', true], // mastercard ['6331101999990016', true], // switch/solo paymentech ['4222222222222', true], // visa ['4012888888881881', true], // visa ['4111111111111111', true], // visa ['4111111111111112', false], [null, false] ], done); }); }); }); describe('#length', function () { it('throws when limit is not a number', function (done) { expect(function () { Joi.string().length('a'); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not an integer', function (done) { expect(function () { Joi.string().length(1.2); }).to.throw('limit must be a positive integer or reference'); done(); }); it('throws when limit is not a positive integer', function (done) { expect(function () { Joi.string().length(-42); }).to.throw('limit must be a positive integer or reference'); done(); }); it('enforces a limit using byte count', function (done) { var schema = Joi.string().length(2, 'utf8'); Helper.validate(schema, [ ['\u00bd', true], ['a', false] ], done); }); it('accepts references as length', function (done) { var schema = Joi.object({ a: Joi.number(), b: Joi.string().length(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 2, b: '\u00bd' }, true], [{ a: 2, b: 'a' }, false], [{ a: 2, b: 'a' }, false, null, 'child "b" fails because ["b" length must be 2 characters long]'] ], done); }); it('accepts context references as length', function (done) { var schema = Joi.object({ b: Joi.string().length(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, true, { context: { a: 2 } }], [{ b: 'a' }, false, { context: { a: 2 } }], [{ b: 'a' }, false, { context: { a: 2 } }, 'child "b" fails because ["b" length must be 2 characters long]'] ], done); }); it('errors if reference is not a number', function (done) { var schema = Joi.object({ a: Joi.any(), b: Joi.string().length(Joi.ref('a'), 'utf8') }); Helper.validate(schema, [ [{ a: 'Hi there', b: '\u00bd' }, false, null, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); it('errors if context reference is not a number', function (done) { var schema = Joi.object({ a: Joi.any(), b: Joi.string().length(Joi.ref('$a'), 'utf8') }); Helper.validate(schema, [ [{ b: '\u00bd' }, false, { context: { a: 'Hi there' } }, 'child "b" fails because ["b" references "a" which is not a number]'] ], done); }); }); describe('#email', function () { it('throws when options are not an object', function (done) { expect(function () { var emailOptions = true; Joi.string().email(emailOptions); }).to.throw('email options must be an object'); done(); }); it('throws when checkDNS option is enabled', function (done) { expect(function () { var emailOptions = { checkDNS: true }; Joi.string().email(emailOptions); }).to.throw('checkDNS option is not supported'); done(); }); it('throws when tldWhitelist is not an array or object', function (done) { expect(function () { var emailOptions = { tldWhitelist: 'domain.tld' }; Joi.string().email(emailOptions); }).to.throw('tldWhitelist must be an array or object'); done(); }); it('throws when minDomainAtoms is not a number', function (done) { expect(function () { var emailOptions = { minDomainAtoms: '1' }; Joi.string().email(emailOptions); }).to.throw('minDomainAtoms must be a positive integer'); done(); }); it('throws when minDomainAtoms is not an integer', function (done) { expect(function () { var emailOptions = { minDomainAtoms: 1.2 }; Joi.string().email(emailOptions); }).to.throw('minDomainAtoms must be a positive integer'); done(); }); it('throws when minDomainAtoms is not positive', function (done) { expect(function () { var emailOptions = { minDomainAtoms: 0 }; Joi.string().email(emailOptions); }).to.throw('minDomainAtoms must be a positive integer'); done(); }); it('does not throw when minDomainAtoms is a positive integer', function (done) { expect(function () { var emailOptions = { minDomainAtoms: 1 }; Joi.string().email(emailOptions); }).to.not.throw(); done(); }); it('throws when errorLevel is not an integer or boolean', function (done) { expect(function () { var emailOptions = { errorLevel: 1.2 }; Joi.string().email(emailOptions); }).to.throw('errorLevel must be a non-negative integer or boolean'); done(); }); it('throws when errorLevel is negative', function (done) { expect(function () { var emailOptions = { errorLevel: -1 }; Joi.string().email(emailOptions); }).to.throw('errorLevel must be a non-negative integer or boolean'); done(); }); it('does not throw when errorLevel is 0', function (done) { expect(function () { var emailOptions = { errorLevel: 0 }; Joi.string().email(emailOptions); }).to.not.throw(); done(); }); }); describe('#hostname', function () { it('validates hostnames', function (done) { var schema = Joi.string().hostname(); Helper.validate(schema, [ ['www.example.com', true], ['domain.local', true], ['3domain.local', true], ['hostname', true], ['host:name', false], ['-', false], ['2387628', true], ['01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789', false], ['::1', true], ['0:0:0:0:0:0:0:1', true], ['0:?:0:0:0:0:0:1', false] ], done); }); }); describe('#lowercase', function () { it('only allows strings that are entirely lowercase', function (done) { var schema = Joi.string().lowercase(); Helper.validateOptions(schema, [ ['this is all lowercase', true], ['5', true], ['lower\tcase', true], ['Uppercase', false], ['MixEd cAsE', false], [1, false] ], { convert: false }, done); }); it('coerce string to lowercase before validation', function (done) { var schema = Joi.string().lowercase(); schema.validate('UPPER TO LOWER', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal('upper to lower'); done(); }); }); it('should work in combination with a trim', function (done) { var schema = Joi.string().lowercase().trim(); Helper.validate(schema, [ [' abc', true], [' ABC', true], ['ABC', true], [1, false] ], done); }); it('should work in combination with a replacement', function (done) { var schema = Joi.string().lowercase().replace(/\s+/g, ' '); Helper.validate(schema, [ ['a\r b\n c', true, null, 'a b c'], ['A\t B C', true, null, 'a b c'], ['ABC', true, null, 'abc'], [1, false] ], done); }); }); describe('#uppercase', function () { it('only allow strings that are entirely uppercase', function (done) { var schema = Joi.string().uppercase(); Helper.validateOptions(schema, [ ['THIS IS ALL UPPERCASE', true], ['5', true], ['UPPER\nCASE', true], ['lOWERCASE', false], ['MixEd cAsE', false], [1, false] ], { convert: false }, done); }); it('coerce string to uppercase before validation', function (done) { var schema = Joi.string().uppercase(); schema.validate('lower to upper', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal('LOWER TO UPPER'); done(); }); }); it('works in combination with a forced trim', function (done) { var schema = Joi.string().uppercase().trim(); Helper.validate(schema, [ [' abc', true], [' ABC', true], ['ABC', true], [1, false] ], done); }); it('works in combination with a forced replacement', function (done) { var schema = Joi.string().uppercase().replace(/\s+/g, ' '); Helper.validate(schema, [ ['a\r b\n c', true, null, 'A B C'], ['A\t B C', true, null, 'A B C'], ['ABC', true, null, 'ABC'], [1, false] ], done); }); }); describe('#trim', function () { it('only allow strings that have no leading or trailing whitespace', function (done) { var schema = Joi.string().trim(); Helper.validateOptions(schema, [ [' something', false], ['something ', false], ['something\n', false], ['some thing', true], ['something', true] ], { convert: false }, done); }); it('removes leading and trailing whitespace before validation', function (done) { var schema = Joi.string().trim(); schema.validate(' trim this ', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal('trim this'); done(); }); }); it('removes leading and trailing whitespace before validation', function (done) { var schema = Joi.string().trim().allow(''); schema.validate(' ', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal(''); done(); }); }); it('should work in combination with min', function (done) { var schema = Joi.string().min(4).trim(); Helper.validate(schema, [ [' a ', false], ['abc ', false], ['abcd ', true] ], done); }); it('should work in combination with max', function (done) { var schema = Joi.string().max(4).trim(); Helper.validate(schema, [ [' abcde ', false], ['abc ', true], ['abcd ', true] ], done); }); it('should work in combination with length', function (done) { var schema = Joi.string().length(4).trim(); Helper.validate(schema, [ [' ab ', false], ['abc ', false], ['abcd ', true] ], done); }); it('should work in combination with a case change', function (done) { var schema = Joi.string().trim().lowercase(); Helper.validate(schema, [ [' abc', true], [' ABC', true], ['ABC', true] ], done); }); }); describe('#replace', function () { it('successfully replaces the first occurrence of the expression', function (done) { var schema = Joi.string().replace(/\s+/, ''); // no "g" flag Helper.validateOptions(schema, [ ['\tsomething', true, null, 'something'], ['something\r', true, null, 'something'], ['something ', true, null, 'something'], ['some thing', true, null, 'something'], ['so me thing', true, null, 'some thing'] // first occurrence! ], { convert: true }, done); }); it('successfully replaces all occurrences of the expression', function (done) { var schema = Joi.string().replace(/\s+/g, ''); // has "g" flag Helper.validateOptions(schema, [ ['\tsomething', true, null, 'something'], ['something\r', true, null, 'something'], ['something ', true, null, 'something'], ['some thing', true, null, 'something'], ['so me thing', true, null, 'something'] ], { convert: true }, done); }); it('successfully replaces all occurrences of a string pattern', function (done) { var schema = Joi.string().replace('foo', 'X'); // has "g" flag Helper.validateOptions(schema, [ ['foobarfoobazfoo', true, null, 'XbarXbazX'] ], { convert: true }, done); }); it('successfully replaces multiple times', function (done) { var schema = Joi.string().replace(/a/g, 'b').replace(/b/g, 'c'); schema.validate('a quick brown fox', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal('c quick crown fox'); done(); }); }); it('should work in combination with trim', function (done) { // The string below is the name "Yamada Tarou" separated by a // carriage return, a "full width" ideographic space and a newline var schema = Joi.string().trim().replace(/\s+/g, ' '); schema.validate(' \u5C71\u7530\r\u3000\n\u592A\u90CE ', function (err, value) { expect(err).to.not.exist(); expect(value).to.equal('\u5C71\u7530 \u592A\u90CE'); done(); }); }); it('should work in combination with min', function (done) { var schema = Joi.string().min(4).replace(/\s+/g, ' '); Helper.validate(schema, [ [' a ', false], ['abc ', true, null, 'abc '], ['a\t\rbc', true, null, 'a bc'] ], done); }); it('should work in combination with max', function (done) { var schema = Joi.string().max(5).replace(/ CHANGE ME /g, '-b-'); Helper.validate(schema, [ ['a CHANGE ME c', true, null, 'a-b-c'], ['a-b-c', true, null, 'a-b-c'] // nothing changes here! ], done); }); it('should work in combination with length', function (done) { var schema = Joi.string().length(5).replace(/\s+/g, ' '); Helper.validate(schema, [ ['a bc', false], ['a\tb\nc', true, null, 'a b c'] ], done); }); }); describe('#regex', function () { it('should not include a pattern name by default', function (done) { var schema = Joi.string().regex(/[a-z]+/).regex(/[0-9]+/); schema.validate('abcd', function (err, value) { expect(err.message).to.contain('required pattern'); done(); }); }); it('should include a pattern name if specified', function (done) { var schema = Joi.string().regex(/[a-z]+/, 'letters').regex(/[0-9]+/, 'numbers'); schema.validate('abcd', function (err, value) { expect(err.message).to.contain('numbers pattern'); done(); }); }); }); describe('#ip', function () { var invalidIPs = [ ['ASDF', false], ['192.0.2.16:80/30', false], ['192.0.2.16a', false], ['qwerty', false], ['127.0.0.1:8000', false], ['ftp://www.example.com', false], ['Bananas in pajamas are coming down the stairs', false] ], invalidIPv4s = [ ['0.0.0.0/33', false], ['256.0.0.0/0', false], ['255.255.255.256/32', false], ['256.0.0.0', false], ['255.255.255.256', false] ], invalidIPv6s = [ ['2001:db8::7/33', false], ['1080:0:0:0:8:800:200C:417G', false] ], invalidIPvFutures = [ ['v1.09azAZ-._~!$&\'()*+,;=:/33', false], ['v1.09#', false] ], validIPv4sWithCidr = function (success) { return [ ['0.0.0.0/32', success], ['255.255.255.255/0', success], ['127.0.0.1/0', success], ['192.168.2.1/0', success], ['0.0.0.3/2', success], ['0.0.0.7/3', success], ['0.0.0.15/4', success], ['0.0.0.31/5', success], ['0.0.0.63/6', success], ['0.0.0.127/7', success], ['01.020.030.100/7', success], ['0.0.0.0/0', success], ['00.00.00.00/0', success], ['000.000.000.000/32', success] ]; }, validIPv4sWithoutCidr = function (success) { return [ ['0.0.0.0', success], ['255.255.255.255', success], ['127.0.0.1', success], ['192.168.2.1', success], ['0.0.0.3', success], ['0.0.0.7', success], ['0.0.0.15', success], ['0.0.0.31', success], ['0.0.0.63', success], ['0.0.0.127', success], ['01.020.030.100', success], ['0.0.0.0', success], ['00.00.00.00', success], ['000.000.000.000', success] ]; }, validIPv6sWithCidr = function (success) { return [ ['2001:db8::7/32', success], ['a:b:c:d:e::1.2.3.4/13', success], ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/0', success], ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210/32', success], ['1080:0:0:0:8:800:200C:417A/27', success] ]; }, validIPv6sWithoutCidr = function (success) { return [ ['2001:db8::7', success], ['a:b:c:d:e::1.2.3.4', success], ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', success], ['FEDC:BA98:7654:3210:FEDC:BA98:7654:3210', success], ['1080:0:0:0:8:800:200C:417A', success] ]; }, validIPvFuturesWithCidr = function (success) { return [ ['v1.09azAZ-._~!$&\'()*+,;=:/32', success] ]; }, validIPvFuturesWithoutCidr = function (success) { return [ ['v1.09azAZ-._~!$&\'()*+,;=:', success] ]; }; it('should validate all ip addresses with optional CIDR by default', function (done) { var schema = Joi.string().ip(); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ip addresses with an optional CIDR', function (done) { var schema = Joi.string().ip({ cidr: 'optional' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ip addresses with a required CIDR', function (done) { var schema = Joi.string().ip({ cidr: 'required' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ip addresses with a forbidden CIDR', function (done) { var schema = Joi.string().ip({ cidr: 'forbidden' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('throws when options is not an object', function (done) { expect(function () { Joi.string().ip(42); }).to.throw('options must be an object'); done(); }); it('throws when options.cidr is not a string', function (done) { expect(function () { Joi.string().ip({ cidr: 42 }); }).to.throw('cidr must be a string'); done(); }); it('throws when options.cidr is not a valid value', function (done) { expect(function () { Joi.string().ip({ cidr: '42' }); }).to.throw('cidr must be one of required, optional, forbidden'); done(); }); it('throws when options.version is an empty array', function (done) { expect(function () { Joi.string().ip({ version: [] }); }).to.throw('version must have at least 1 version specified'); done(); }); it('throws when options.version is not a string', function (done) { expect(function () { Joi.string().ip({ version: 42 }); }).to.throw('version at position 0 must be a string'); done(); }); it('throws when options.version is not a valid value', function (done) { expect(function () { Joi.string().ip({ version: '42' }); }).to.throw('version at position 0 must be one of ipv4, ipv6, ipvfuture'); done(); }); it('validates ip with a friendly error message', function (done) { var schema = { item: Joi.string().ip() }; Joi.compile(schema).validate({ item: 'something' }, function (err, value) { expect(err.message).to.contain('must be a valid ip address'); done(); }); }); it('validates ip and cidr presence with a friendly error message', function (done) { var schema = { item: Joi.string().ip({ cidr: 'required' }) }; Joi.compile(schema).validate({ item: 'something' }, function (err, value) { expect(err.message).to.contain('must be a valid ip address with a required CIDR'); done(); }); }); it('validates custom ip version and cidr presence with a friendly error message', function (done) { var schema = { item: Joi.string().ip({ version: 'ipv4', cidr: 'required' }) }; Joi.compile(schema).validate({ item: 'something' }, function (err, value) { expect(err.message).to.contain('child "item" fails because ["item" must be a valid ip address of one of the following versions [ipv4] with a required CIDR]'); done(); }); }); describe('#ip({ version: "ipv4" })', function () { it('should validate all ipv4 addresses with a default CIDR strategy', function (done) { var schema = Joi.string().ip({ version: 'ipv4' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 addresses with an optional CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv4', cidr: 'optional' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 addresses with a required CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv4', cidr: 'required' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 addresses with a forbidden CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv4', cidr: 'forbidden' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); }); describe('#ip({ version: "ipv6" })', function () { it('should validate all ipv6 addresses with a default CIDR strategy', function (done) { var schema = Joi.string().ip({ version: 'ipv6' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv6 addresses with an optional CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv6', cidr: 'optional' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv6 addresses with a required CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv6', cidr: 'required' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv6 addresses with a forbidden CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipv6', cidr: 'forbidden' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); }); describe('#ip({ version: "ipvfuture" })', function () { it('should validate all ipvfuture addresses with a default CIDR strategy', function (done) { var schema = Joi.string().ip({ version: 'ipvfuture' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipvfuture addresses with an optional CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'optional' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipvfuture addresses with a required CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'required' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(true)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipvfuture addresses with a forbidden CIDR', function (done) { var schema = Joi.string().ip({ version: 'ipvfuture', cidr: 'forbidden' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(true)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); }); describe('#ip({ version: [ "ipv4", "ipv6" ] })', function () { it('should validate all ipv4 and ipv6 addresses with a default CIDR strategy', function (done) { var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'] }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 and ipv6 addresses with an optional CIDR', function (done) { var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'optional' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 and ipv6 addresses with a required CIDR', function (done) { var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'required' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(true)) .concat(validIPv4sWithoutCidr(false)) .concat(validIPv6sWithCidr(true)) .concat(validIPv6sWithoutCidr(false)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); it('should validate all ipv4 and ipv6 addresses with a forbidden CIDR', function (done) { var schema = Joi.string().ip({ version: ['ipv4', 'ipv6'], cidr: 'forbidden' }); Helper.validate(schema, [] .concat(validIPv4sWithCidr(false)) .concat(validIPv4sWithoutCidr(true)) .concat(validIPv6sWithCidr(false)) .concat(validIPv6sWithoutCidr(true)) .concat(validIPvFuturesWithCidr(false)) .concat(validIPvFuturesWithoutCidr(false)) .concat(invalidIPs) .concat(invalidIPv4s) .concat(invalidIPv6s) .concat(invalidIPvFutures), done); }); }); }); describe('#validate', function () { it('should, by default, allow undefined, deny empty string', function (done) { Helper.validate(Joi.string(), [ [undefined, true], ['', false] ], done); }); it('should, when .required(), deny undefined, deny empty string', function (done) { Helper.validate(Joi.string().required(), [ [undefined, false], ['', false] ], done); }); it('should, when .required(), print a friend error message for an empty string', function (done) { var schema = Joi.string().required(); Joi.compile(schema).validate('', function (err, value) { expect(err.message).to.contain('be empty'); done(); }); }); it('should, when .required(), validate non-empty strings', function (done) { var schema = Joi.string().required(); Helper.validate(schema, [ ['test', true], ['0', true], [null, false] ], done); }); it('validates invalid values', function (done) { var schema = Joi.string().invalid('a', 'b', 'c'); Helper.validate(schema, [