joi 8.4.2 → 9.0.0-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.
package/test/number.js ADDED
@@ -0,0 +1,836 @@
1
+ 'use strict';
2
+
3
+ // Load modules
4
+
5
+ const Lab = require('lab');
6
+ const Code = require('code');
7
+ const Joi = require('../lib');
8
+ const Helper = require('./helper');
9
+
10
+
11
+ // Declare internals
12
+
13
+ const internals = {};
14
+
15
+
16
+ // Test shortcuts
17
+
18
+ const lab = exports.lab = Lab.script();
19
+ const describe = lab.describe;
20
+ const it = lab.it;
21
+ const expect = Code.expect;
22
+
23
+
24
+ describe('number', () => {
25
+
26
+ it('fails on boolean', (done) => {
27
+
28
+ const schema = Joi.number();
29
+ Helper.validate(schema, [
30
+ [true, false],
31
+ [false, false]
32
+ ], done);
33
+ });
34
+
35
+ describe('validate()', () => {
36
+
37
+ it('should, by default, allow undefined', (done) => {
38
+
39
+ Helper.validate(Joi.number(), [
40
+ [undefined, true]
41
+ ], done);
42
+ });
43
+
44
+ it('should, when .required(), deny undefined', (done) => {
45
+
46
+ Helper.validate(Joi.number().required(), [
47
+ [undefined, false]
48
+ ], done);
49
+ });
50
+
51
+ it('should return false for denied value', (done) => {
52
+
53
+ const text = Joi.number().invalid(50);
54
+ text.validate(50, (err, value) => {
55
+
56
+ expect(err).to.exist();
57
+ done();
58
+ });
59
+ });
60
+
61
+ it('should validate integer', (done) => {
62
+
63
+ const t = Joi.number().integer();
64
+ Helper.validate(t, [
65
+ [100, true],
66
+ [0, true],
67
+ [null, false],
68
+ [1.02, false],
69
+ [0.01, false]
70
+ ], done);
71
+ });
72
+
73
+ it('should return false for Infinity', (done) => {
74
+
75
+ const t = Joi.number();
76
+ Helper.validate(t, [
77
+ [Infinity, false],
78
+ [-Infinity, false]
79
+ ], done);
80
+ });
81
+
82
+ it('should return true for allowed Infinity', (done) => {
83
+
84
+ const t = Joi.number().allow(Infinity, -Infinity);
85
+ Helper.validate(t, [
86
+ [Infinity, true],
87
+ [-Infinity, true]
88
+ ], done);
89
+ });
90
+
91
+ it('can accept string numbers', (done) => {
92
+
93
+ const t = Joi.number();
94
+ Helper.validate(t, [
95
+ ['1', true],
96
+ ['100', true],
97
+ ['1e3', true],
98
+ ['1 some text', false],
99
+ ['\t\r', false],
100
+ [' ', false],
101
+ [' 2', true],
102
+ ['\t\r43', true],
103
+ ['43 ', true],
104
+ ['', false]
105
+ ], done);
106
+ });
107
+
108
+ it('required validates correctly', (done) => {
109
+
110
+ const t = Joi.number().required();
111
+ Helper.validate(t, [
112
+ [NaN, false],
113
+ ['100', true]
114
+ ], done);
115
+ });
116
+
117
+ it('converts an object string to a number', (done) => {
118
+
119
+ const config = { a: Joi.number() };
120
+ const obj = { a: '123' };
121
+
122
+ Joi.compile(config).validate(obj, (err, value) => {
123
+
124
+ expect(err).to.not.exist();
125
+ expect(value.a).to.equal(123);
126
+ done();
127
+ });
128
+ });
129
+
130
+ it('converts a string to a number', (done) => {
131
+
132
+ Joi.number().validate('1', (err, value) => {
133
+
134
+ expect(err).to.not.exist();
135
+ expect(value).to.equal(1);
136
+ done();
137
+ });
138
+ });
139
+
140
+ it('errors on null', (done) => {
141
+
142
+ Joi.number().validate(null, (err, value) => {
143
+
144
+ expect(err).to.exist();
145
+ expect(value).to.equal(null);
146
+ done();
147
+ });
148
+ });
149
+
150
+ it('should handle combination of min and max', (done) => {
151
+
152
+ const rule = Joi.number().min(8).max(10);
153
+ Helper.validate(rule, [
154
+ [1, false],
155
+ [11, false],
156
+ [8, true],
157
+ [9, true],
158
+ [null, false]
159
+ ], done);
160
+ });
161
+
162
+ it('should handle combination of min, max, and null allowed', (done) => {
163
+
164
+ const rule = Joi.number().min(8).max(10).allow(null);
165
+ Helper.validate(rule, [
166
+ [1, false],
167
+ [11, false],
168
+ [8, true],
169
+ [9, true],
170
+ [null, true]
171
+ ], done);
172
+ });
173
+
174
+ it('should handle combination of min and positive', (done) => {
175
+
176
+ const rule = Joi.number().min(-3).positive();
177
+ Helper.validate(rule, [
178
+ [1, true],
179
+ [-2, false],
180
+ [8, true],
181
+ [null, false]
182
+ ], done);
183
+ });
184
+
185
+ it('should handle combination of max and positive', (done) => {
186
+
187
+ const rule = Joi.number().max(5).positive();
188
+ Helper.validate(rule, [
189
+ [4, true],
190
+ [-2, false],
191
+ [8, false],
192
+ [null, false]
193
+ ], done);
194
+ });
195
+
196
+ it('should handle combination of min and negative', (done) => {
197
+
198
+ const rule = Joi.number().min(-3).negative();
199
+ Helper.validate(rule, [
200
+ [4, false],
201
+ [-2, true],
202
+ [-4, false],
203
+ [null, false]
204
+ ], done);
205
+ });
206
+
207
+ it('should handle combination of negative and positive', (done) => {
208
+
209
+ const rule = Joi.number().negative().positive();
210
+ Helper.validate(rule, [
211
+ [4, false],
212
+ [-2, false],
213
+ [0, false],
214
+ [null, false]
215
+ ], done);
216
+ });
217
+
218
+ it('should handle combination of negative and allow', (done) => {
219
+
220
+ const rule = Joi.number().negative().allow(1);
221
+ Helper.validate(rule, [
222
+ [1, true],
223
+ [-10, true],
224
+ [8, false],
225
+ [0, false],
226
+ [null, false]
227
+ ], done);
228
+ });
229
+
230
+ it('should handle combination of positive and allow', (done) => {
231
+
232
+ const rule = Joi.number().positive().allow(-1);
233
+ Helper.validate(rule, [
234
+ [1, true],
235
+ [-1, true],
236
+ [8, true],
237
+ [-10, false],
238
+ [null, false]
239
+ ], done);
240
+ });
241
+
242
+ it('should handle combination of positive, allow, and null allowed', (done) => {
243
+
244
+ const rule = Joi.number().positive().allow(-1).allow(null);
245
+ Helper.validate(rule, [
246
+ [1, true],
247
+ [-1, true],
248
+ [8, true],
249
+ [-10, false],
250
+ [null, true]
251
+ ], done);
252
+ });
253
+
254
+ it('should handle combination of negative, allow, and null allowed', (done) => {
255
+
256
+ const rule = Joi.number().negative().allow(1).allow(null);
257
+ Helper.validate(rule, [
258
+ [1, true],
259
+ [-10, true],
260
+ [8, false],
261
+ [0, false],
262
+ [null, true]
263
+ ], done);
264
+ });
265
+
266
+ it('should handle combination of positive, allow, null allowed, and invalid', (done) => {
267
+
268
+ const rule = Joi.number().positive().allow(-1).allow(null).invalid(1);
269
+ Helper.validate(rule, [
270
+ [1, false],
271
+ [-1, true],
272
+ [8, true],
273
+ [-10, false],
274
+ [null, true]
275
+ ], done);
276
+ });
277
+
278
+ it('should handle combination of negative, allow, null allowed, and invalid', (done) => {
279
+
280
+ const rule = Joi.number().negative().allow(1).allow(null).invalid(-5);
281
+ Helper.validate(rule, [
282
+ [1, true],
283
+ [-10, true],
284
+ [-5, false],
285
+ [8, false],
286
+ [0, false],
287
+ [null, true]
288
+ ], done);
289
+ });
290
+
291
+ it('should handle combination of min, max, and allow', (done) => {
292
+
293
+ const rule = Joi.number().min(8).max(10).allow(1);
294
+ Helper.validate(rule, [
295
+ [1, true],
296
+ [11, false],
297
+ [8, true],
298
+ [9, true],
299
+ [null, false]
300
+ ], done);
301
+ });
302
+
303
+ it('should handle combination of min, max, allow, and null allowed', (done) => {
304
+
305
+ const rule = Joi.number().min(8).max(10).allow(1).allow(null);
306
+ Helper.validate(rule, [
307
+ [1, true],
308
+ [11, false],
309
+ [8, true],
310
+ [9, true],
311
+ [null, true]
312
+ ], done);
313
+ });
314
+
315
+ it('should handle combination of min, max, allow, and invalid', (done) => {
316
+
317
+ const rule = Joi.number().min(8).max(10).allow(1).invalid(9);
318
+ Helper.validate(rule, [
319
+ [1, true],
320
+ [11, false],
321
+ [8, true],
322
+ [9, false],
323
+ [null, false]
324
+ ], done);
325
+ });
326
+
327
+ it('should handle combination of min, max, allow, invalid, and null allowed', (done) => {
328
+
329
+ const rule = Joi.number().min(8).max(10).allow(1).invalid(9).allow(null);
330
+ Helper.validate(rule, [
331
+ [1, true],
332
+ [11, false],
333
+ [8, true],
334
+ [9, false],
335
+ [null, true]
336
+ ], done);
337
+ });
338
+
339
+ it('should handle combination of min, max, and integer', (done) => {
340
+
341
+ const rule = Joi.number().min(8).max(10).integer();
342
+ Helper.validate(rule, [
343
+ [1, false],
344
+ [11, false],
345
+ [8, true],
346
+ [9, true],
347
+ [9.1, false],
348
+ [null, false]
349
+ ], done);
350
+ });
351
+
352
+ it('should handle combination of min, max, integer, and allow', (done) => {
353
+
354
+ const rule = Joi.number().min(8).max(10).integer().allow(9.1);
355
+ Helper.validate(rule, [
356
+ [1, false],
357
+ [11, false],
358
+ [8, true],
359
+ [9, true],
360
+ [9.1, true],
361
+ [9.2, false],
362
+ [null, false]
363
+ ], done);
364
+ });
365
+
366
+ it('should handle combination of min, max, integer, allow, and invalid', (done) => {
367
+
368
+ const rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8);
369
+ Helper.validate(rule, [
370
+ [1, false],
371
+ [11, false],
372
+ [8, false],
373
+ [9, true],
374
+ [9.1, true],
375
+ [9.2, false],
376
+ [null, false]
377
+ ], done);
378
+ });
379
+
380
+ it('should handle combination of min, max, integer, allow, invalid, and null allowed', (done) => {
381
+
382
+ const rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8).allow(null);
383
+ Helper.validate(rule, [
384
+ [1, false],
385
+ [11, false],
386
+ [8, false],
387
+ [9, true],
388
+ [9.1, true],
389
+ [9.2, false],
390
+ [null, true]
391
+ ], done);
392
+ });
393
+
394
+ it('should handle limiting the number of decimal places', (done) => {
395
+
396
+ const rule = Joi.number().precision(1).options({ convert: false });
397
+ Helper.validate(rule, [
398
+ [1, true],
399
+ [9.1, true],
400
+ [9.21, false],
401
+ [9.9999, false],
402
+ [9.999e99, true],
403
+ [9.9e-99, false],
404
+ [9.9e3, true],
405
+ [null, false]
406
+ ], done);
407
+ });
408
+
409
+ it('should handle combination of min, max, integer, allow, invalid, null allowed and precision', (done) => {
410
+
411
+ const rule = Joi.number().min(8).max(10).integer().allow(9.1).invalid(8).allow(null).precision(1).options({ convert: false });
412
+ Helper.validate(rule, [
413
+ [1, false],
414
+ [11, false],
415
+ [8, false],
416
+ [9, true],
417
+ [9.1, true],
418
+ [9.11, false],
419
+ [9.2, false],
420
+ [9.22, false],
421
+ [null, true]
422
+ ], done);
423
+ });
424
+
425
+ it('should handle combination of greater and less', (done) => {
426
+
427
+ const rule = Joi.number().greater(5).less(10);
428
+ Helper.validate(rule, [
429
+ [0, false],
430
+ [11, false],
431
+ [5, false],
432
+ [10, false],
433
+ [8, true],
434
+ [5.01, true],
435
+ [9.99, true],
436
+ [null, false]
437
+ ], done);
438
+ });
439
+
440
+ it('should handle combination of greater, less, and integer', (done) => {
441
+
442
+ const rule = Joi.number().integer().greater(5).less(10);
443
+ Helper.validate(rule, [
444
+ [0, false],
445
+ [11, false],
446
+ [5, false],
447
+ [10, false],
448
+ [6, true],
449
+ [9, true],
450
+ [5.01, false],
451
+ [9.99, false]
452
+ ], done);
453
+ });
454
+
455
+ it('should handle combination of greater, less, and null allowed', (done) => {
456
+
457
+ const rule = Joi.number().greater(5).less(10).allow(null);
458
+ Helper.validate(rule, [
459
+ [0, false],
460
+ [11, false],
461
+ [5, false],
462
+ [10, false],
463
+ [8, true],
464
+ [5.01, true],
465
+ [9.99, true],
466
+ [null, true]
467
+ ], done);
468
+ });
469
+
470
+ it('should handle combination of greater, less, invalid, and allow', (done) => {
471
+
472
+ const rule = Joi.number().greater(5).less(10).invalid(6).allow(-3);
473
+ Helper.validate(rule, [
474
+ [0, false],
475
+ [11, false],
476
+ [5, false],
477
+ [10, false],
478
+ [6, false],
479
+ [8, true],
480
+ [5.01, true],
481
+ [9.99, true],
482
+ [-3, true],
483
+ [null, false]
484
+ ], done);
485
+ });
486
+ });
487
+
488
+ it('should instantiate separate copies on invocation', (done) => {
489
+
490
+ const result1 = Joi.number().min(5);
491
+ const result2 = Joi.number().max(5);
492
+
493
+ expect(Object.keys(result1)).to.not.equal(Object.keys(result2));
494
+ done();
495
+ });
496
+
497
+ it('should show resulting object with #valueOf', (done) => {
498
+
499
+ const result = Joi.number().min(5);
500
+ expect(result.valueOf()).to.exist();
501
+ done();
502
+ });
503
+
504
+ describe('error message', () => {
505
+
506
+ it('should display correctly for int type', (done) => {
507
+
508
+ const t = Joi.number().integer();
509
+ Joi.compile(t).validate('1.1', (err, value) => {
510
+
511
+ expect(err.message).to.contain('integer');
512
+ done();
513
+ });
514
+ });
515
+ });
516
+
517
+ describe('min()', () => {
518
+
519
+ it('throws when limit is not a number', (done) => {
520
+
521
+ expect(() => {
522
+
523
+ Joi.number().min('a');
524
+ }).to.throw('limit must be a number or reference');
525
+ done();
526
+ });
527
+
528
+ it('supports 64bit numbers', (done) => {
529
+
530
+ const schema = Joi.number().min(1394035612500);
531
+ const input = 1394035612552;
532
+
533
+ schema.validate(input, (err, value) => {
534
+
535
+ expect(err).to.not.exist();
536
+ expect(value).to.equal(input);
537
+ done();
538
+ });
539
+ });
540
+
541
+ it('accepts references as min value', (done) => {
542
+
543
+ const schema = Joi.object({ a: Joi.number(), b: Joi.number().min(Joi.ref('a')) });
544
+
545
+ Helper.validate(schema, [
546
+ [{ a: 42, b: 1337 }, true],
547
+ [{ a: 1337, b: 42 }, false],
548
+ [{ a: '1337', b: 42 }, false, null, 'child "b" fails because ["b" must be larger than or equal to 1337]'],
549
+ [{ a: 2.4, b: 4.2 }, true],
550
+ [{ a: 4.2, b: 4.20000001 }, true],
551
+ [{ a: 4.20000001, b: 4.2 }, false],
552
+ [{ a: 4.2, b: 2.4 }, false, null, 'child "b" fails because ["b" must be larger than or equal to 4.2]']
553
+ ], done);
554
+ });
555
+
556
+ it('accepts context references as min value', (done) => {
557
+
558
+ const schema = Joi.object({ b: Joi.number().min(Joi.ref('$a')) });
559
+
560
+ Helper.validate(schema, [
561
+ [{ b: 1337 }, true, { context: { a: 42 } }],
562
+ [{ b: 42 }, false, { context: { a: 1337 } }],
563
+ [{ b: 4.2 }, true, { context: { a: 2.4 } }],
564
+ [{ b: 4.20000001 }, true, { context: { a: 4.2 } }],
565
+ [{ b: 4.2 }, false, { context: { a: 4.20000001 } }],
566
+ [{ b: 2.4 }, false, { context: { a: 4.2 } }, 'child "b" fails because ["b" must be larger than or equal to 4.2]']
567
+ ], done);
568
+ });
569
+
570
+ it('errors if reference is not a number', (done) => {
571
+
572
+ const schema = Joi.object({ a: Joi.string(), b: Joi.number().min(Joi.ref('a')) });
573
+
574
+ Helper.validate(schema, [
575
+ [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]']
576
+ ], done);
577
+ });
578
+
579
+ it('errors if context reference is not a number', (done) => {
580
+
581
+ const schema = Joi.object({ b: Joi.number().min(Joi.ref('$a')) });
582
+
583
+ Helper.validate(schema, [
584
+ [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]']
585
+ ], done);
586
+ });
587
+ });
588
+
589
+ describe('max()', () => {
590
+
591
+ it('throws when limit is not a number', (done) => {
592
+
593
+ expect(() => {
594
+
595
+ Joi.number().max('a');
596
+ }).to.throw('limit must be a number or reference');
597
+ done();
598
+ });
599
+
600
+ it('accepts references as max value', (done) => {
601
+
602
+ const schema = Joi.object({ a: Joi.number(), b: Joi.number().max(Joi.ref('a')) });
603
+
604
+ Helper.validate(schema, [
605
+ [{ a: 1337, b: 42 }, true],
606
+ [{ a: 42, b: 1337 }, false],
607
+ [{ a: '42', b: 1337 }, false, null, 'child "b" fails because ["b" must be less than or equal to 42]'],
608
+ [{ a: 4.2, b: 2.4 }, true],
609
+ [{ a: 4.2, b: 4.20000001 }, false],
610
+ [{ a: 4.20000001, b: 4.2 }, true],
611
+ [{ a: 2.4, b: 4.2 }, false, null, 'child "b" fails because ["b" must be less than or equal to 2.4]']
612
+ ], done);
613
+ });
614
+
615
+ it('accepts context references as max value', (done) => {
616
+
617
+ const schema = Joi.object({ b: Joi.number().max(Joi.ref('$a')) });
618
+
619
+ Helper.validate(schema, [
620
+ [{ b: 42 }, true, { context: { a: 1337 } }],
621
+ [{ b: 1337 }, false, { context: { a: 42 } }],
622
+ [{ b: 2.4 }, true, { context: { a: 4.2 } }],
623
+ [{ b: 4.20000001 }, false, { context: { a: 4.2 } }],
624
+ [{ b: 4.2 }, true, { context: { a: 4.20000001 } }],
625
+ [{ b: 4.2 }, false, { context: { a: 2.4 } }, 'child "b" fails because ["b" must be less than or equal to 2.4]']
626
+ ], done);
627
+ });
628
+
629
+ it('errors if reference is not a number', (done) => {
630
+
631
+ const schema = Joi.object({ a: Joi.string(), b: Joi.number().max(Joi.ref('a')) });
632
+
633
+ Helper.validate(schema, [
634
+ [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]']
635
+ ], done);
636
+ });
637
+
638
+ it('errors if context reference is not a number', (done) => {
639
+
640
+ const schema = Joi.object({ b: Joi.number().max(Joi.ref('$a')) });
641
+
642
+ Helper.validate(schema, [
643
+ [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]']
644
+ ], done);
645
+ });
646
+ });
647
+
648
+ describe('less()', () => {
649
+
650
+ it('throws when limit is not a number', (done) => {
651
+
652
+ expect(() => {
653
+
654
+ Joi.number().less('a');
655
+ }).to.throw('limit must be a number or reference');
656
+ done();
657
+ });
658
+
659
+ it('accepts references as less value', (done) => {
660
+
661
+ const schema = Joi.object({ a: Joi.number(), b: Joi.number().less(Joi.ref('a')) });
662
+
663
+ Helper.validate(schema, [
664
+ [{ a: 1337, b: 42 }, true],
665
+ [{ a: 42, b: 1337 }, false],
666
+ [{ a: '42', b: 1337 }, false, null, 'child "b" fails because ["b" must be less than 42]'],
667
+ [{ a: 4.2, b: 2.4 }, true],
668
+ [{ a: 4.2, b: 4.20000001 }, false],
669
+ [{ a: 4.20000001, b: 4.2 }, true],
670
+ [{ a: 2.4, b: 4.2 }, false, null, 'child "b" fails because ["b" must be less than 2.4]']
671
+ ], done);
672
+ });
673
+
674
+ it('accepts context references as less value', (done) => {
675
+
676
+ const schema = Joi.object({ b: Joi.number().less(Joi.ref('$a')) });
677
+
678
+ Helper.validate(schema, [
679
+ [{ b: 42 }, true, { context: { a: 1337 } }],
680
+ [{ b: 1337 }, false, { context: { a: 42 } }],
681
+ [{ b: 2.4 }, true, { context: { a: 4.2 } }],
682
+ [{ b: 4.20000001 }, false, { context: { a: 4.2 } }],
683
+ [{ b: 4.2 }, true, { context: { a: 4.20000001 } }],
684
+ [{ b: 4.2 }, false, { context: { a: 2.4 } }, 'child "b" fails because ["b" must be less than 2.4]']
685
+ ], done);
686
+ });
687
+
688
+ it('errors if reference is not a number', (done) => {
689
+
690
+ const schema = Joi.object({ a: Joi.string(), b: Joi.number().less(Joi.ref('a')) });
691
+
692
+ Helper.validate(schema, [
693
+ [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]']
694
+ ], done);
695
+ });
696
+
697
+ it('errors if context reference is not a number', (done) => {
698
+
699
+ const schema = Joi.object({ a: Joi.string(), b: Joi.number().less(Joi.ref('$a')) });
700
+
701
+ Helper.validate(schema, [
702
+ [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]']
703
+ ], done);
704
+ });
705
+ });
706
+
707
+ describe('greater()', () => {
708
+
709
+ it('throws when limit is not a number', (done) => {
710
+
711
+ expect(() => {
712
+
713
+ Joi.number().greater('a');
714
+ }).to.throw('limit must be a number or reference');
715
+ done();
716
+ });
717
+
718
+ it('accepts references as greater value', (done) => {
719
+
720
+ const schema = Joi.object({ a: Joi.number(), b: Joi.number().greater(Joi.ref('a')) });
721
+
722
+ Helper.validate(schema, [
723
+ [{ a: 42, b: 1337 }, true],
724
+ [{ a: 1337, b: 42 }, false],
725
+ [{ a: '1337', b: 42 }, false, null, 'child "b" fails because ["b" must be greater than 1337]'],
726
+ [{ a: 2.4, b: 4.2 }, true],
727
+ [{ a: 4.2, b: 4.20000001 }, true],
728
+ [{ a: 4.20000001, b: 4.2 }, false],
729
+ [{ a: 4.2, b: 2.4 }, false, null, 'child "b" fails because ["b" must be greater than 4.2]']
730
+ ], done);
731
+ });
732
+
733
+ it('accepts context references as greater value', (done) => {
734
+
735
+ const schema = Joi.object({ b: Joi.number().greater(Joi.ref('$a')) });
736
+
737
+ Helper.validate(schema, [
738
+ [{ b: 1337 }, true, { context: { a: 42 } }],
739
+ [{ b: 42 }, false, { context: { a: 1337 } }],
740
+ [{ b: 4.2 }, true, { context: { a: 2.4 } }],
741
+ [{ b: 4.20000001 }, true, { context: { a: 4.2 } }],
742
+ [{ b: 4.2 }, false, { context: { a: 4.20000001 } }],
743
+ [{ b: 2.4 }, false, { context: { a: 4.2 } }, 'child "b" fails because ["b" must be greater than 4.2]']
744
+ ], done);
745
+ });
746
+
747
+ it('errors if reference is not a number', (done) => {
748
+
749
+ const schema = Joi.object({ a: Joi.string(), b: Joi.number().greater(Joi.ref('a')) });
750
+
751
+ Helper.validate(schema, [
752
+ [{ a: 'abc', b: 42 }, false, null, 'child "b" fails because ["b" references "a" which is not a number]']
753
+ ], done);
754
+ });
755
+
756
+ it('errors if context reference is not a number', (done) => {
757
+
758
+ const schema = Joi.object({ b: Joi.number().greater(Joi.ref('$a')) });
759
+
760
+ Helper.validate(schema, [
761
+ [{ b: 42 }, false, { context: { a: 'abc' } }, 'child "b" fails because ["b" references "a" which is not a number]']
762
+ ], done);
763
+ });
764
+ });
765
+
766
+ describe('precision()', () => {
767
+
768
+ it('converts numbers', (done) => {
769
+
770
+ const rule = Joi.number().precision(4);
771
+ Helper.validate(rule, [
772
+ [1.5, true, null, 1.5],
773
+ [0.12345, true, null, 0.1235],
774
+ [123456, true, null, 123456],
775
+ [123456.123456, true, null, 123456.1235],
776
+ ['123456.123456', true, null, 123456.1235],
777
+ ['abc', false],
778
+ [NaN, false]
779
+ ], done);
780
+ });
781
+ });
782
+
783
+ describe('describe()', () => {
784
+
785
+ it('should describe a minimum of 0', (done) => {
786
+
787
+ const schema = Joi.number().min(0);
788
+ expect(schema.describe()).to.deep.equal({
789
+ type: 'number',
790
+ invalids: [Infinity, -Infinity],
791
+ rules: [
792
+ {
793
+ name: 'min',
794
+ arg: 0
795
+ }
796
+ ]
797
+ });
798
+ done();
799
+ });
800
+ });
801
+
802
+ describe('multiple()', () => {
803
+
804
+ it('throws when multiple is not a number', (done) => {
805
+
806
+ expect(() => {
807
+
808
+ Joi.number().multiple('a');
809
+ }).to.throw('multiple must be an integer');
810
+ done();
811
+ });
812
+
813
+ it('throws when multiple is 0', (done) => {
814
+
815
+ expect(() => {
816
+
817
+ Joi.number().multiple(0);
818
+ }).to.throw('multiple must be greater than 0');
819
+ done();
820
+ });
821
+
822
+ it('should handle multiples correctly', (done) => {
823
+
824
+ const rule = Joi.number().multiple(3);
825
+ Helper.validate(rule, [
826
+ [0, true], // 0 is a multiple of every integer
827
+ [3, true],
828
+ [4, false],
829
+ [9, true],
830
+ ['a', false],
831
+ [9.1, false],
832
+ [8.9, false]
833
+ ], done);
834
+ });
835
+ });
836
+ });