zater-cep
Version:
ZAter cep correios e via cep
1,363 lines (1,066 loc) • 117 kB
JavaScript
// 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, [