joi 4.6.2 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.c9/.nakignore +17 -0
  2. package/.c9/metadata/tab0 +1 -0
  3. package/.c9/metadata/workspace/.c9/project.settings +1 -0
  4. package/.c9/metadata/workspace/.travis.yml +1 -0
  5. package/.c9/metadata/workspace/Makefile +1 -0
  6. package/.c9/metadata/workspace/README.md +1 -0
  7. package/.c9/metadata/workspace/lib/any.js +1 -0
  8. package/.c9/metadata/workspace/lib/array.js +1 -0
  9. package/.c9/metadata/workspace/lib/binary.js +1 -0
  10. package/.c9/metadata/workspace/lib/boolean.js +1 -0
  11. package/.c9/metadata/workspace/lib/cast.js +1 -0
  12. package/.c9/metadata/workspace/lib/date.js +1 -0
  13. package/.c9/metadata/workspace/lib/errors.js +1 -0
  14. package/.c9/metadata/workspace/lib/function.js +1 -0
  15. package/.c9/metadata/workspace/lib/index.js +1 -0
  16. package/.c9/metadata/workspace/lib/language.js +1 -0
  17. package/.c9/metadata/workspace/lib/number.js +1 -0
  18. package/.c9/metadata/workspace/lib/object.js +1 -0
  19. package/.c9/metadata/workspace/lib/string.js +1 -0
  20. package/.c9/metadata/workspace/package.json +1 -0
  21. package/.c9/metadata/workspace/test/alternatives.js +1 -0
  22. package/.c9/metadata/workspace/test/any.js +1 -0
  23. package/.c9/metadata/workspace/test/array.js +1 -0
  24. package/.c9/metadata/workspace/test/binary.js +1 -0
  25. package/.c9/metadata/workspace/test/boolean.js +1 -0
  26. package/.c9/metadata/workspace/test/date.js +1 -0
  27. package/.c9/metadata/workspace/test/errors.js +1 -0
  28. package/.c9/metadata/workspace/test/function.js +1 -0
  29. package/.c9/metadata/workspace/test/helper.js +1 -0
  30. package/.c9/metadata/workspace/test/index.js +1 -0
  31. package/.c9/metadata/workspace/test/number.js +1 -0
  32. package/.c9/metadata/workspace/test/object.js +1 -0
  33. package/.c9/metadata/workspace/test/ref.js +1 -0
  34. package/.c9/metadata/workspace/test/string.js +1 -0
  35. package/.c9/project.settings +34 -0
  36. package/.travis.yml +1 -0
  37. package/Makefile +3 -3
  38. package/README.md +162 -31
  39. package/examples/conditionalRequire.js +43 -0
  40. package/examples/customMessage.js +22 -0
  41. package/examples/multipleWhen.js +17 -0
  42. package/lib/any.js +35 -24
  43. package/lib/array.js +25 -0
  44. package/lib/date.js +64 -9
  45. package/lib/errors.js +18 -2
  46. package/lib/index.js +3 -2
  47. package/lib/language.js +17 -6
  48. package/lib/number.js +50 -0
  49. package/lib/object.js +69 -5
  50. package/lib/string.js +27 -6
  51. package/package.json +5 -3
  52. package/test/alternatives.js +12 -10
  53. package/test/any.js +64 -15
  54. package/test/array.js +55 -16
  55. package/test/binary.js +13 -11
  56. package/test/boolean.js +9 -7
  57. package/test/date.js +143 -20
  58. package/test/errors.js +26 -15
  59. package/test/function.js +7 -5
  60. package/test/helper.js +7 -5
  61. package/test/index.js +116 -73
  62. package/test/number.js +125 -12
  63. package/test/object.js +192 -43
  64. package/test/ref.js +22 -20
  65. package/test/string.js +255 -106
  66. package/AUTHORS +0 -3
package/lib/date.js CHANGED
@@ -3,12 +3,15 @@
3
3
  var Any = require('./any');
4
4
  var Errors = require('./errors');
5
5
  var Hoek = require('hoek');
6
+ var Moment = require('moment');
6
7
 
7
8
 
8
9
  // Declare internals
9
10
 
10
11
  var internals = {};
11
12
 
13
+ internals.isoDate = /^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\d))$/;
14
+ internals.invalidDate = new Date('');
12
15
 
13
16
  internals.Date = function () {
14
17
 
@@ -22,15 +25,21 @@ Hoek.inherits(internals.Date, Any);
22
25
  internals.Date.prototype._base = function (value, state, options) {
23
26
 
24
27
  var result = {
25
- value: (options.convert && internals.toDate(value)) || value
28
+ value: (options.convert && internals.toDate(value, this._flags.format)) || value
26
29
  };
27
30
 
28
- result.errors = (result.value instanceof Date && !isNaN(result.value.getTime())) ? null : Errors.create('date.base', null, state, options);
31
+ if (result.value instanceof Date && !isNaN(result.value.getTime())) {
32
+ result.errors = null;
33
+ }
34
+ else {
35
+ result.errors = Errors.create(this._flags.format === internals.isoDate ? 'date.isoDate' : 'date.base', null, state, options);
36
+ }
37
+
29
38
  return result;
30
39
  };
31
40
 
32
41
 
33
- internals.toDate = function (value) {
42
+ internals.toDate = function (value, format) {
34
43
 
35
44
  if (value instanceof Date) {
36
45
  return value;
@@ -40,12 +49,25 @@ internals.toDate = function (value) {
40
49
  Hoek.isInteger(value)) {
41
50
 
42
51
  if (typeof value === 'string' &&
43
- /^\d+$/.test(value)) {
52
+ /^[+-]?\d+$/.test(value)) {
44
53
 
45
54
  value = parseInt(value, 10);
46
55
  }
47
56
 
48
- var date = new Date(value);
57
+ var date;
58
+ if (format) {
59
+ if (format === internals.isoDate) {
60
+ date = format.test(value) ? new Date(value) : internals.invalidDate;
61
+ }
62
+ else {
63
+ date = Moment(value, format, true);
64
+ date = date.isValid() ? date.toDate() : internals.invalidDate;
65
+ }
66
+ }
67
+ else {
68
+ date = new Date(value);
69
+ }
70
+
49
71
  if (!isNaN(date.getTime())) {
50
72
  return date;
51
73
  }
@@ -57,12 +79,17 @@ internals.toDate = function (value) {
57
79
 
58
80
  internals.Date.prototype.min = function (date) {
59
81
 
60
- date = internals.toDate(date);
82
+ var isNow = date === 'now';
83
+
84
+ if (!isNow) {
85
+ date = internals.toDate(date);
86
+ }
87
+
61
88
  Hoek.assert(date, 'Invalid date format');
62
89
 
63
90
  return this._test('min', date, function (value, state, options) {
64
91
 
65
- if (value.getTime() >= date.getTime()) {
92
+ if (value.getTime() >= (isNow ? Date.now() : date.getTime())) {
66
93
  return null;
67
94
  }
68
95
 
@@ -73,12 +100,17 @@ internals.Date.prototype.min = function (date) {
73
100
 
74
101
  internals.Date.prototype.max = function (date) {
75
102
 
76
- date = internals.toDate(date);
103
+ var isNow = date === 'now';
104
+
105
+ if (!isNow) {
106
+ date = internals.toDate(date);
107
+ }
108
+
77
109
  Hoek.assert(date, 'Invalid date format');
78
110
 
79
111
  return this._test('max', date, function (value, state, options) {
80
112
 
81
- if (value.getTime() <= date.getTime()) {
113
+ if (value.getTime() <= (isNow ? Date.now() : date.getTime())) {
82
114
  return null;
83
115
  }
84
116
 
@@ -86,5 +118,28 @@ internals.Date.prototype.max = function (date) {
86
118
  });
87
119
  };
88
120
 
121
+ internals.Date.prototype.format = function (format) {
122
+
123
+ Hoek.assert(typeof format === 'string' || (Array.isArray(format) && format.every(function (f) {
124
+
125
+ return typeof f === 'string';
126
+ })), 'Invalid format.');
127
+
128
+ var obj = this.clone();
129
+ obj._flags.format = format;
130
+ return obj;
131
+ };
132
+
133
+ internals.Date.prototype.iso = function () {
134
+
135
+ var obj = this.clone();
136
+ obj._flags.format = internals.isoDate;
137
+ return obj;
138
+ }
139
+
140
+ internals.Date.prototype._isIsoDate = function (value) {
141
+
142
+ return internals.isoDate.test(value);
143
+ };
89
144
 
90
145
  module.exports = new internals.Date();
package/lib/errors.js CHANGED
@@ -24,7 +24,7 @@ internals.Err.prototype.toString = function () {
24
24
  var self = this;
25
25
 
26
26
  var localized = this.options.language;
27
- this.context.key = this.context.key || localized.root || Language.errors.root;
27
+ this.context.key = localized.label || this.context.key || localized.root || Language.errors.root;
28
28
 
29
29
  var format = Hoek.reach(localized, this.type) || Hoek.reach(Language.errors, this.type);
30
30
  var hasKey = /\{\{\!?key\}\}/.test(format);
@@ -57,7 +57,7 @@ exports.process = function (errors, object) {
57
57
  var item = errors[i];
58
58
  details.push({
59
59
  message: item.toString(),
60
- path: item.path || item.context.key,
60
+ path: internals.getPath(item),
61
61
  type: item.type
62
62
  });
63
63
  }
@@ -79,6 +79,22 @@ exports.process = function (errors, object) {
79
79
  };
80
80
 
81
81
 
82
+ internals.getPath = function (item) {
83
+
84
+ var recursePath = function (it) {
85
+
86
+ var reachedItem = Hoek.reach(it, 'context.reason.0');
87
+ if (reachedItem && reachedItem.context) {
88
+ return recursePath(reachedItem);
89
+ }
90
+
91
+ return it.path;
92
+ };
93
+
94
+ return recursePath(item) || item.context.key;
95
+ };
96
+
97
+
82
98
  internals.annotate = function () {
83
99
 
84
100
  var obj = Hoek.clone(this._object || {});
package/lib/index.js CHANGED
@@ -113,11 +113,12 @@ internals.root = function () {
113
113
  return Cast.schema(schema);
114
114
  };
115
115
 
116
- root.assert = function (value, schema) {
116
+ root.assert = function (value, schema, message) {
117
117
 
118
+ message = (message ? message + ' ' : '');
118
119
  var error = root.validate(value, schema).error;
119
120
  if (error) {
120
- throw new Error(error.annotate());
121
+ throw new Error(message + error.annotate());
121
122
  }
122
123
  };
123
124
 
package/lib/language.js CHANGED
@@ -25,7 +25,8 @@ exports.errors = {
25
25
  excludes: 'position {{pos}} contains an excluded value',
26
26
  min: 'must contain at least {{limit}} items',
27
27
  max: 'must contain less than or equal to {{limit}} items',
28
- length: 'must contain {{limit}} items'
28
+ length: 'must contain {{limit}} items',
29
+ unique: 'position {{pos}} contains a duplicate value'
29
30
  },
30
31
  boolean: {
31
32
  base: 'must be a boolean'
@@ -39,7 +40,8 @@ exports.errors = {
39
40
  date: {
40
41
  base: 'must be a number of milliseconds or valid date string',
41
42
  min: 'must be larger than or equal to {{limit}}',
42
- max: 'must be less than or equal to {{limit}}'
43
+ max: 'must be less than or equal to {{limit}}',
44
+ isoDate: 'must be a valid ISO 8601 date'
43
45
  },
44
46
  function: {
45
47
  base: 'must be a Function'
@@ -56,20 +58,25 @@ exports.errors = {
56
58
  xor: 'contains a conflict between exclusive peers {{peers}}',
57
59
  or: 'must contain at least one of {{peers}}',
58
60
  and: 'contains {{present}} without its required peers {{missing}}',
61
+ nand: '{{main}} must not exist simultaneously with {{peers}}',
59
62
  assert: 'validation failed because {{ref}} failed to {{message}}',
60
63
  rename: {
61
64
  multiple: 'cannot rename child {{from}} because multiple renames are disabled and another key was already renamed to {{to}}',
62
65
  override: 'cannot rename child {{from}} because override is disabled and target {{to}} exists'
63
- }
66
+ },
67
+ type: 'must be an instance of {{type}}'
64
68
  },
65
69
  number: {
66
70
  base: 'must be a number',
67
71
  min: 'must be larger than or equal to {{limit}}',
68
72
  max: 'must be less than or equal to {{limit}}',
73
+ less: 'must be less than {{limit}}',
74
+ greater: 'must be greater than {{limit}}',
69
75
  float: 'must be a float or double',
70
76
  integer: 'must be an integer',
71
77
  negative: 'must be a negative number',
72
- positive: 'must be a positive number'
78
+ positive: 'must be a positive number',
79
+ precision: 'must have no more than {{limit}} decimal places'
73
80
  },
74
81
  string: {
75
82
  base: 'must be a string',
@@ -78,13 +85,17 @@ exports.errors = {
78
85
  length: 'length must be {{limit}} characters long',
79
86
  alphanum: 'must only contain alpha-numeric characters',
80
87
  token: 'must only contain alpha-numeric and underscore characters',
81
- regex: 'fails to match the required pattern',
88
+ regex: {
89
+ base: 'fails to match the required pattern',
90
+ name: 'fails to match the {{name}} pattern'
91
+ },
82
92
  email: 'must be a valid email',
83
93
  isoDate: 'must be a valid ISO 8601 date',
84
94
  guid: 'must be a valid GUID',
85
95
  hostname: 'must be a valid hostname',
86
96
  lowercase: 'must only contain lowercase characters',
87
97
  uppercase: 'must only contain uppercase characters',
88
- trim: 'must not have leading or trailing whitespace'
98
+ trim: 'must not have leading or trailing whitespace',
99
+ creditCard: 'must be a credit card'
89
100
  }
90
101
  };
package/lib/number.js CHANGED
@@ -68,6 +68,36 @@ internals.Number.prototype.max = function (limit) {
68
68
  };
69
69
 
70
70
 
71
+ internals.Number.prototype.greater = function (limit) {
72
+
73
+ Hoek.assert(Hoek.isInteger(limit), 'limit must be an integer');
74
+
75
+ return this._test('greater', limit, function (value, state, options) {
76
+
77
+ if (value > limit) {
78
+ return null;
79
+ }
80
+
81
+ return Errors.create('number.greater', { limit: limit }, state, options);
82
+ });
83
+ };
84
+
85
+
86
+ internals.Number.prototype.less = function (limit) {
87
+
88
+ Hoek.assert(Hoek.isInteger(limit), 'limit must be an integer');
89
+
90
+ return this._test('less', limit, function (value, state, options) {
91
+
92
+ if (value < limit) {
93
+ return null;
94
+ }
95
+
96
+ return Errors.create('number.less', { limit: limit }, state, options);
97
+ });
98
+ };
99
+
100
+
71
101
  internals.Number.prototype.integer = function () {
72
102
 
73
103
  return this._test('integer', undefined, function (value, state, options) {
@@ -103,4 +133,24 @@ internals.Number.prototype.positive = function () {
103
133
  };
104
134
 
105
135
 
136
+ internals.precisionRx = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
137
+
138
+
139
+ internals.Number.prototype.precision = function (limit) {
140
+
141
+ Hoek.assert(Hoek.isInteger(limit), 'limit must be an integer');
142
+
143
+ return this._test('precision', limit, function (value, state, options){
144
+
145
+ var places = value.toString().match(internals.precisionRx);
146
+ var decimals = Math.max((places[1] ? places[1].length : 0) - (places[2] ? parseInt(places[2], 10) : 0), 0);
147
+ if (decimals <= limit) {
148
+ return null;
149
+ }
150
+
151
+ return Errors.create('number.precision', {limit: limit}, state, options);
152
+ });
153
+ };
154
+
155
+
106
156
  module.exports = new internals.Number();
package/lib/object.js CHANGED
@@ -55,11 +55,21 @@ internals.Object.prototype._base = function (value, state, options) {
55
55
  return finish();
56
56
  }
57
57
 
58
+ // Skip if there are no other rules to test
59
+
60
+ if (!this._inner.renames.length &&
61
+ !this._inner.dependencies.length &&
62
+ !this._inner.children && // null allows any keys
63
+ !this._inner.patterns.length) {
64
+
65
+ target = value;
66
+ return finish();
67
+ }
68
+
58
69
  // Ensure target is a local copy (parsed) or shallow copy
59
70
 
60
71
  if (target === value) {
61
- target = {};
62
- target.__proto__ = Object.getPrototypeOf(value);
72
+ target = Object.create(Object.getPrototypeOf(value));
63
73
  var valueKeys = Object.keys(value);
64
74
  for (var t = 0, tl = valueKeys.length; t < tl; ++t) {
65
75
  target[valueKeys[t]] = value[valueKeys[t]];
@@ -320,13 +330,15 @@ internals.Object.prototype.max = function (limit) {
320
330
  };
321
331
 
322
332
 
323
- internals.Object.prototype.pattern = function (regex, schema) {
333
+ internals.Object.prototype.pattern = function (pattern, schema) {
324
334
 
325
- Hoek.assert(regex instanceof RegExp, 'Invalid regular expression');
335
+ Hoek.assert(pattern instanceof RegExp, 'Invalid regular expression');
326
336
  Hoek.assert(schema !== undefined, 'Invalid rule');
327
337
 
338
+ pattern = new RegExp(pattern.source, pattern.ignoreCase ? 'i' : undefined); // Future version should break this and forbid unsupported regex flags
339
+
328
340
  var obj = this.clone();
329
- obj._inner.patterns.push({ regex: regex, rule: Cast.schema(schema) });
341
+ obj._inner.patterns.push({ regex: pattern, rule: Cast.schema(schema) });
330
342
  return obj;
331
343
  };
332
344
 
@@ -364,6 +376,13 @@ internals.Object.prototype.and = function () {
364
376
  };
365
377
 
366
378
 
379
+ internals.Object.prototype.nand = function () {
380
+
381
+ var peers = Hoek.flatten(Array.prototype.slice.call(arguments));
382
+ return this._dependency('nand', null, peers);
383
+ };
384
+
385
+
367
386
  internals.renameDefaults = {
368
387
  alias: false, // Keep old value in place
369
388
  multiple: false, // Allow renaming multiple keys into the same target
@@ -504,6 +523,25 @@ internals.and = function (value, peers, parent, state, options) {
504
523
  };
505
524
 
506
525
 
526
+ internals.nand = function (value, peers, parent, state, options) {
527
+
528
+ var present = [];
529
+ for (var i = 0, il = peers.length; i < il; ++i) {
530
+ var peer = peers[i];
531
+ if (parent.hasOwnProperty(peer) &&
532
+ parent[peer] !== undefined) {
533
+
534
+ present.push(peer);
535
+ }
536
+ }
537
+
538
+ var values = Hoek.clone(peers);
539
+ var main = values.splice(0,1);
540
+ var allPresent = (present.length === peers.length);
541
+ return allPresent ? Errors.create('object.nand', { main: main, peers: values }, state, options) : null;
542
+ };
543
+
544
+
507
545
  internals.Object.prototype.describe = function (shallow) {
508
546
 
509
547
  var description = Any.prototype.describe.call(this);
@@ -522,6 +560,15 @@ internals.Object.prototype.describe = function (shallow) {
522
560
  description.dependencies = Hoek.clone(this._inner.dependencies);
523
561
  }
524
562
 
563
+ if (this._inner.patterns.length) {
564
+ description.patterns = [];
565
+
566
+ for (var p = 0, pl = this._inner.patterns.length; p < pl; ++p) {
567
+ var pattern = this._inner.patterns[p];
568
+ description.patterns.push({ regex: pattern.regex.toString(), rule: pattern.rule.describe() });
569
+ }
570
+ }
571
+
525
572
  return description;
526
573
  };
527
574
 
@@ -530,6 +577,7 @@ internals.Object.prototype.assert = function (ref, schema, message) {
530
577
 
531
578
  ref = Cast.ref(ref);
532
579
  Hoek.assert(ref.isContext || ref.depth > 1, 'Cannot use assertions for root level references - use direct key rules instead');
580
+ message = message || 'pass the assertion test';
533
581
 
534
582
  var cast = Cast.schema(schema);
535
583
 
@@ -545,4 +593,20 @@ internals.Object.prototype.assert = function (ref, schema, message) {
545
593
  };
546
594
 
547
595
 
596
+ internals.Object.prototype.type = function (constructor, name) {
597
+
598
+ Hoek.assert(typeof constructor === 'function', 'type must be a constructor function');
599
+ name = name || constructor.name;
600
+
601
+ return this._test('type', name, function (value, state, options) {
602
+
603
+ if (value instanceof constructor) {
604
+ return null;
605
+ }
606
+
607
+ return Errors.create('object.type', { type: name }, state, options);
608
+ });
609
+ };
610
+
611
+
548
612
  module.exports = new internals.Object();
package/lib/string.js CHANGED
@@ -4,9 +4,9 @@ var Net = require('net');
4
4
  var Hoek = require('hoek');
5
5
  var Isemail = require('isemail');
6
6
  var Any = require('./any');
7
+ var JoiDate = require('./date');
7
8
  var Errors = require('./errors');
8
9
 
9
-
10
10
  // Declare internals
11
11
 
12
12
  var internals = {};
@@ -85,6 +85,27 @@ internals.String.prototype.max = function (limit, encoding) {
85
85
  };
86
86
 
87
87
 
88
+ internals.String.prototype.creditCard = function () {
89
+
90
+ return this._test('creditCard', undefined, function (value, state, options) {
91
+
92
+ var i = value.length;
93
+ var sum = 0;
94
+ var mul = 1;
95
+ var char;
96
+
97
+ while (i--) {
98
+ char = value.charAt(i) * mul;
99
+ sum += char - (char > 9) * 9;
100
+ mul ^= 3;
101
+ }
102
+
103
+ var check = (sum % 10 === 0) && (sum > 0);
104
+ return check ? null : Errors.create('string.creditCard', null, state, options);
105
+ });
106
+ };
107
+
108
+
88
109
  internals.String.prototype.length = function (limit, encoding) {
89
110
 
90
111
  Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer');
@@ -102,17 +123,19 @@ internals.String.prototype.length = function (limit, encoding) {
102
123
  };
103
124
 
104
125
 
105
- internals.String.prototype.regex = function (pattern) {
126
+ internals.String.prototype.regex = function (pattern, name) {
106
127
 
107
128
  Hoek.assert(pattern instanceof RegExp, 'pattern must be a RegExp');
108
129
 
130
+ pattern = new RegExp(pattern.source, pattern.ignoreCase ? 'i' : undefined); // Future version should break this and forbid unsupported regex flags
131
+
109
132
  return this._test('regex', pattern, function (value, state, options) {
110
133
 
111
134
  if (pattern.test(value)) {
112
135
  return null;
113
136
  }
114
137
 
115
- return Errors.create('string.regex', null, state, options);
138
+ return Errors.create((name ? 'string.regex.name' : 'string.regex.base'), { name: name }, state, options);
116
139
  });
117
140
  };
118
141
 
@@ -158,11 +181,9 @@ internals.String.prototype.email = function () {
158
181
 
159
182
  internals.String.prototype.isoDate = function () {
160
183
 
161
- var regex = /^(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))$/;
162
-
163
184
  return this._test('isoDate', undefined, function (value, state, options) {
164
185
 
165
- if (regex.test(value)) {
186
+ if (JoiDate._isIsoDate(value)) {
166
187
  return null;
167
188
  }
168
189
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "joi",
3
3
  "description": "Object schema validation",
4
- "version": "4.6.2",
4
+ "version": "4.9.0",
5
5
  "repository": "git://github.com/hapijs/joi",
6
6
  "main": "index",
7
7
  "keywords": [
@@ -14,10 +14,12 @@
14
14
  "dependencies": {
15
15
  "hoek": "^2.2.x",
16
16
  "topo": "1.x.x",
17
- "isemail": "1.x.x"
17
+ "isemail": "1.x.x",
18
+ "moment": "2.x.x"
18
19
  },
19
20
  "devDependencies": {
20
- "lab": "3.x.x"
21
+ "code": "1.x.x",
22
+ "lab": "5.x.x"
21
23
  },
22
24
  "scripts": {
23
25
  "test": "make test-cov"
@@ -1,6 +1,7 @@
1
1
  // Load modules
2
2
 
3
3
  var Lab = require('lab');
4
+ var Code = require('code');
4
5
  var Joi = require('..');
5
6
  var Helper = require('./helper');
6
7
 
@@ -12,11 +13,12 @@ var internals = {};
12
13
 
13
14
  // Test shortcuts
14
15
 
15
- var expect = Lab.expect;
16
- var before = Lab.before;
17
- var after = Lab.after;
18
- var describe = Lab.experiment;
19
- var it = Lab.test;
16
+ var lab = exports.lab = Lab.script();
17
+ var before = lab.before;
18
+ var after = lab.after;
19
+ var describe = lab.describe;
20
+ var it = lab.it;
21
+ var expect = Code.expect;
20
22
 
21
23
 
22
24
  describe('alternatives', function () {
@@ -25,7 +27,7 @@ describe('alternatives', function () {
25
27
 
26
28
  Joi.alternatives().validate('a', function (err, value) {
27
29
 
28
- expect(err).to.exist;
30
+ expect(err).to.exist();
29
31
  expect(err.message).to.equal('value not matching any of the allowed alternatives');
30
32
  done();
31
33
  });
@@ -35,7 +37,7 @@ describe('alternatives', function () {
35
37
 
36
38
  Joi.alternatives().validate(undefined, function (err, value) {
37
39
 
38
- expect(err).to.not.exist;
40
+ expect(err).to.not.exist();
39
41
  done();
40
42
  });
41
43
  });
@@ -51,7 +53,7 @@ describe('alternatives', function () {
51
53
 
52
54
  schema.validate({ a: '5' }, function (err, value) {
53
55
 
54
- expect(err).to.not.exist;
56
+ expect(err).to.not.exist();
55
57
  expect(value.a).to.equal(5);
56
58
  done();
57
59
  });
@@ -68,7 +70,7 @@ describe('alternatives', function () {
68
70
 
69
71
  schema.validate({ a: '5' }, function (err, value) {
70
72
 
71
- expect(err).to.not.exist;
73
+ expect(err).to.not.exist();
72
74
  expect(value.a).to.equal(5);
73
75
  done();
74
76
  });
@@ -86,7 +88,7 @@ describe('alternatives', function () {
86
88
  var input = { a: { b: 'any', d: 'string' } };
87
89
  schema.validate(input, function (err, value) {
88
90
 
89
- expect(err).to.not.exist;
91
+ expect(err).to.not.exist();
90
92
  expect(value.a.b).to.equal('any');
91
93
  done();
92
94
  });