joi 6.8.1 → 6.10.1
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.
- package/.travis.yml +1 -0
- package/API.md +34 -6
- package/lib/any.js +5 -1
- package/lib/array.js +103 -3
- package/lib/index.js +15 -5
- package/lib/language.js +2 -0
- package/lib/object.js +39 -5
- package/package.json +1 -1
- package/test/any.js +91 -2
- package/test/array.js +256 -3
- package/test/errors.js +38 -3
- package/test/index.js +31 -0
- package/test/object.js +62 -0
package/.travis.yml
CHANGED
package/API.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<!-- version -->
|
|
2
|
-
# 6.
|
|
2
|
+
# 6.10.1 API Reference
|
|
3
3
|
<!-- versionstop -->
|
|
4
4
|
|
|
5
5
|
<img src="https://raw.github.com/hapijs/joi/master/images/validation.png" align="right" />
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
- [`array.sparse(enabled)`](#arraysparseenabled)
|
|
39
39
|
- [`array.single(enabled)`](#arraysingleenabled)
|
|
40
40
|
- [`array.items(type)`](#arrayitemstype)
|
|
41
|
+
- [`array.ordered(type)`](#arrayorderedtype)
|
|
41
42
|
- [`array.min(limit)`](#arrayminlimit)
|
|
42
43
|
- [`array.max(limit)`](#arraymaxlimit)
|
|
43
44
|
- [`array.length(limit)`](#arraylengthlimit)
|
|
@@ -109,6 +110,7 @@
|
|
|
109
110
|
- [`alternatives.try(schemas)`](#alternativestryschemas)
|
|
110
111
|
- [`alternatives.when(ref, options)`](#alternativeswhenref-options)
|
|
111
112
|
- [`ref(key, [options])`](#refkey-options)
|
|
113
|
+
- [Errors](#errors)
|
|
112
114
|
|
|
113
115
|
<!-- tocstop -->
|
|
114
116
|
|
|
@@ -132,9 +134,9 @@ Validates a value using the given schema and options where:
|
|
|
132
134
|
`validate()` and not using `any.options()`.
|
|
133
135
|
- `noDefaults` - when `true`, do not apply default values. Defaults to `false`.
|
|
134
136
|
- `callback` - the optional synchronous callback method using the signature `function(err, value)` where:
|
|
135
|
-
- `err` - if validation failed, the error reason, otherwise `null`.
|
|
137
|
+
- `err` - if validation failed, the [error](#errors) reason, otherwise `null`.
|
|
136
138
|
- `value` - the validated value with any type conversions and other modifiers applied (the input is left unchanged). `value` can be
|
|
137
|
-
incomplete if validation failed and `abortEarly` is `true`. If callback is not provided, then returns an object with error
|
|
139
|
+
incomplete if validation failed and `abortEarly` is `true`. If callback is not provided, then returns an object with [error](#errors)
|
|
138
140
|
and value properties.
|
|
139
141
|
|
|
140
142
|
```javascript
|
|
@@ -182,7 +184,7 @@ var schema = Joi.alternatives().try([
|
|
|
182
184
|
|
|
183
185
|
### `assert(value, schema, [message])`
|
|
184
186
|
|
|
185
|
-
Validates a value against a schema and throws if validation fails where:
|
|
187
|
+
Validates a value against a schema and [throws](#errors) if validation fails where:
|
|
186
188
|
- `value` - the value to validate.
|
|
187
189
|
- `schema` - the schema object.
|
|
188
190
|
- `message` - optional message string prefix added in front of the error message. may also be an Error object.
|
|
@@ -193,7 +195,7 @@ Joi.assert('x', Joi.number());
|
|
|
193
195
|
|
|
194
196
|
### `attempt(value, schema, [message])`
|
|
195
197
|
|
|
196
|
-
Validates a value against a schema, returns valid object, and throws if validation fails where:
|
|
198
|
+
Validates a value against a schema, returns valid object, and [throws](#errors) if validation fails where:
|
|
197
199
|
- `value` - the value to validate.
|
|
198
200
|
- `schema` - the schema object.
|
|
199
201
|
- `message` - optional message string prefix added in front of the error message. may also be an Error object.
|
|
@@ -547,6 +549,20 @@ var schema = Joi.array().items(Joi.string().valid('not allowed').forbidden(), Jo
|
|
|
547
549
|
var schema = Joi.array().items(Joi.string().label('My string').required(), Joi.number().required()); // If this fails it can result in `[ValidationError: "value" does not contain [My string] and 1 other required value(s)]`
|
|
548
550
|
```
|
|
549
551
|
|
|
552
|
+
#### `array.ordered(type)`
|
|
553
|
+
|
|
554
|
+
List the types in sequence order for the array values where:
|
|
555
|
+
- `type` - a **joi** schema object to validate against each array item in sequence order. `type` can be an array of values, or multiple values can be passed as individual arguments.
|
|
556
|
+
|
|
557
|
+
If a given type is `.required()` then there must be a matching item with the same index position in the array.
|
|
558
|
+
Errors will contain the number of items that didn't match. Any unmatched item having a [label](#anylabelname) will be mentioned explicitly.
|
|
559
|
+
|
|
560
|
+
```javascript
|
|
561
|
+
var schema = Joi.array().ordered(Joi.string().required(), Joi.number().required()); // array must have first item as string and second item as number
|
|
562
|
+
var schema = Joi.array().ordered(Joi.string().required()).items(Joi.number().required()); // array must have first item as string and 1 or more subsequent items as number
|
|
563
|
+
var schema = Joi.array().ordered(Joi.string().required(), Joi.number()); // array must have first item as string and optionally second item as number
|
|
564
|
+
```
|
|
565
|
+
|
|
550
566
|
#### `array.min(limit)`
|
|
551
567
|
|
|
552
568
|
Specifies the minimum number of items in the array where:
|
|
@@ -1484,4 +1500,16 @@ var schema = Joi.object().keys({
|
|
|
1484
1500
|
});
|
|
1485
1501
|
|
|
1486
1502
|
Joi.validate({ a: 5, b: { c: 5 } }, schema, { context: { x: 5 } }, function (err, value) {});
|
|
1487
|
-
```
|
|
1503
|
+
```
|
|
1504
|
+
|
|
1505
|
+
## Errors
|
|
1506
|
+
|
|
1507
|
+
Joi throws classical javascript `Error`s containing :
|
|
1508
|
+
- `name` - `ValidationError`.
|
|
1509
|
+
- `details` - an array of errors :
|
|
1510
|
+
- `message` - string with a description of the error.
|
|
1511
|
+
- `path` - dotted path to the key where the error happened.
|
|
1512
|
+
- `type` - type of the error.
|
|
1513
|
+
- `context` - object providing context of the error.
|
|
1514
|
+
- `annotate` - function that returns a string with an annotated version of the object pointing at the places where errors occured.
|
|
1515
|
+
- `_object` - the original object to validate.
|
package/lib/any.js
CHANGED
|
@@ -256,6 +256,8 @@ internals.Any.prototype._allow = function () {
|
|
|
256
256
|
var values = Hoek.flatten(Array.prototype.slice.call(arguments));
|
|
257
257
|
for (var i = 0, il = values.length; i < il; ++i) {
|
|
258
258
|
var value = values[i];
|
|
259
|
+
|
|
260
|
+
Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');
|
|
259
261
|
this._invalids.remove(value);
|
|
260
262
|
this._valids.add(value, this._refs);
|
|
261
263
|
}
|
|
@@ -286,6 +288,8 @@ internals.Any.prototype.invalid = internals.Any.prototype.disallow = internals.A
|
|
|
286
288
|
var values = Hoek.flatten(Array.prototype.slice.call(arguments));
|
|
287
289
|
for (var i = 0, il = values.length; i < il; ++i) {
|
|
288
290
|
value = values[i];
|
|
291
|
+
|
|
292
|
+
Hoek.assert(value !== undefined, 'Cannot call allow/valid/invalid with undefined');
|
|
289
293
|
obj._valids.remove(value);
|
|
290
294
|
obj._invalids.add(value, this._refs);
|
|
291
295
|
}
|
|
@@ -526,7 +530,7 @@ internals.Any.prototype._validate = function (value, state, options, reference)
|
|
|
526
530
|
}
|
|
527
531
|
}
|
|
528
532
|
else {
|
|
529
|
-
finalValue = self._flags.default;
|
|
533
|
+
finalValue = Hoek.clone(self._flags.default);
|
|
530
534
|
}
|
|
531
535
|
}
|
|
532
536
|
|
package/lib/array.js
CHANGED
|
@@ -29,6 +29,7 @@ internals.Array = function () {
|
|
|
29
29
|
Any.call(this);
|
|
30
30
|
this._type = 'array';
|
|
31
31
|
this._inner.items = [];
|
|
32
|
+
this._inner.ordereds = [];
|
|
32
33
|
this._inner.inclusions = [];
|
|
33
34
|
this._inner.exclusions = [];
|
|
34
35
|
this._inner.requireds = [];
|
|
@@ -106,6 +107,7 @@ internals.checkItems = function (items, wasArray, state, options) {
|
|
|
106
107
|
var errored;
|
|
107
108
|
|
|
108
109
|
var requireds = this._inner.requireds.slice();
|
|
110
|
+
var ordereds = this._inner.ordereds.slice();
|
|
109
111
|
var inclusions = this._inner.inclusions.concat(requireds);
|
|
110
112
|
|
|
111
113
|
for (var v = 0, vl = items.length; v < vl; ++v) {
|
|
@@ -131,6 +133,7 @@ internals.checkItems = function (items, wasArray, state, options) {
|
|
|
131
133
|
|
|
132
134
|
for (var i = 0, il = this._inner.exclusions.length; i < il; ++i) {
|
|
133
135
|
res = this._inner.exclusions[i]._validate(item, localState, {}); // Not passing options to use defaults
|
|
136
|
+
|
|
134
137
|
if (!res.errors) {
|
|
135
138
|
errors.push(Errors.create(wasArray ? 'array.excludes' : 'array.excludesSingle', { pos: v, value: item }, { key: state.key, path: localState.path }, options));
|
|
136
139
|
errored = true;
|
|
@@ -147,6 +150,38 @@ internals.checkItems = function (items, wasArray, state, options) {
|
|
|
147
150
|
continue;
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
// Ordered
|
|
154
|
+
if (this._inner.ordereds.length) {
|
|
155
|
+
if (ordereds.length > 0) {
|
|
156
|
+
var ordered = ordereds.shift();
|
|
157
|
+
res = ordered._validate(item, localState, options);
|
|
158
|
+
if (!res.errors) {
|
|
159
|
+
if (ordered._flags.strip) {
|
|
160
|
+
internals.fastSplice(items, v);
|
|
161
|
+
--v;
|
|
162
|
+
--vl;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
items[v] = res.value;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
errors.push(Errors.create('array.ordered', { pos: v, reason: res.errors, value: item }, { key: state.key, path: localState.path }, options));
|
|
170
|
+
if (options.abortEarly) {
|
|
171
|
+
return errors;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
else if (!this._inner.items.length) {
|
|
177
|
+
errors.push(Errors.create('array.orderedLength', { pos: v, limit: this._inner.ordereds.length }, { key: state.key, path: localState.path }, options));
|
|
178
|
+
if (options.abortEarly) {
|
|
179
|
+
return errors;
|
|
180
|
+
}
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
150
185
|
// Requireds
|
|
151
186
|
|
|
152
187
|
var requiredChecks = [];
|
|
@@ -238,10 +273,13 @@ internals.checkItems = function (items, wasArray, state, options) {
|
|
|
238
273
|
internals.fillMissedErrors(errors, requireds, state, options);
|
|
239
274
|
}
|
|
240
275
|
|
|
276
|
+
if (ordereds.length) {
|
|
277
|
+
internals.fillOrderedErrors(errors, ordereds, state, options);
|
|
278
|
+
}
|
|
279
|
+
|
|
241
280
|
return errors.length ? errors : null;
|
|
242
281
|
};
|
|
243
282
|
|
|
244
|
-
|
|
245
283
|
internals.fillMissedErrors = function (errors, requireds, state, options) {
|
|
246
284
|
|
|
247
285
|
var knownMisses = [];
|
|
@@ -269,11 +307,34 @@ internals.fillMissedErrors = function (errors, requireds, state, options) {
|
|
|
269
307
|
}
|
|
270
308
|
};
|
|
271
309
|
|
|
310
|
+
internals.fillOrderedErrors = function (errors, ordereds, state, options) {
|
|
311
|
+
|
|
312
|
+
var requiredOrdereds = [];
|
|
313
|
+
|
|
314
|
+
for (var i = 0, il = ordereds.length; i < il; ++i) {
|
|
315
|
+
var presence = Hoek.reach(ordereds[i], '_flags.presence');
|
|
316
|
+
if (presence === 'required') {
|
|
317
|
+
requiredOrdereds.push(ordereds[i]);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (requiredOrdereds.length) {
|
|
322
|
+
internals.fillMissedErrors(errors, requiredOrdereds, state, options);
|
|
323
|
+
}
|
|
324
|
+
};
|
|
272
325
|
|
|
273
326
|
internals.Array.prototype.describe = function () {
|
|
274
327
|
|
|
275
328
|
var description = Any.prototype.describe.call(this);
|
|
276
329
|
|
|
330
|
+
if (this._inner.ordereds.length) {
|
|
331
|
+
description.orderedItems = [];
|
|
332
|
+
|
|
333
|
+
for (var o = 0, ol = this._inner.ordereds.length; o < ol; ++o) {
|
|
334
|
+
description.orderedItems.push(this._inner.ordereds[o].describe());
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
277
338
|
if (this._inner.items.length) {
|
|
278
339
|
description.items = [];
|
|
279
340
|
|
|
@@ -290,9 +351,22 @@ internals.Array.prototype.items = function () {
|
|
|
290
351
|
|
|
291
352
|
var obj = this.clone();
|
|
292
353
|
|
|
293
|
-
Hoek.flatten(Array.prototype.slice.call(arguments)).forEach(function (type) {
|
|
354
|
+
Hoek.flatten(Array.prototype.slice.call(arguments)).forEach(function (type, index) {
|
|
355
|
+
|
|
356
|
+
try {
|
|
357
|
+
type = Cast.schema(type);
|
|
358
|
+
}
|
|
359
|
+
catch (castErr) {
|
|
360
|
+
if (castErr.hasOwnProperty('path')) {
|
|
361
|
+
castErr.path = index + '.' + castErr.path;
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
castErr.path = index;
|
|
365
|
+
}
|
|
366
|
+
castErr.message += '(' + castErr.path + ')';
|
|
367
|
+
throw castErr;
|
|
368
|
+
}
|
|
294
369
|
|
|
295
|
-
type = Cast.schema(type);
|
|
296
370
|
obj._inner.items.push(type);
|
|
297
371
|
|
|
298
372
|
if (type._flags.presence === 'required') {
|
|
@@ -310,6 +384,32 @@ internals.Array.prototype.items = function () {
|
|
|
310
384
|
};
|
|
311
385
|
|
|
312
386
|
|
|
387
|
+
internals.Array.prototype.ordered = function () {
|
|
388
|
+
|
|
389
|
+
var obj = this.clone();
|
|
390
|
+
|
|
391
|
+
Hoek.flatten(Array.prototype.slice.call(arguments)).forEach(function (type, index) {
|
|
392
|
+
|
|
393
|
+
try {
|
|
394
|
+
type = Cast.schema(type);
|
|
395
|
+
}
|
|
396
|
+
catch (castErr) {
|
|
397
|
+
if (castErr.hasOwnProperty('path')) {
|
|
398
|
+
castErr.path = index + '.' + castErr.path;
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
castErr.path = index;
|
|
402
|
+
}
|
|
403
|
+
castErr.message += '(' + castErr.path + ')';
|
|
404
|
+
throw castErr;
|
|
405
|
+
}
|
|
406
|
+
obj._inner.ordereds.push(type);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
return obj;
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
|
|
313
413
|
internals.Array.prototype.min = function (limit) {
|
|
314
414
|
|
|
315
415
|
Hoek.assert(Hoek.isInteger(limit) && limit >= 0, 'limit must be a positive integer');
|
package/lib/index.js
CHANGED
|
@@ -95,20 +95,28 @@ internals.root = function () {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
var options = count === 3 ? arguments[2] : {};
|
|
98
|
-
var schema =
|
|
98
|
+
var schema = root.compile(arguments[1]);
|
|
99
99
|
|
|
100
100
|
return schema._validateWithOptions(value, options, callback);
|
|
101
101
|
};
|
|
102
102
|
|
|
103
103
|
root.describe = function () {
|
|
104
104
|
|
|
105
|
-
var schema = arguments.length ?
|
|
105
|
+
var schema = arguments.length ? root.compile(arguments[0]) : any;
|
|
106
106
|
return schema.describe();
|
|
107
107
|
};
|
|
108
108
|
|
|
109
109
|
root.compile = function (schema) {
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
try {
|
|
112
|
+
return Cast.schema(schema);
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (err.hasOwnProperty('path')) {
|
|
116
|
+
err.message += '(' + err.path + ')';
|
|
117
|
+
}
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
112
120
|
};
|
|
113
121
|
|
|
114
122
|
root.assert = function (value, schema, message) {
|
|
@@ -122,11 +130,13 @@ internals.root = function () {
|
|
|
122
130
|
var error = result.error;
|
|
123
131
|
if (error) {
|
|
124
132
|
if (!message) {
|
|
125
|
-
|
|
133
|
+
error.message = error.annotate();
|
|
134
|
+
throw error;
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
if (!(message instanceof Error)) {
|
|
129
|
-
|
|
138
|
+
error.message = message + ' ' + error.annotate();
|
|
139
|
+
throw error;
|
|
130
140
|
}
|
|
131
141
|
|
|
132
142
|
throw message;
|
package/lib/language.js
CHANGED
|
@@ -37,6 +37,8 @@ exports.errors = {
|
|
|
37
37
|
min: 'must contain at least {{limit}} items',
|
|
38
38
|
max: 'must contain less than or equal to {{limit}} items',
|
|
39
39
|
length: 'must contain {{limit}} items',
|
|
40
|
+
ordered: 'at position {{pos}} fails because {{reason}}',
|
|
41
|
+
orderedLength: 'at position {{pos}} fails because array must contain at most {{limit}} items',
|
|
40
42
|
sparse: 'must not be a sparse array',
|
|
41
43
|
unique: 'position {{pos}} contains a duplicate value'
|
|
42
44
|
},
|
package/lib/object.js
CHANGED
|
@@ -231,7 +231,7 @@ internals.Object.prototype._base = function (value, state, options) {
|
|
|
231
231
|
(this._flags.allowUnknown !== undefined ? !this._flags.allowUnknown : !options.allowUnknown)) {
|
|
232
232
|
|
|
233
233
|
for (var e = 0, el = unprocessedKeys.length; e < el; ++e) {
|
|
234
|
-
errors.push(Errors.create('object.allowUnknown', null, { key: unprocessedKeys[e], path: state.path + '.' + unprocessedKeys[e] }, options));
|
|
234
|
+
errors.push(Errors.create('object.allowUnknown', null, { key: unprocessedKeys[e], path: state.path + (state.path ? '.' : '') + unprocessedKeys[e] }, options));
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
}
|
|
@@ -296,8 +296,19 @@ internals.Object.prototype.keys = function (schema) {
|
|
|
296
296
|
for (var c = 0, cl = children.length; c < cl; ++c) {
|
|
297
297
|
var key = children[c];
|
|
298
298
|
child = schema[key];
|
|
299
|
-
|
|
300
|
-
|
|
299
|
+
try {
|
|
300
|
+
var cast = Cast.schema(child);
|
|
301
|
+
topo.add({ key: key, schema: cast }, { after: cast._refs, group: key });
|
|
302
|
+
}
|
|
303
|
+
catch (castErr) {
|
|
304
|
+
if (castErr.hasOwnProperty('path')) {
|
|
305
|
+
castErr.path = key + '.' + castErr.path;
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
castErr.path = key;
|
|
309
|
+
}
|
|
310
|
+
throw castErr;
|
|
311
|
+
}
|
|
301
312
|
}
|
|
302
313
|
|
|
303
314
|
obj._inner.children = topo.nodes;
|
|
@@ -366,8 +377,20 @@ internals.Object.prototype.pattern = function (pattern, schema) {
|
|
|
366
377
|
|
|
367
378
|
pattern = new RegExp(pattern.source, pattern.ignoreCase ? 'i' : undefined); // Future version should break this and forbid unsupported regex flags
|
|
368
379
|
|
|
380
|
+
try {
|
|
381
|
+
schema = Cast.schema(schema);
|
|
382
|
+
}
|
|
383
|
+
catch (castErr) {
|
|
384
|
+
if (castErr.hasOwnProperty('path')) {
|
|
385
|
+
castErr.message += '(' + castErr.path + ')';
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
throw castErr;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
|
|
369
392
|
var obj = this.clone();
|
|
370
|
-
obj._inner.patterns.push({ regex: pattern, rule:
|
|
393
|
+
obj._inner.patterns.push({ regex: pattern, rule: schema });
|
|
371
394
|
return obj;
|
|
372
395
|
};
|
|
373
396
|
|
|
@@ -682,7 +705,18 @@ internals.Object.prototype.assert = function (ref, schema, message) {
|
|
|
682
705
|
Hoek.assert(ref.isContext || ref.depth > 1, 'Cannot use assertions for root level references - use direct key rules instead');
|
|
683
706
|
message = message || 'pass the assertion test';
|
|
684
707
|
|
|
685
|
-
var cast
|
|
708
|
+
var cast;
|
|
709
|
+
try {
|
|
710
|
+
cast = Cast.schema(schema);
|
|
711
|
+
}
|
|
712
|
+
catch (castErr) {
|
|
713
|
+
if (castErr.hasOwnProperty('path')) {
|
|
714
|
+
castErr.message += '(' + castErr.path + ')';
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
throw castErr;
|
|
718
|
+
}
|
|
719
|
+
|
|
686
720
|
var key = ref.path[ref.path.length - 1];
|
|
687
721
|
var path = ref.path.join('.');
|
|
688
722
|
|
package/package.json
CHANGED
package/test/any.js
CHANGED
|
@@ -552,6 +552,31 @@ describe('any', function () {
|
|
|
552
552
|
], done);
|
|
553
553
|
});
|
|
554
554
|
|
|
555
|
+
it('should set default value as a clone', function (done) {
|
|
556
|
+
|
|
557
|
+
var defaultValue = { bar: 'val' };
|
|
558
|
+
var schema = Joi.object({ foo: Joi.object().default(defaultValue) });
|
|
559
|
+
var input = {};
|
|
560
|
+
|
|
561
|
+
schema.validate(input, function (err, value) {
|
|
562
|
+
|
|
563
|
+
expect(err).to.not.exist();
|
|
564
|
+
expect(value.foo).to.not.equal(defaultValue);
|
|
565
|
+
expect(value.foo).to.only.deep.include({ bar: 'val' });
|
|
566
|
+
|
|
567
|
+
value.foo.bar = 'mutated';
|
|
568
|
+
|
|
569
|
+
schema.validate(input, function (err2, value2) {
|
|
570
|
+
|
|
571
|
+
expect(err2).to.not.exist();
|
|
572
|
+
expect(value2.foo).to.not.equal(defaultValue);
|
|
573
|
+
expect(value2.foo).to.only.deep.include({ bar: 'val' });
|
|
574
|
+
|
|
575
|
+
done();
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
});
|
|
579
|
+
|
|
555
580
|
it('should not apply default values if the noDefaults option is enquire', function (done) {
|
|
556
581
|
|
|
557
582
|
var schema = Joi.object({
|
|
@@ -1497,8 +1522,72 @@ describe('any', function () {
|
|
|
1497
1522
|
|
|
1498
1523
|
it('strips undefined', function (done) {
|
|
1499
1524
|
|
|
1500
|
-
var
|
|
1501
|
-
|
|
1525
|
+
var any = Joi.any().clone();
|
|
1526
|
+
any._valids.add(undefined);
|
|
1527
|
+
expect(any._valids.values({ stripUndefined: true })).to.not.include(undefined);
|
|
1528
|
+
done();
|
|
1529
|
+
});
|
|
1530
|
+
});
|
|
1531
|
+
|
|
1532
|
+
describe('#allow', function () {
|
|
1533
|
+
|
|
1534
|
+
it('allows valid values to be set', function (done) {
|
|
1535
|
+
|
|
1536
|
+
expect(function () {
|
|
1537
|
+
|
|
1538
|
+
Joi.any().allow(true, 1, 'hello', new Date());
|
|
1539
|
+
}).not.to.throw();
|
|
1540
|
+
done();
|
|
1541
|
+
});
|
|
1542
|
+
|
|
1543
|
+
it('throws when passed undefined', function (done) {
|
|
1544
|
+
|
|
1545
|
+
expect(function () {
|
|
1546
|
+
|
|
1547
|
+
Joi.any().allow(undefined);
|
|
1548
|
+
}).to.throw(Error, 'Cannot call allow/valid/invalid with undefined');
|
|
1549
|
+
done();
|
|
1550
|
+
});
|
|
1551
|
+
});
|
|
1552
|
+
|
|
1553
|
+
describe('#valid', function () {
|
|
1554
|
+
|
|
1555
|
+
it('allows valid values to be set', function (done) {
|
|
1556
|
+
|
|
1557
|
+
expect(function () {
|
|
1558
|
+
|
|
1559
|
+
Joi.any().valid(true, 1, 'hello', new Date());
|
|
1560
|
+
}).not.to.throw();
|
|
1561
|
+
done();
|
|
1562
|
+
});
|
|
1563
|
+
|
|
1564
|
+
it('throws when passed undefined', function (done) {
|
|
1565
|
+
|
|
1566
|
+
expect(function () {
|
|
1567
|
+
|
|
1568
|
+
Joi.any().valid(undefined);
|
|
1569
|
+
}).to.throw(Error, 'Cannot call allow/valid/invalid with undefined');
|
|
1570
|
+
done();
|
|
1571
|
+
});
|
|
1572
|
+
});
|
|
1573
|
+
|
|
1574
|
+
describe('#invalid', function () {
|
|
1575
|
+
|
|
1576
|
+
it('allows invalid values to be set', function (done) {
|
|
1577
|
+
|
|
1578
|
+
expect(function () {
|
|
1579
|
+
|
|
1580
|
+
Joi.any().valid(true, 1, 'hello', new Date());
|
|
1581
|
+
}).not.to.throw();
|
|
1582
|
+
done();
|
|
1583
|
+
});
|
|
1584
|
+
|
|
1585
|
+
it('throws when passed undefined', function (done) {
|
|
1586
|
+
|
|
1587
|
+
expect(function () {
|
|
1588
|
+
|
|
1589
|
+
Joi.any().invalid(undefined);
|
|
1590
|
+
}).to.throw('Cannot call allow/valid/invalid with undefined');
|
|
1502
1591
|
done();
|
|
1503
1592
|
});
|
|
1504
1593
|
});
|
package/test/array.js
CHANGED
|
@@ -85,6 +85,29 @@ describe('array', function () {
|
|
|
85
85
|
});
|
|
86
86
|
});
|
|
87
87
|
|
|
88
|
+
it('shows path to errors in array items', function (done) {
|
|
89
|
+
|
|
90
|
+
expect(function () {
|
|
91
|
+
|
|
92
|
+
Joi.array().items({
|
|
93
|
+
a: {
|
|
94
|
+
b: {
|
|
95
|
+
c: {
|
|
96
|
+
d: undefined
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
}).to.throw(Error, 'Invalid schema content: (0.a.b.c.d)');
|
|
102
|
+
|
|
103
|
+
expect(function () {
|
|
104
|
+
|
|
105
|
+
Joi.array().items({ foo: 'bar' }, undefined);
|
|
106
|
+
}).to.throw(Error, 'Invalid schema content: (1)');
|
|
107
|
+
|
|
108
|
+
done();
|
|
109
|
+
});
|
|
110
|
+
|
|
88
111
|
it('allows zero size', function (done) {
|
|
89
112
|
|
|
90
113
|
var schema = Joi.object({
|
|
@@ -569,7 +592,7 @@ describe('array', function () {
|
|
|
569
592
|
done();
|
|
570
593
|
});
|
|
571
594
|
|
|
572
|
-
it('returns an
|
|
595
|
+
it('returns an items array only if items are specified', function (done) {
|
|
573
596
|
|
|
574
597
|
var schema = Joi.array().items().max(5);
|
|
575
598
|
var desc = schema.describe();
|
|
@@ -577,14 +600,19 @@ describe('array', function () {
|
|
|
577
600
|
done();
|
|
578
601
|
});
|
|
579
602
|
|
|
580
|
-
it('returns a recursively defined array of
|
|
603
|
+
it('returns a recursively defined array of items when specified', function (done) {
|
|
581
604
|
|
|
582
|
-
var schema = Joi.array()
|
|
605
|
+
var schema = Joi.array()
|
|
606
|
+
.items(Joi.number(), Joi.string())
|
|
607
|
+
.items(Joi.boolean().forbidden())
|
|
608
|
+
.ordered(Joi.number(), Joi.string())
|
|
609
|
+
.ordered(Joi.string().required());
|
|
583
610
|
var desc = schema.describe();
|
|
584
611
|
expect(desc.items).to.have.length(3);
|
|
585
612
|
expect(desc).to.deep.equal({
|
|
586
613
|
type: 'array',
|
|
587
614
|
flags: { sparse: false },
|
|
615
|
+
orderedItems: [{ type: 'number', invalids: [Infinity, -Infinity] }, { type: 'string', invalids: [''] }, { type: 'string', invalids: [''], flags: { presence: 'required' } }],
|
|
588
616
|
items: [{ type: 'number', invalids: [Infinity, -Infinity] }, { type: 'string', invalids: [''] }, { type: 'boolean', flags: { presence: 'forbidden' } }]
|
|
589
617
|
});
|
|
590
618
|
|
|
@@ -793,4 +821,229 @@ describe('array', function () {
|
|
|
793
821
|
});
|
|
794
822
|
});
|
|
795
823
|
});
|
|
824
|
+
|
|
825
|
+
describe('#ordered', function () {
|
|
826
|
+
|
|
827
|
+
it('shows path to errors in array ordered items', function (done) {
|
|
828
|
+
|
|
829
|
+
expect(function () {
|
|
830
|
+
|
|
831
|
+
Joi.array().ordered({
|
|
832
|
+
a: {
|
|
833
|
+
b: {
|
|
834
|
+
c: {
|
|
835
|
+
d: undefined
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
}).to.throw(Error, 'Invalid schema content: (0.a.b.c.d)');
|
|
841
|
+
|
|
842
|
+
expect(function () {
|
|
843
|
+
|
|
844
|
+
Joi.array().ordered({ foo: 'bar' }, undefined);
|
|
845
|
+
}).to.throw(Error, 'Invalid schema content: (1)');
|
|
846
|
+
|
|
847
|
+
done();
|
|
848
|
+
});
|
|
849
|
+
|
|
850
|
+
it('validates input against items in order', function (done) {
|
|
851
|
+
|
|
852
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]);
|
|
853
|
+
var input = ['s1', 2];
|
|
854
|
+
schema.validate(input, function (err, value) {
|
|
855
|
+
|
|
856
|
+
expect(err).to.not.exist();
|
|
857
|
+
expect(value).to.deep.equal(['s1', 2]);
|
|
858
|
+
done();
|
|
859
|
+
});
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
it('validates input with optional item', function (done) {
|
|
863
|
+
|
|
864
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]);
|
|
865
|
+
var input = ['s1', 2, 3];
|
|
866
|
+
|
|
867
|
+
schema.validate(input, function (err, value) {
|
|
868
|
+
|
|
869
|
+
expect(err).to.not.exist();
|
|
870
|
+
expect(value).to.deep.equal(['s1', 2, 3]);
|
|
871
|
+
done();
|
|
872
|
+
});
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
it('validates input without optional item', function (done) {
|
|
876
|
+
|
|
877
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]);
|
|
878
|
+
var input = ['s1', 2];
|
|
879
|
+
|
|
880
|
+
schema.validate(input, function (err, value) {
|
|
881
|
+
|
|
882
|
+
expect(err).to.not.exist();
|
|
883
|
+
expect(value).to.deep.equal(['s1', 2]);
|
|
884
|
+
done();
|
|
885
|
+
});
|
|
886
|
+
});
|
|
887
|
+
|
|
888
|
+
it('validates input without optional item', function (done) {
|
|
889
|
+
|
|
890
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required(), Joi.number()]).sparse(true);
|
|
891
|
+
var input = ['s1', 2, undefined];
|
|
892
|
+
|
|
893
|
+
schema.validate(input, function (err, value) {
|
|
894
|
+
|
|
895
|
+
expect(err).to.not.exist();
|
|
896
|
+
expect(value).to.deep.equal(['s1', 2, undefined]);
|
|
897
|
+
done();
|
|
898
|
+
});
|
|
899
|
+
});
|
|
900
|
+
|
|
901
|
+
it('validates input without optional item in a sparse array', function (done) {
|
|
902
|
+
|
|
903
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number(), Joi.number().required()]).sparse(true);
|
|
904
|
+
var input = ['s1', undefined, 3];
|
|
905
|
+
|
|
906
|
+
schema.validate(input, function (err, value) {
|
|
907
|
+
|
|
908
|
+
expect(err).to.not.exist();
|
|
909
|
+
expect(value).to.deep.equal(['s1', undefined, 3]);
|
|
910
|
+
done();
|
|
911
|
+
});
|
|
912
|
+
});
|
|
913
|
+
|
|
914
|
+
it('validates when input matches ordered items and matches regular items', function (done) {
|
|
915
|
+
|
|
916
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]).items(Joi.number());
|
|
917
|
+
var input = ['s1', 2, 3, 4, 5];
|
|
918
|
+
schema.validate(input, function (err, value) {
|
|
919
|
+
|
|
920
|
+
expect(err).to.not.exist();
|
|
921
|
+
expect(value).to.deep.equal(['s1', 2, 3, 4, 5]);
|
|
922
|
+
done();
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
it('errors when input does not match ordered items', function (done) {
|
|
927
|
+
|
|
928
|
+
var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]);
|
|
929
|
+
var input = ['s1', 2];
|
|
930
|
+
schema.validate(input, function (err, value) {
|
|
931
|
+
|
|
932
|
+
expect(err).to.exist();
|
|
933
|
+
expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a number]');
|
|
934
|
+
done();
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
|
|
938
|
+
it('errors when input has more items than ordered items', function (done) {
|
|
939
|
+
|
|
940
|
+
var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]);
|
|
941
|
+
var input = [1, 's2', 3];
|
|
942
|
+
schema.validate(input, function (err, value) {
|
|
943
|
+
|
|
944
|
+
expect(err).to.exist();
|
|
945
|
+
expect(err.message).to.equal('"value" at position 2 fails because array must contain at most 2 items');
|
|
946
|
+
done();
|
|
947
|
+
});
|
|
948
|
+
});
|
|
949
|
+
|
|
950
|
+
it('errors when input has more items than ordered items with abortEarly = false', function (done) {
|
|
951
|
+
|
|
952
|
+
var schema = Joi.array().ordered([Joi.string(), Joi.number()]).options({ abortEarly: false });
|
|
953
|
+
var input = [1, 2, 3, 4, 5];
|
|
954
|
+
schema.validate(input, function (err, value) {
|
|
955
|
+
|
|
956
|
+
expect(err).to.exist();
|
|
957
|
+
expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]. "value" at position 2 fails because array must contain at most 2 items. "value" at position 3 fails because array must contain at most 2 items. "value" at position 4 fails because array must contain at most 2 items');
|
|
958
|
+
expect(err.details).to.have.length(4);
|
|
959
|
+
done();
|
|
960
|
+
});
|
|
961
|
+
});
|
|
962
|
+
|
|
963
|
+
it('errors when input has less items than ordered items', function (done) {
|
|
964
|
+
|
|
965
|
+
var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]);
|
|
966
|
+
var input = [1];
|
|
967
|
+
schema.validate(input, function (err, value) {
|
|
968
|
+
|
|
969
|
+
expect(err).to.exist();
|
|
970
|
+
expect(err.message).to.equal('"value" does not contain 1 required value(s)');
|
|
971
|
+
done();
|
|
972
|
+
});
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
it('errors when input matches ordered items but not matches regular items', function (done) {
|
|
976
|
+
|
|
977
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().required()]).items(Joi.number()).options({ abortEarly: false });
|
|
978
|
+
var input = ['s1', 2, 3, 4, 's5'];
|
|
979
|
+
schema.validate(input, function (err, value) {
|
|
980
|
+
|
|
981
|
+
expect(err).to.exist();
|
|
982
|
+
expect(err.message).to.equal('"value" at position 4 fails because ["4" must be a number]');
|
|
983
|
+
done();
|
|
984
|
+
});
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
it('errors when input does not match ordered items but matches regular items', function (done) {
|
|
988
|
+
|
|
989
|
+
var schema = Joi.array().ordered([Joi.string(), Joi.number()]).items(Joi.number()).options({ abortEarly: false });
|
|
990
|
+
var input = [1, 2, 3, 4, 5];
|
|
991
|
+
schema.validate(input, function (err, value) {
|
|
992
|
+
|
|
993
|
+
expect(err).to.exist();
|
|
994
|
+
expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]');
|
|
995
|
+
done();
|
|
996
|
+
});
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
it('errors when input does not match ordered items not matches regular items', function (done) {
|
|
1000
|
+
|
|
1001
|
+
var schema = Joi.array().ordered([Joi.string(), Joi.number()]).items(Joi.string()).options({ abortEarly: false });
|
|
1002
|
+
var input = [1, 2, 3, 4, 5];
|
|
1003
|
+
schema.validate(input, function (err, value) {
|
|
1004
|
+
|
|
1005
|
+
expect(err).to.exist();
|
|
1006
|
+
expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a string]. "value" at position 2 fails because ["2" must be a string]. "value" at position 3 fails because ["3" must be a string]. "value" at position 4 fails because ["4" must be a string]');
|
|
1007
|
+
expect(err.details).to.have.length(4);
|
|
1008
|
+
done();
|
|
1009
|
+
});
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
it('errors but continues when abortEarly is set to false', function (done) {
|
|
1013
|
+
|
|
1014
|
+
var schema = Joi.array().ordered([Joi.number().required(), Joi.string().required()]).options({ abortEarly: false });
|
|
1015
|
+
var input = ['s1', 2];
|
|
1016
|
+
schema.validate(input, function (err, value) {
|
|
1017
|
+
|
|
1018
|
+
expect(err).to.exist();
|
|
1019
|
+
expect(err.message).to.equal('"value" at position 0 fails because ["0" must be a number]. "value" at position 1 fails because ["1" must be a string]');
|
|
1020
|
+
expect(err.details).to.have.length(2);
|
|
1021
|
+
done();
|
|
1022
|
+
});
|
|
1023
|
+
});
|
|
1024
|
+
|
|
1025
|
+
it('strips item', function (done) {
|
|
1026
|
+
|
|
1027
|
+
var schema = Joi.array().ordered([Joi.string().required(), Joi.number().strip(), Joi.number().required()]);
|
|
1028
|
+
var input = ['s1', 2, 3];
|
|
1029
|
+
schema.validate(input, function (err, value) {
|
|
1030
|
+
|
|
1031
|
+
expect(err).to.not.exist();
|
|
1032
|
+
expect(value).to.deep.equal(['s1', 3]);
|
|
1033
|
+
done();
|
|
1034
|
+
});
|
|
1035
|
+
});
|
|
1036
|
+
|
|
1037
|
+
it('strips multiple items', function (done) {
|
|
1038
|
+
|
|
1039
|
+
var schema = Joi.array().ordered([Joi.string().strip(), Joi.number(), Joi.number().strip()]);
|
|
1040
|
+
var input = ['s1', 2, 3];
|
|
1041
|
+
schema.validate(input, function (err, value) {
|
|
1042
|
+
|
|
1043
|
+
expect(err).to.not.exist();
|
|
1044
|
+
expect(value).to.deep.equal([2]);
|
|
1045
|
+
done();
|
|
1046
|
+
});
|
|
1047
|
+
});
|
|
1048
|
+
});
|
|
796
1049
|
});
|
package/test/errors.js
CHANGED
|
@@ -233,6 +233,41 @@ describe('errors', function () {
|
|
|
233
233
|
});
|
|
234
234
|
});
|
|
235
235
|
|
|
236
|
+
it('has a name that is ValidationError', function (done) {
|
|
237
|
+
|
|
238
|
+
var schema = Joi.number();
|
|
239
|
+
schema.validate('a', function (validateErr) {
|
|
240
|
+
|
|
241
|
+
expect(validateErr).to.exist();
|
|
242
|
+
expect(validateErr.name).to.be.equal('ValidationError');
|
|
243
|
+
|
|
244
|
+
try {
|
|
245
|
+
Joi.assert('a', schema);
|
|
246
|
+
throw new Error('should not reach that');
|
|
247
|
+
}
|
|
248
|
+
catch (assertErr) {
|
|
249
|
+
expect(assertErr.name).to.be.equal('ValidationError');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
try {
|
|
253
|
+
Joi.assert('a', schema, 'foo');
|
|
254
|
+
throw new Error('should not reach that');
|
|
255
|
+
}
|
|
256
|
+
catch (assertErr) {
|
|
257
|
+
expect(assertErr.name).to.be.equal('ValidationError');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
try {
|
|
261
|
+
Joi.assert('a', schema, new Error('foo'));
|
|
262
|
+
throw new Error('should not reach that');
|
|
263
|
+
}
|
|
264
|
+
catch (assertErr) {
|
|
265
|
+
expect(assertErr.name).to.equal('Error');
|
|
266
|
+
done();
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
|
|
236
271
|
describe('#annotate', function () {
|
|
237
272
|
|
|
238
273
|
it('annotates error', function (done) {
|
|
@@ -287,7 +322,7 @@ describe('errors', function () {
|
|
|
287
322
|
it('annotates error within array multiple times on the same element', function (done) {
|
|
288
323
|
|
|
289
324
|
var object = {
|
|
290
|
-
a: [2, 3
|
|
325
|
+
a: [2, 3, 4]
|
|
291
326
|
};
|
|
292
327
|
|
|
293
328
|
var schema = {
|
|
@@ -323,8 +358,8 @@ describe('errors', function () {
|
|
|
323
358
|
it('annotates error within multiple arrays and multiple times on the same element', function (done) {
|
|
324
359
|
|
|
325
360
|
var object = {
|
|
326
|
-
a: [2, 3
|
|
327
|
-
b: [2, 3
|
|
361
|
+
a: [2, 3, 4],
|
|
362
|
+
b: [2, 3, 4]
|
|
328
363
|
};
|
|
329
364
|
|
|
330
365
|
var schema = {
|
package/test/index.js
CHANGED
|
@@ -1658,4 +1658,35 @@ describe('Joi', function () {
|
|
|
1658
1658
|
done();
|
|
1659
1659
|
});
|
|
1660
1660
|
});
|
|
1661
|
+
|
|
1662
|
+
describe('#compile', function () {
|
|
1663
|
+
|
|
1664
|
+
it('throws an error on invalid value', function (done) {
|
|
1665
|
+
|
|
1666
|
+
expect(function () {
|
|
1667
|
+
|
|
1668
|
+
Joi.compile(undefined);
|
|
1669
|
+
}).to.throw(Error, 'Invalid schema content: ');
|
|
1670
|
+
done();
|
|
1671
|
+
});
|
|
1672
|
+
|
|
1673
|
+
it('shows path to errors in object', function (done) {
|
|
1674
|
+
|
|
1675
|
+
var schema = {
|
|
1676
|
+
a: {
|
|
1677
|
+
b: {
|
|
1678
|
+
c: {
|
|
1679
|
+
d: undefined
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
|
|
1685
|
+
expect(function () {
|
|
1686
|
+
|
|
1687
|
+
Joi.compile(schema);
|
|
1688
|
+
}).to.throw(Error, 'Invalid schema content: (a.b.c.d)');
|
|
1689
|
+
done();
|
|
1690
|
+
});
|
|
1691
|
+
});
|
|
1661
1692
|
});
|
package/test/object.js
CHANGED
|
@@ -362,6 +362,17 @@ describe('object', function () {
|
|
|
362
362
|
});
|
|
363
363
|
});
|
|
364
364
|
|
|
365
|
+
it('errors on unknown nested keys with the correct path at the root level', function (done) {
|
|
366
|
+
|
|
367
|
+
var schema = Joi.object({ a: Joi.object().keys({}) });
|
|
368
|
+
var obj = { c: 'hello' };
|
|
369
|
+
schema.validate(obj, function (err, value) {
|
|
370
|
+
|
|
371
|
+
expect(err).to.exist();
|
|
372
|
+
expect(err.details[0].path).to.equal('c');
|
|
373
|
+
done();
|
|
374
|
+
});
|
|
375
|
+
});
|
|
365
376
|
|
|
366
377
|
it('should work on prototype-less objects', function (done) {
|
|
367
378
|
|
|
@@ -881,6 +892,31 @@ describe('object', function () {
|
|
|
881
892
|
|
|
882
893
|
describe('#pattern', function () {
|
|
883
894
|
|
|
895
|
+
it('shows path to errors in schema', function (done) {
|
|
896
|
+
|
|
897
|
+
expect(function () {
|
|
898
|
+
|
|
899
|
+
Joi.object().pattern(/.*/, {
|
|
900
|
+
a: {
|
|
901
|
+
b: {
|
|
902
|
+
c: {
|
|
903
|
+
d: undefined
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
}).to.throw(Error, 'Invalid schema content: (a.b.c.d)');
|
|
909
|
+
|
|
910
|
+
expect(function () {
|
|
911
|
+
|
|
912
|
+
Joi.object().pattern(/.*/, function () {
|
|
913
|
+
|
|
914
|
+
});
|
|
915
|
+
}).to.throw(Error, 'Invalid schema content: ');
|
|
916
|
+
|
|
917
|
+
done();
|
|
918
|
+
});
|
|
919
|
+
|
|
884
920
|
it('validates unknown keys using a pattern', function (done) {
|
|
885
921
|
|
|
886
922
|
var schema = Joi.object({
|
|
@@ -1081,6 +1117,32 @@ describe('object', function () {
|
|
|
1081
1117
|
|
|
1082
1118
|
describe('#assert', function () {
|
|
1083
1119
|
|
|
1120
|
+
it('shows path to errors in schema', function (done) {
|
|
1121
|
+
|
|
1122
|
+
expect(function () {
|
|
1123
|
+
|
|
1124
|
+
Joi.object().assert('a.b', {
|
|
1125
|
+
a: {
|
|
1126
|
+
b: {
|
|
1127
|
+
c: {
|
|
1128
|
+
d: undefined
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
}).to.throw(Error, 'Invalid schema content: (a.b.c.d)');
|
|
1134
|
+
done();
|
|
1135
|
+
});
|
|
1136
|
+
|
|
1137
|
+
it('shows errors in schema', function (done) {
|
|
1138
|
+
|
|
1139
|
+
expect(function () {
|
|
1140
|
+
|
|
1141
|
+
Joi.object().assert('a.b', undefined);
|
|
1142
|
+
}).to.throw(Error, 'Invalid schema content: ');
|
|
1143
|
+
done();
|
|
1144
|
+
});
|
|
1145
|
+
|
|
1084
1146
|
it('validates upwards reference', function (done) {
|
|
1085
1147
|
|
|
1086
1148
|
var schema = Joi.object({
|