chai 5.1.2 → 5.2.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/.prettierrc.json +10 -0
- package/README.md +1 -1
- package/chai.js +892 -542
- package/eslint.config.js +15 -0
- package/lib/chai/assertion.js +181 -141
- package/lib/chai/config.js +0 -2
- package/lib/chai/core/assertions.js +760 -538
- package/lib/chai/interface/assert.js +437 -260
- package/lib/chai/interface/expect.js +11 -7
- package/lib/chai/interface/should.js +27 -21
- package/lib/chai/utils/addChainableMethod.js +69 -70
- package/lib/chai/utils/addLengthGuard.js +18 -5
- package/lib/chai/utils/addMethod.js +4 -5
- package/lib/chai/utils/addProperty.js +27 -28
- package/lib/chai/utils/expectTypes.js +18 -10
- package/lib/chai/utils/flag.js +4 -3
- package/lib/chai/utils/getMessage.js +18 -12
- package/lib/chai/utils/getOperator.js +7 -7
- package/lib/chai/utils/getProperties.js +2 -2
- package/lib/chai/utils/index.js +8 -2
- package/lib/chai/utils/inspect.js +3 -3
- package/lib/chai/utils/isNaN.js +1 -20
- package/lib/chai/utils/isProxyEnabled.js +4 -2
- package/lib/chai/utils/objDisplay.js +7 -6
- package/lib/chai/utils/overwriteChainableMethod.js +15 -14
- package/lib/chai/utils/overwriteMethod.js +8 -9
- package/lib/chai/utils/overwriteProperty.js +38 -39
- package/lib/chai/utils/proxify.js +40 -29
- package/lib/chai/utils/test.js +2 -2
- package/lib/chai/utils/transferFlags.js +9 -4
- package/lib/chai/utils/type-detect.js +1 -1
- package/lib/chai.js +2 -1
- package/package.json +15 -7
- package/tsconfig.json +18 -0
- package/lib/chai/utils/getEnumerableProperties.js +0 -25
- package/register-assert.cjs +0 -3
- package/register-expect.cjs +0 -3
- package/register-should.cjs +0 -3
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import {Assertion} from '../assertion.js';
|
|
9
9
|
import {AssertionError} from 'assertion-error';
|
|
10
10
|
import * as _ from '../utils/index.js';
|
|
11
|
+
import {config} from '../config.js';
|
|
11
12
|
|
|
12
13
|
const {flag} = _;
|
|
13
14
|
|
|
@@ -42,10 +43,25 @@ const {flag} = _;
|
|
|
42
43
|
* @public
|
|
43
44
|
*/
|
|
44
45
|
|
|
45
|
-
[
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
[
|
|
47
|
+
'to',
|
|
48
|
+
'be',
|
|
49
|
+
'been',
|
|
50
|
+
'is',
|
|
51
|
+
'and',
|
|
52
|
+
'has',
|
|
53
|
+
'have',
|
|
54
|
+
'with',
|
|
55
|
+
'that',
|
|
56
|
+
'which',
|
|
57
|
+
'at',
|
|
58
|
+
'of',
|
|
59
|
+
'same',
|
|
60
|
+
'but',
|
|
61
|
+
'does',
|
|
62
|
+
'still',
|
|
63
|
+
'also'
|
|
64
|
+
].forEach(function (chain) {
|
|
49
65
|
Assertion.addProperty(chain);
|
|
50
66
|
});
|
|
51
67
|
|
|
@@ -239,11 +255,16 @@ Assertion.addProperty('all', function () {
|
|
|
239
255
|
});
|
|
240
256
|
|
|
241
257
|
const functionTypes = {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
258
|
+
function: [
|
|
259
|
+
'function',
|
|
260
|
+
'asyncfunction',
|
|
261
|
+
'generatorfunction',
|
|
262
|
+
'asyncgeneratorfunction'
|
|
263
|
+
],
|
|
264
|
+
asyncfunction: ['asyncfunction', 'asyncgeneratorfunction'],
|
|
265
|
+
generatorfunction: ['generatorfunction', 'asyncgeneratorfunction'],
|
|
266
|
+
asyncgeneratorfunction: ['asyncgeneratorfunction']
|
|
267
|
+
};
|
|
247
268
|
|
|
248
269
|
/**
|
|
249
270
|
* ### .a(type[, msg])
|
|
@@ -304,25 +325,25 @@ const functionTypes = {
|
|
|
304
325
|
* @namespace BDD
|
|
305
326
|
* @public
|
|
306
327
|
*/
|
|
307
|
-
function an
|
|
328
|
+
function an(type, msg) {
|
|
308
329
|
if (msg) flag(this, 'message', msg);
|
|
309
330
|
type = type.toLowerCase();
|
|
310
|
-
|
|
311
|
-
|
|
331
|
+
let obj = flag(this, 'object'),
|
|
332
|
+
article = ~['a', 'e', 'i', 'o', 'u'].indexOf(type.charAt(0)) ? 'an ' : 'a ';
|
|
312
333
|
|
|
313
334
|
const detectedType = _.type(obj).toLowerCase();
|
|
314
335
|
|
|
315
336
|
if (functionTypes['function'].includes(type)) {
|
|
316
337
|
this.assert(
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
338
|
+
functionTypes[type].includes(detectedType),
|
|
339
|
+
'expected #{this} to be ' + article + type,
|
|
340
|
+
'expected #{this} not to be ' + article + type
|
|
320
341
|
);
|
|
321
342
|
} else {
|
|
322
343
|
this.assert(
|
|
323
|
-
type === detectedType
|
|
324
|
-
|
|
325
|
-
|
|
344
|
+
type === detectedType,
|
|
345
|
+
'expected #{this} to be ' + article + type,
|
|
346
|
+
'expected #{this} not to be ' + article + type
|
|
326
347
|
);
|
|
327
348
|
}
|
|
328
349
|
}
|
|
@@ -331,7 +352,6 @@ Assertion.addChainableMethod('an', an);
|
|
|
331
352
|
Assertion.addChainableMethod('a', an);
|
|
332
353
|
|
|
333
354
|
/**
|
|
334
|
-
*
|
|
335
355
|
* @param {unknown} a
|
|
336
356
|
* @param {unknown} b
|
|
337
357
|
* @returns {boolean}
|
|
@@ -340,10 +360,8 @@ function SameValueZero(a, b) {
|
|
|
340
360
|
return (_.isNaN(a) && _.isNaN(b)) || a === b;
|
|
341
361
|
}
|
|
342
362
|
|
|
343
|
-
/**
|
|
344
|
-
|
|
345
|
-
*/
|
|
346
|
-
function includeChainingBehavior () {
|
|
363
|
+
/** */
|
|
364
|
+
function includeChainingBehavior() {
|
|
347
365
|
flag(this, 'contains', true);
|
|
348
366
|
}
|
|
349
367
|
|
|
@@ -493,21 +511,21 @@ function includeChainingBehavior () {
|
|
|
493
511
|
* @namespace BDD
|
|
494
512
|
* @public
|
|
495
513
|
*/
|
|
496
|
-
function include
|
|
514
|
+
function include(val, msg) {
|
|
497
515
|
if (msg) flag(this, 'message', msg);
|
|
498
516
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
517
|
+
let obj = flag(this, 'object'),
|
|
518
|
+
objType = _.type(obj).toLowerCase(),
|
|
519
|
+
flagMsg = flag(this, 'message'),
|
|
520
|
+
negate = flag(this, 'negate'),
|
|
521
|
+
ssfi = flag(this, 'ssfi'),
|
|
522
|
+
isDeep = flag(this, 'deep'),
|
|
523
|
+
descriptor = isDeep ? 'deep ' : '',
|
|
524
|
+
isEql = isDeep ? flag(this, 'eql') : SameValueZero;
|
|
507
525
|
|
|
508
526
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
509
527
|
|
|
510
|
-
|
|
528
|
+
let included = false;
|
|
511
529
|
|
|
512
530
|
switch (objType) {
|
|
513
531
|
case 'string':
|
|
@@ -546,36 +564,39 @@ function include (val, msg) {
|
|
|
546
564
|
if (isDeep) {
|
|
547
565
|
included = obj.some(function (item) {
|
|
548
566
|
return isEql(item, val);
|
|
549
|
-
})
|
|
567
|
+
});
|
|
550
568
|
} else {
|
|
551
569
|
included = obj.indexOf(val) !== -1;
|
|
552
570
|
}
|
|
553
571
|
break;
|
|
554
572
|
|
|
555
|
-
default:
|
|
573
|
+
default: {
|
|
556
574
|
// This block is for asserting a subset of properties in an object.
|
|
557
575
|
// `_.expectTypes` isn't used here because `.include` should work with
|
|
558
576
|
// objects with a custom `@@toStringTag`.
|
|
559
577
|
if (val !== Object(val)) {
|
|
560
578
|
throw new AssertionError(
|
|
561
|
-
flagMsg +
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
579
|
+
flagMsg +
|
|
580
|
+
'the given combination of arguments (' +
|
|
581
|
+
objType +
|
|
582
|
+
' and ' +
|
|
583
|
+
_.type(val).toLowerCase() +
|
|
584
|
+
')' +
|
|
585
|
+
' is invalid for this assertion. ' +
|
|
586
|
+
'You can use an array, a map, an object, a set, a string, ' +
|
|
587
|
+
'or a weakset instead of a ' +
|
|
588
|
+
_.type(val).toLowerCase(),
|
|
568
589
|
undefined,
|
|
569
590
|
ssfi
|
|
570
591
|
);
|
|
571
592
|
}
|
|
572
593
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
594
|
+
let props = Object.keys(val);
|
|
595
|
+
let firstErr = null;
|
|
596
|
+
let numErrs = 0;
|
|
576
597
|
|
|
577
598
|
props.forEach(function (prop) {
|
|
578
|
-
|
|
599
|
+
let propAssertion = new Assertion(obj);
|
|
579
600
|
_.transferFlags(this, propAssertion, true);
|
|
580
601
|
flag(propAssertion, 'lockSsfi', true);
|
|
581
602
|
|
|
@@ -603,13 +624,15 @@ function include (val, msg) {
|
|
|
603
624
|
throw firstErr;
|
|
604
625
|
}
|
|
605
626
|
return;
|
|
627
|
+
}
|
|
606
628
|
}
|
|
607
629
|
|
|
608
630
|
// Assert inclusion in collection or substring in a string.
|
|
609
631
|
this.assert(
|
|
610
|
-
included
|
|
611
|
-
|
|
612
|
-
|
|
632
|
+
included,
|
|
633
|
+
'expected #{this} to ' + descriptor + 'include ' + _.inspect(val),
|
|
634
|
+
'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val)
|
|
635
|
+
);
|
|
613
636
|
}
|
|
614
637
|
|
|
615
638
|
Assertion.addChainableMethod('include', include, includeChainingBehavior);
|
|
@@ -654,9 +677,10 @@ Assertion.addChainableMethod('includes', include, includeChainingBehavior);
|
|
|
654
677
|
*/
|
|
655
678
|
Assertion.addProperty('ok', function () {
|
|
656
679
|
this.assert(
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
680
|
+
flag(this, 'object'),
|
|
681
|
+
'expected #{this} to be truthy',
|
|
682
|
+
'expected #{this} to be falsy'
|
|
683
|
+
);
|
|
660
684
|
});
|
|
661
685
|
|
|
662
686
|
/**
|
|
@@ -686,10 +710,10 @@ Assertion.addProperty('ok', function () {
|
|
|
686
710
|
*/
|
|
687
711
|
Assertion.addProperty('true', function () {
|
|
688
712
|
this.assert(
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
713
|
+
true === flag(this, 'object'),
|
|
714
|
+
'expected #{this} to be true',
|
|
715
|
+
'expected #{this} to be false',
|
|
716
|
+
flag(this, 'negate') ? false : true
|
|
693
717
|
);
|
|
694
718
|
});
|
|
695
719
|
|
|
@@ -697,10 +721,10 @@ Assertion.addProperty('numeric', function () {
|
|
|
697
721
|
const object = flag(this, 'object');
|
|
698
722
|
|
|
699
723
|
this.assert(
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
724
|
+
['Number', 'BigInt'].includes(_.type(object)),
|
|
725
|
+
'expected #{this} to be numeric',
|
|
726
|
+
'expected #{this} to not be numeric',
|
|
727
|
+
flag(this, 'negate') ? false : true
|
|
704
728
|
);
|
|
705
729
|
});
|
|
706
730
|
|
|
@@ -720,24 +744,25 @@ Assertion.addProperty('numeric', function () {
|
|
|
720
744
|
* @public
|
|
721
745
|
*/
|
|
722
746
|
Assertion.addProperty('callable', function () {
|
|
723
|
-
const val = flag(this, 'object')
|
|
724
|
-
const ssfi = flag(this, 'ssfi')
|
|
725
|
-
const message = flag(this, 'message')
|
|
726
|
-
const msg = message ? `${message}: ` : ''
|
|
747
|
+
const val = flag(this, 'object');
|
|
748
|
+
const ssfi = flag(this, 'ssfi');
|
|
749
|
+
const message = flag(this, 'message');
|
|
750
|
+
const msg = message ? `${message}: ` : '';
|
|
727
751
|
const negate = flag(this, 'negate');
|
|
728
752
|
|
|
729
|
-
const assertionMessage = negate
|
|
730
|
-
`${msg}expected ${_.inspect(val)} not to be a callable function`
|
|
731
|
-
`${msg}expected ${_.inspect(val)} to be a callable function`;
|
|
753
|
+
const assertionMessage = negate
|
|
754
|
+
? `${msg}expected ${_.inspect(val)} not to be a callable function`
|
|
755
|
+
: `${msg}expected ${_.inspect(val)} to be a callable function`;
|
|
732
756
|
|
|
733
|
-
const isCallable = [
|
|
757
|
+
const isCallable = [
|
|
758
|
+
'Function',
|
|
759
|
+
'AsyncFunction',
|
|
760
|
+
'GeneratorFunction',
|
|
761
|
+
'AsyncGeneratorFunction'
|
|
762
|
+
].includes(_.type(val));
|
|
734
763
|
|
|
735
764
|
if ((isCallable && negate) || (!isCallable && !negate)) {
|
|
736
|
-
throw new AssertionError(
|
|
737
|
-
assertionMessage,
|
|
738
|
-
undefined,
|
|
739
|
-
ssfi
|
|
740
|
-
);
|
|
765
|
+
throw new AssertionError(assertionMessage, undefined, ssfi);
|
|
741
766
|
}
|
|
742
767
|
});
|
|
743
768
|
|
|
@@ -768,10 +793,10 @@ Assertion.addProperty('callable', function () {
|
|
|
768
793
|
*/
|
|
769
794
|
Assertion.addProperty('false', function () {
|
|
770
795
|
this.assert(
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
796
|
+
false === flag(this, 'object'),
|
|
797
|
+
'expected #{this} to be false',
|
|
798
|
+
'expected #{this} to be true',
|
|
799
|
+
flag(this, 'negate') ? true : false
|
|
775
800
|
);
|
|
776
801
|
});
|
|
777
802
|
|
|
@@ -799,9 +824,9 @@ Assertion.addProperty('false', function () {
|
|
|
799
824
|
*/
|
|
800
825
|
Assertion.addProperty('null', function () {
|
|
801
826
|
this.assert(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
827
|
+
null === flag(this, 'object'),
|
|
828
|
+
'expected #{this} to be null',
|
|
829
|
+
'expected #{this} not to be null'
|
|
805
830
|
);
|
|
806
831
|
});
|
|
807
832
|
|
|
@@ -829,9 +854,9 @@ Assertion.addProperty('null', function () {
|
|
|
829
854
|
*/
|
|
830
855
|
Assertion.addProperty('undefined', function () {
|
|
831
856
|
this.assert(
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
857
|
+
undefined === flag(this, 'object'),
|
|
858
|
+
'expected #{this} to be undefined',
|
|
859
|
+
'expected #{this} not to be undefined'
|
|
835
860
|
);
|
|
836
861
|
});
|
|
837
862
|
|
|
@@ -859,9 +884,9 @@ Assertion.addProperty('undefined', function () {
|
|
|
859
884
|
*/
|
|
860
885
|
Assertion.addProperty('NaN', function () {
|
|
861
886
|
this.assert(
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
887
|
+
_.isNaN(flag(this, 'object')),
|
|
888
|
+
'expected #{this} to be NaN',
|
|
889
|
+
'expected #{this} not to be NaN'
|
|
865
890
|
);
|
|
866
891
|
});
|
|
867
892
|
|
|
@@ -897,12 +922,12 @@ Assertion.addProperty('NaN', function () {
|
|
|
897
922
|
* @namespace BDD
|
|
898
923
|
* @public
|
|
899
924
|
*/
|
|
900
|
-
function assertExist
|
|
901
|
-
|
|
925
|
+
function assertExist() {
|
|
926
|
+
let val = flag(this, 'object');
|
|
902
927
|
this.assert(
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
928
|
+
val !== null && val !== undefined,
|
|
929
|
+
'expected #{this} to exist',
|
|
930
|
+
'expected #{this} to not exist'
|
|
906
931
|
);
|
|
907
932
|
}
|
|
908
933
|
|
|
@@ -958,10 +983,10 @@ Assertion.addProperty('exists', assertExist);
|
|
|
958
983
|
* @public
|
|
959
984
|
*/
|
|
960
985
|
Assertion.addProperty('empty', function () {
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
986
|
+
let val = flag(this, 'object'),
|
|
987
|
+
ssfi = flag(this, 'ssfi'),
|
|
988
|
+
flagMsg = flag(this, 'message'),
|
|
989
|
+
itemsCount;
|
|
965
990
|
|
|
966
991
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
967
992
|
|
|
@@ -981,9 +1006,10 @@ Assertion.addProperty('empty', function () {
|
|
|
981
1006
|
undefined,
|
|
982
1007
|
ssfi
|
|
983
1008
|
);
|
|
984
|
-
case 'function':
|
|
985
|
-
|
|
1009
|
+
case 'function': {
|
|
1010
|
+
const msg = flagMsg + '.empty was passed a function ' + _.getName(val);
|
|
986
1011
|
throw new AssertionError(msg.trim(), undefined, ssfi);
|
|
1012
|
+
}
|
|
987
1013
|
default:
|
|
988
1014
|
if (val !== Object(val)) {
|
|
989
1015
|
throw new AssertionError(
|
|
@@ -996,9 +1022,9 @@ Assertion.addProperty('empty', function () {
|
|
|
996
1022
|
}
|
|
997
1023
|
|
|
998
1024
|
this.assert(
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1025
|
+
0 === itemsCount,
|
|
1026
|
+
'expected #{this} to be empty',
|
|
1027
|
+
'expected #{this} not to be empty'
|
|
1002
1028
|
);
|
|
1003
1029
|
});
|
|
1004
1030
|
|
|
@@ -1031,13 +1057,13 @@ Assertion.addProperty('empty', function () {
|
|
|
1031
1057
|
* @namespace BDD
|
|
1032
1058
|
* @public
|
|
1033
1059
|
*/
|
|
1034
|
-
function checkArguments
|
|
1035
|
-
|
|
1036
|
-
|
|
1060
|
+
function checkArguments() {
|
|
1061
|
+
let obj = flag(this, 'object'),
|
|
1062
|
+
type = _.type(obj);
|
|
1037
1063
|
this.assert(
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1064
|
+
'Arguments' === type,
|
|
1065
|
+
'expected #{this} to be arguments but got ' + type,
|
|
1066
|
+
'expected #{this} to not be arguments'
|
|
1041
1067
|
);
|
|
1042
1068
|
}
|
|
1043
1069
|
|
|
@@ -1088,22 +1114,22 @@ Assertion.addProperty('Arguments', checkArguments);
|
|
|
1088
1114
|
* @namespace BDD
|
|
1089
1115
|
* @public
|
|
1090
1116
|
*/
|
|
1091
|
-
function assertEqual
|
|
1117
|
+
function assertEqual(val, msg) {
|
|
1092
1118
|
if (msg) flag(this, 'message', msg);
|
|
1093
|
-
|
|
1119
|
+
let obj = flag(this, 'object');
|
|
1094
1120
|
if (flag(this, 'deep')) {
|
|
1095
|
-
|
|
1121
|
+
let prevLockSsfi = flag(this, 'lockSsfi');
|
|
1096
1122
|
flag(this, 'lockSsfi', true);
|
|
1097
1123
|
this.eql(val);
|
|
1098
1124
|
flag(this, 'lockSsfi', prevLockSsfi);
|
|
1099
1125
|
} else {
|
|
1100
1126
|
this.assert(
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
,
|
|
1105
|
-
|
|
1106
|
-
|
|
1127
|
+
val === obj,
|
|
1128
|
+
'expected #{this} to equal #{exp}',
|
|
1129
|
+
'expected #{this} to not equal #{exp}',
|
|
1130
|
+
val,
|
|
1131
|
+
this._obj,
|
|
1132
|
+
true
|
|
1107
1133
|
);
|
|
1108
1134
|
}
|
|
1109
1135
|
}
|
|
@@ -1154,14 +1180,14 @@ Assertion.addMethod('eq', assertEqual);
|
|
|
1154
1180
|
*/
|
|
1155
1181
|
function assertEql(obj, msg) {
|
|
1156
1182
|
if (msg) flag(this, 'message', msg);
|
|
1157
|
-
|
|
1183
|
+
let eql = flag(this, 'eql');
|
|
1158
1184
|
this.assert(
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
,
|
|
1163
|
-
|
|
1164
|
-
|
|
1185
|
+
eql(obj, flag(this, 'object')),
|
|
1186
|
+
'expected #{this} to deeply equal #{exp}',
|
|
1187
|
+
'expected #{this} to not deeply equal #{exp}',
|
|
1188
|
+
obj,
|
|
1189
|
+
this._obj,
|
|
1190
|
+
true
|
|
1165
1191
|
);
|
|
1166
1192
|
}
|
|
1167
1193
|
|
|
@@ -1210,32 +1236,44 @@ Assertion.addMethod('eqls', assertEql);
|
|
|
1210
1236
|
* @namespace BDD
|
|
1211
1237
|
* @public
|
|
1212
1238
|
*/
|
|
1213
|
-
function assertAbove
|
|
1239
|
+
function assertAbove(n, msg) {
|
|
1214
1240
|
if (msg) flag(this, 'message', msg);
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1241
|
+
let obj = flag(this, 'object'),
|
|
1242
|
+
doLength = flag(this, 'doLength'),
|
|
1243
|
+
flagMsg = flag(this, 'message'),
|
|
1244
|
+
msgPrefix = flagMsg ? flagMsg + ': ' : '',
|
|
1245
|
+
ssfi = flag(this, 'ssfi'),
|
|
1246
|
+
objType = _.type(obj).toLowerCase(),
|
|
1247
|
+
nType = _.type(n).toLowerCase();
|
|
1222
1248
|
|
|
1223
1249
|
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1224
1250
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1225
1251
|
}
|
|
1226
1252
|
|
|
1227
|
-
if (!doLength &&
|
|
1228
|
-
throw new AssertionError(
|
|
1253
|
+
if (!doLength && objType === 'date' && nType !== 'date') {
|
|
1254
|
+
throw new AssertionError(
|
|
1255
|
+
msgPrefix + 'the argument to above must be a date',
|
|
1256
|
+
undefined,
|
|
1257
|
+
ssfi
|
|
1258
|
+
);
|
|
1229
1259
|
} else if (!_.isNumeric(n) && (doLength || _.isNumeric(obj))) {
|
|
1230
|
-
throw new AssertionError(
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1260
|
+
throw new AssertionError(
|
|
1261
|
+
msgPrefix + 'the argument to above must be a number',
|
|
1262
|
+
undefined,
|
|
1263
|
+
ssfi
|
|
1264
|
+
);
|
|
1265
|
+
} else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
|
|
1266
|
+
let printObj = objType === 'string' ? "'" + obj + "'" : obj;
|
|
1267
|
+
throw new AssertionError(
|
|
1268
|
+
msgPrefix + 'expected ' + printObj + ' to be a number or a date',
|
|
1269
|
+
undefined,
|
|
1270
|
+
ssfi
|
|
1271
|
+
);
|
|
1234
1272
|
}
|
|
1235
1273
|
|
|
1236
1274
|
if (doLength) {
|
|
1237
|
-
|
|
1238
|
-
|
|
1275
|
+
let descriptor = 'length',
|
|
1276
|
+
itemsCount;
|
|
1239
1277
|
if (objType === 'map' || objType === 'set') {
|
|
1240
1278
|
descriptor = 'size';
|
|
1241
1279
|
itemsCount = obj.size;
|
|
@@ -1243,18 +1281,20 @@ function assertAbove (n, msg) {
|
|
|
1243
1281
|
itemsCount = obj.length;
|
|
1244
1282
|
}
|
|
1245
1283
|
this.assert(
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
,
|
|
1284
|
+
itemsCount > n,
|
|
1285
|
+
'expected #{this} to have a ' +
|
|
1286
|
+
descriptor +
|
|
1287
|
+
' above #{exp} but got #{act}',
|
|
1288
|
+
'expected #{this} to not have a ' + descriptor + ' above #{exp}',
|
|
1289
|
+
n,
|
|
1290
|
+
itemsCount
|
|
1251
1291
|
);
|
|
1252
1292
|
} else {
|
|
1253
1293
|
this.assert(
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1294
|
+
obj > n,
|
|
1295
|
+
'expected #{this} to be above #{exp}',
|
|
1296
|
+
'expected #{this} to be at most #{exp}',
|
|
1297
|
+
n
|
|
1258
1298
|
);
|
|
1259
1299
|
}
|
|
1260
1300
|
}
|
|
@@ -1306,29 +1346,30 @@ Assertion.addMethod('greaterThan', assertAbove);
|
|
|
1306
1346
|
* @namespace BDD
|
|
1307
1347
|
* @public
|
|
1308
1348
|
*/
|
|
1309
|
-
function assertLeast
|
|
1349
|
+
function assertLeast(n, msg) {
|
|
1310
1350
|
if (msg) flag(this, 'message', msg);
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
,
|
|
1319
|
-
|
|
1351
|
+
let obj = flag(this, 'object'),
|
|
1352
|
+
doLength = flag(this, 'doLength'),
|
|
1353
|
+
flagMsg = flag(this, 'message'),
|
|
1354
|
+
msgPrefix = flagMsg ? flagMsg + ': ' : '',
|
|
1355
|
+
ssfi = flag(this, 'ssfi'),
|
|
1356
|
+
objType = _.type(obj).toLowerCase(),
|
|
1357
|
+
nType = _.type(n).toLowerCase(),
|
|
1358
|
+
errorMessage,
|
|
1359
|
+
shouldThrow = true;
|
|
1320
1360
|
|
|
1321
1361
|
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1322
1362
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1323
1363
|
}
|
|
1324
1364
|
|
|
1325
|
-
if (!doLength &&
|
|
1365
|
+
if (!doLength && objType === 'date' && nType !== 'date') {
|
|
1326
1366
|
errorMessage = msgPrefix + 'the argument to least must be a date';
|
|
1327
1367
|
} else if (!_.isNumeric(n) && (doLength || _.isNumeric(obj))) {
|
|
1328
1368
|
errorMessage = msgPrefix + 'the argument to least must be a number';
|
|
1329
|
-
} else if (!doLength &&
|
|
1330
|
-
|
|
1331
|
-
errorMessage =
|
|
1369
|
+
} else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
|
|
1370
|
+
let printObj = objType === 'string' ? "'" + obj + "'" : obj;
|
|
1371
|
+
errorMessage =
|
|
1372
|
+
msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1332
1373
|
} else {
|
|
1333
1374
|
shouldThrow = false;
|
|
1334
1375
|
}
|
|
@@ -1338,8 +1379,8 @@ function assertLeast (n, msg) {
|
|
|
1338
1379
|
}
|
|
1339
1380
|
|
|
1340
1381
|
if (doLength) {
|
|
1341
|
-
|
|
1342
|
-
|
|
1382
|
+
let descriptor = 'length',
|
|
1383
|
+
itemsCount;
|
|
1343
1384
|
if (objType === 'map' || objType === 'set') {
|
|
1344
1385
|
descriptor = 'size';
|
|
1345
1386
|
itemsCount = obj.size;
|
|
@@ -1347,18 +1388,20 @@ function assertLeast (n, msg) {
|
|
|
1347
1388
|
itemsCount = obj.length;
|
|
1348
1389
|
}
|
|
1349
1390
|
this.assert(
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
,
|
|
1391
|
+
itemsCount >= n,
|
|
1392
|
+
'expected #{this} to have a ' +
|
|
1393
|
+
descriptor +
|
|
1394
|
+
' at least #{exp} but got #{act}',
|
|
1395
|
+
'expected #{this} to have a ' + descriptor + ' below #{exp}',
|
|
1396
|
+
n,
|
|
1397
|
+
itemsCount
|
|
1355
1398
|
);
|
|
1356
1399
|
} else {
|
|
1357
1400
|
this.assert(
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1401
|
+
obj >= n,
|
|
1402
|
+
'expected #{this} to be at least #{exp}',
|
|
1403
|
+
'expected #{this} to be below #{exp}',
|
|
1404
|
+
n
|
|
1362
1405
|
);
|
|
1363
1406
|
}
|
|
1364
1407
|
}
|
|
@@ -1409,29 +1452,30 @@ Assertion.addMethod('greaterThanOrEqual', assertLeast);
|
|
|
1409
1452
|
* @namespace BDD
|
|
1410
1453
|
* @public
|
|
1411
1454
|
*/
|
|
1412
|
-
function assertBelow
|
|
1455
|
+
function assertBelow(n, msg) {
|
|
1413
1456
|
if (msg) flag(this, 'message', msg);
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
,
|
|
1422
|
-
|
|
1457
|
+
let obj = flag(this, 'object'),
|
|
1458
|
+
doLength = flag(this, 'doLength'),
|
|
1459
|
+
flagMsg = flag(this, 'message'),
|
|
1460
|
+
msgPrefix = flagMsg ? flagMsg + ': ' : '',
|
|
1461
|
+
ssfi = flag(this, 'ssfi'),
|
|
1462
|
+
objType = _.type(obj).toLowerCase(),
|
|
1463
|
+
nType = _.type(n).toLowerCase(),
|
|
1464
|
+
errorMessage,
|
|
1465
|
+
shouldThrow = true;
|
|
1423
1466
|
|
|
1424
1467
|
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1425
1468
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1426
1469
|
}
|
|
1427
|
-
|
|
1428
|
-
if (!doLength &&
|
|
1470
|
+
|
|
1471
|
+
if (!doLength && objType === 'date' && nType !== 'date') {
|
|
1429
1472
|
errorMessage = msgPrefix + 'the argument to below must be a date';
|
|
1430
1473
|
} else if (!_.isNumeric(n) && (doLength || _.isNumeric(obj))) {
|
|
1431
1474
|
errorMessage = msgPrefix + 'the argument to below must be a number';
|
|
1432
|
-
} else if (!doLength &&
|
|
1433
|
-
|
|
1434
|
-
errorMessage =
|
|
1475
|
+
} else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
|
|
1476
|
+
let printObj = objType === 'string' ? "'" + obj + "'" : obj;
|
|
1477
|
+
errorMessage =
|
|
1478
|
+
msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1435
1479
|
} else {
|
|
1436
1480
|
shouldThrow = false;
|
|
1437
1481
|
}
|
|
@@ -1441,8 +1485,8 @@ function assertBelow (n, msg) {
|
|
|
1441
1485
|
}
|
|
1442
1486
|
|
|
1443
1487
|
if (doLength) {
|
|
1444
|
-
|
|
1445
|
-
|
|
1488
|
+
let descriptor = 'length',
|
|
1489
|
+
itemsCount;
|
|
1446
1490
|
if (objType === 'map' || objType === 'set') {
|
|
1447
1491
|
descriptor = 'size';
|
|
1448
1492
|
itemsCount = obj.size;
|
|
@@ -1450,18 +1494,20 @@ function assertBelow (n, msg) {
|
|
|
1450
1494
|
itemsCount = obj.length;
|
|
1451
1495
|
}
|
|
1452
1496
|
this.assert(
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
,
|
|
1497
|
+
itemsCount < n,
|
|
1498
|
+
'expected #{this} to have a ' +
|
|
1499
|
+
descriptor +
|
|
1500
|
+
' below #{exp} but got #{act}',
|
|
1501
|
+
'expected #{this} to not have a ' + descriptor + ' below #{exp}',
|
|
1502
|
+
n,
|
|
1503
|
+
itemsCount
|
|
1458
1504
|
);
|
|
1459
1505
|
} else {
|
|
1460
1506
|
this.assert(
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1507
|
+
obj < n,
|
|
1508
|
+
'expected #{this} to be below #{exp}',
|
|
1509
|
+
'expected #{this} to be at least #{exp}',
|
|
1510
|
+
n
|
|
1465
1511
|
);
|
|
1466
1512
|
}
|
|
1467
1513
|
}
|
|
@@ -1513,29 +1559,30 @@ Assertion.addMethod('lessThan', assertBelow);
|
|
|
1513
1559
|
* @namespace BDD
|
|
1514
1560
|
* @public
|
|
1515
1561
|
*/
|
|
1516
|
-
function assertMost
|
|
1562
|
+
function assertMost(n, msg) {
|
|
1517
1563
|
if (msg) flag(this, 'message', msg);
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
,
|
|
1526
|
-
|
|
1564
|
+
let obj = flag(this, 'object'),
|
|
1565
|
+
doLength = flag(this, 'doLength'),
|
|
1566
|
+
flagMsg = flag(this, 'message'),
|
|
1567
|
+
msgPrefix = flagMsg ? flagMsg + ': ' : '',
|
|
1568
|
+
ssfi = flag(this, 'ssfi'),
|
|
1569
|
+
objType = _.type(obj).toLowerCase(),
|
|
1570
|
+
nType = _.type(n).toLowerCase(),
|
|
1571
|
+
errorMessage,
|
|
1572
|
+
shouldThrow = true;
|
|
1527
1573
|
|
|
1528
1574
|
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1529
1575
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1530
1576
|
}
|
|
1531
1577
|
|
|
1532
|
-
if (!doLength &&
|
|
1578
|
+
if (!doLength && objType === 'date' && nType !== 'date') {
|
|
1533
1579
|
errorMessage = msgPrefix + 'the argument to most must be a date';
|
|
1534
1580
|
} else if (!_.isNumeric(n) && (doLength || _.isNumeric(obj))) {
|
|
1535
1581
|
errorMessage = msgPrefix + 'the argument to most must be a number';
|
|
1536
|
-
} else if (!doLength &&
|
|
1537
|
-
|
|
1538
|
-
errorMessage =
|
|
1582
|
+
} else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
|
|
1583
|
+
let printObj = objType === 'string' ? "'" + obj + "'" : obj;
|
|
1584
|
+
errorMessage =
|
|
1585
|
+
msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1539
1586
|
} else {
|
|
1540
1587
|
shouldThrow = false;
|
|
1541
1588
|
}
|
|
@@ -1545,8 +1592,8 @@ function assertMost (n, msg) {
|
|
|
1545
1592
|
}
|
|
1546
1593
|
|
|
1547
1594
|
if (doLength) {
|
|
1548
|
-
|
|
1549
|
-
|
|
1595
|
+
let descriptor = 'length',
|
|
1596
|
+
itemsCount;
|
|
1550
1597
|
if (objType === 'map' || objType === 'set') {
|
|
1551
1598
|
descriptor = 'size';
|
|
1552
1599
|
itemsCount = obj.size;
|
|
@@ -1554,18 +1601,20 @@ function assertMost (n, msg) {
|
|
|
1554
1601
|
itemsCount = obj.length;
|
|
1555
1602
|
}
|
|
1556
1603
|
this.assert(
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
,
|
|
1604
|
+
itemsCount <= n,
|
|
1605
|
+
'expected #{this} to have a ' +
|
|
1606
|
+
descriptor +
|
|
1607
|
+
' at most #{exp} but got #{act}',
|
|
1608
|
+
'expected #{this} to have a ' + descriptor + ' above #{exp}',
|
|
1609
|
+
n,
|
|
1610
|
+
itemsCount
|
|
1562
1611
|
);
|
|
1563
1612
|
} else {
|
|
1564
1613
|
this.assert(
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1614
|
+
obj <= n,
|
|
1615
|
+
'expected #{this} to be at most #{exp}',
|
|
1616
|
+
'expected #{this} to be above #{exp}',
|
|
1617
|
+
n
|
|
1569
1618
|
);
|
|
1570
1619
|
}
|
|
1571
1620
|
}
|
|
@@ -1618,17 +1667,18 @@ Assertion.addMethod('lessThanOrEqual', assertMost);
|
|
|
1618
1667
|
*/
|
|
1619
1668
|
Assertion.addMethod('within', function (start, finish, msg) {
|
|
1620
1669
|
if (msg) flag(this, 'message', msg);
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
,
|
|
1630
|
-
|
|
1631
|
-
|
|
1670
|
+
let obj = flag(this, 'object'),
|
|
1671
|
+
doLength = flag(this, 'doLength'),
|
|
1672
|
+
flagMsg = flag(this, 'message'),
|
|
1673
|
+
msgPrefix = flagMsg ? flagMsg + ': ' : '',
|
|
1674
|
+
ssfi = flag(this, 'ssfi'),
|
|
1675
|
+
objType = _.type(obj).toLowerCase(),
|
|
1676
|
+
startType = _.type(start).toLowerCase(),
|
|
1677
|
+
finishType = _.type(finish).toLowerCase(),
|
|
1678
|
+
errorMessage,
|
|
1679
|
+
shouldThrow = true,
|
|
1680
|
+
range =
|
|
1681
|
+
startType === 'date' && finishType === 'date'
|
|
1632
1682
|
? start.toISOString() + '..' + finish.toISOString()
|
|
1633
1683
|
: start + '..' + finish;
|
|
1634
1684
|
|
|
@@ -1636,13 +1686,21 @@ Assertion.addMethod('within', function (start, finish, msg) {
|
|
|
1636
1686
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1637
1687
|
}
|
|
1638
1688
|
|
|
1639
|
-
if (
|
|
1689
|
+
if (
|
|
1690
|
+
!doLength &&
|
|
1691
|
+
objType === 'date' &&
|
|
1692
|
+
(startType !== 'date' || finishType !== 'date')
|
|
1693
|
+
) {
|
|
1640
1694
|
errorMessage = msgPrefix + 'the arguments to within must be dates';
|
|
1641
|
-
} else if (
|
|
1695
|
+
} else if (
|
|
1696
|
+
(!_.isNumeric(start) || !_.isNumeric(finish)) &&
|
|
1697
|
+
(doLength || _.isNumeric(obj))
|
|
1698
|
+
) {
|
|
1642
1699
|
errorMessage = msgPrefix + 'the arguments to within must be numbers';
|
|
1643
|
-
} else if (!doLength &&
|
|
1644
|
-
|
|
1645
|
-
errorMessage =
|
|
1700
|
+
} else if (!doLength && objType !== 'date' && !_.isNumeric(obj)) {
|
|
1701
|
+
let printObj = objType === 'string' ? "'" + obj + "'" : obj;
|
|
1702
|
+
errorMessage =
|
|
1703
|
+
msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1646
1704
|
} else {
|
|
1647
1705
|
shouldThrow = false;
|
|
1648
1706
|
}
|
|
@@ -1652,8 +1710,8 @@ Assertion.addMethod('within', function (start, finish, msg) {
|
|
|
1652
1710
|
}
|
|
1653
1711
|
|
|
1654
1712
|
if (doLength) {
|
|
1655
|
-
|
|
1656
|
-
|
|
1713
|
+
let descriptor = 'length',
|
|
1714
|
+
itemsCount;
|
|
1657
1715
|
if (objType === 'map' || objType === 'set') {
|
|
1658
1716
|
descriptor = 'size';
|
|
1659
1717
|
itemsCount = obj.size;
|
|
@@ -1661,15 +1719,15 @@ Assertion.addMethod('within', function (start, finish, msg) {
|
|
|
1661
1719
|
itemsCount = obj.length;
|
|
1662
1720
|
}
|
|
1663
1721
|
this.assert(
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1722
|
+
itemsCount >= start && itemsCount <= finish,
|
|
1723
|
+
'expected #{this} to have a ' + descriptor + ' within ' + range,
|
|
1724
|
+
'expected #{this} to not have a ' + descriptor + ' within ' + range
|
|
1667
1725
|
);
|
|
1668
1726
|
} else {
|
|
1669
1727
|
this.assert(
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1728
|
+
obj >= start && obj <= finish,
|
|
1729
|
+
'expected #{this} to be within ' + range,
|
|
1730
|
+
'expected #{this} to not be within ' + range
|
|
1673
1731
|
);
|
|
1674
1732
|
}
|
|
1675
1733
|
});
|
|
@@ -1712,21 +1770,24 @@ Assertion.addMethod('within', function (start, finish, msg) {
|
|
|
1712
1770
|
* @namespace BDD
|
|
1713
1771
|
* @public
|
|
1714
1772
|
*/
|
|
1715
|
-
function assertInstanceOf
|
|
1773
|
+
function assertInstanceOf(constructor, msg) {
|
|
1716
1774
|
if (msg) flag(this, 'message', msg);
|
|
1717
1775
|
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1776
|
+
let target = flag(this, 'object');
|
|
1777
|
+
let ssfi = flag(this, 'ssfi');
|
|
1778
|
+
let flagMsg = flag(this, 'message');
|
|
1779
|
+
let isInstanceOf;
|
|
1721
1780
|
|
|
1722
1781
|
try {
|
|
1723
|
-
|
|
1782
|
+
isInstanceOf = target instanceof constructor;
|
|
1724
1783
|
} catch (err) {
|
|
1725
1784
|
if (err instanceof TypeError) {
|
|
1726
1785
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1727
1786
|
throw new AssertionError(
|
|
1728
|
-
flagMsg +
|
|
1729
|
-
|
|
1787
|
+
flagMsg +
|
|
1788
|
+
'The instanceof assertion needs a constructor but ' +
|
|
1789
|
+
_.type(constructor) +
|
|
1790
|
+
' was given.',
|
|
1730
1791
|
undefined,
|
|
1731
1792
|
ssfi
|
|
1732
1793
|
);
|
|
@@ -1734,17 +1795,17 @@ function assertInstanceOf (constructor, msg) {
|
|
|
1734
1795
|
throw err;
|
|
1735
1796
|
}
|
|
1736
1797
|
|
|
1737
|
-
|
|
1798
|
+
let name = _.getName(constructor);
|
|
1738
1799
|
if (name == null) {
|
|
1739
1800
|
name = 'an unnamed constructor';
|
|
1740
1801
|
}
|
|
1741
1802
|
|
|
1742
1803
|
this.assert(
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1804
|
+
isInstanceOf,
|
|
1805
|
+
'expected #{this} to be an instance of ' + name,
|
|
1806
|
+
'expected #{this} to not be an instance of ' + name
|
|
1746
1807
|
);
|
|
1747
|
-
}
|
|
1808
|
+
}
|
|
1748
1809
|
|
|
1749
1810
|
Assertion.addMethod('instanceof', assertInstanceOf);
|
|
1750
1811
|
Assertion.addMethod('instanceOf', assertInstanceOf);
|
|
@@ -1859,30 +1920,36 @@ Assertion.addMethod('instanceOf', assertInstanceOf);
|
|
|
1859
1920
|
* @namespace BDD
|
|
1860
1921
|
* @public
|
|
1861
1922
|
*/
|
|
1862
|
-
function assertProperty
|
|
1923
|
+
function assertProperty(name, val, msg) {
|
|
1863
1924
|
if (msg) flag(this, 'message', msg);
|
|
1864
1925
|
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1926
|
+
let isNested = flag(this, 'nested'),
|
|
1927
|
+
isOwn = flag(this, 'own'),
|
|
1928
|
+
flagMsg = flag(this, 'message'),
|
|
1929
|
+
obj = flag(this, 'object'),
|
|
1930
|
+
ssfi = flag(this, 'ssfi'),
|
|
1931
|
+
nameType = typeof name;
|
|
1871
1932
|
|
|
1872
1933
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1873
1934
|
|
|
1874
1935
|
if (isNested) {
|
|
1875
1936
|
if (nameType !== 'string') {
|
|
1876
1937
|
throw new AssertionError(
|
|
1877
|
-
flagMsg +
|
|
1938
|
+
flagMsg +
|
|
1939
|
+
'the argument to property must be a string when using nested syntax',
|
|
1878
1940
|
undefined,
|
|
1879
1941
|
ssfi
|
|
1880
1942
|
);
|
|
1881
1943
|
}
|
|
1882
1944
|
} else {
|
|
1883
|
-
if (
|
|
1945
|
+
if (
|
|
1946
|
+
nameType !== 'string' &&
|
|
1947
|
+
nameType !== 'number' &&
|
|
1948
|
+
nameType !== 'symbol'
|
|
1949
|
+
) {
|
|
1884
1950
|
throw new AssertionError(
|
|
1885
|
-
flagMsg +
|
|
1951
|
+
flagMsg +
|
|
1952
|
+
'the argument to property must be a string, number, or symbol',
|
|
1886
1953
|
undefined,
|
|
1887
1954
|
ssfi
|
|
1888
1955
|
);
|
|
@@ -1905,19 +1972,19 @@ function assertProperty (name, val, msg) {
|
|
|
1905
1972
|
);
|
|
1906
1973
|
}
|
|
1907
1974
|
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1975
|
+
let isDeep = flag(this, 'deep'),
|
|
1976
|
+
negate = flag(this, 'negate'),
|
|
1977
|
+
pathInfo = isNested ? _.getPathInfo(obj, name) : null,
|
|
1978
|
+
value = isNested ? pathInfo.value : obj[name],
|
|
1979
|
+
isEql = isDeep ? flag(this, 'eql') : (val1, val2) => val1 === val2;
|
|
1913
1980
|
|
|
1914
|
-
|
|
1981
|
+
let descriptor = '';
|
|
1915
1982
|
if (isDeep) descriptor += 'deep ';
|
|
1916
1983
|
if (isOwn) descriptor += 'own ';
|
|
1917
1984
|
if (isNested) descriptor += 'nested ';
|
|
1918
1985
|
descriptor += 'property ';
|
|
1919
1986
|
|
|
1920
|
-
|
|
1987
|
+
let hasProperty;
|
|
1921
1988
|
if (isOwn) hasProperty = Object.prototype.hasOwnProperty.call(obj, name);
|
|
1922
1989
|
else if (isNested) hasProperty = pathInfo.exists;
|
|
1923
1990
|
else hasProperty = _.hasProperty(obj, name);
|
|
@@ -1929,18 +1996,25 @@ function assertProperty (name, val, msg) {
|
|
|
1929
1996
|
// favor of the next.
|
|
1930
1997
|
if (!negate || arguments.length === 1) {
|
|
1931
1998
|
this.assert(
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1999
|
+
hasProperty,
|
|
2000
|
+
'expected #{this} to have ' + descriptor + _.inspect(name),
|
|
2001
|
+
'expected #{this} to not have ' + descriptor + _.inspect(name)
|
|
2002
|
+
);
|
|
1935
2003
|
}
|
|
1936
2004
|
|
|
1937
2005
|
if (arguments.length > 1) {
|
|
1938
2006
|
this.assert(
|
|
1939
|
-
hasProperty && isEql(val, value)
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2007
|
+
hasProperty && isEql(val, value),
|
|
2008
|
+
'expected #{this} to have ' +
|
|
2009
|
+
descriptor +
|
|
2010
|
+
_.inspect(name) +
|
|
2011
|
+
' of #{exp}, but got #{act}',
|
|
2012
|
+
'expected #{this} to not have ' +
|
|
2013
|
+
descriptor +
|
|
2014
|
+
_.inspect(name) +
|
|
2015
|
+
' of #{act}',
|
|
2016
|
+
val,
|
|
2017
|
+
value
|
|
1944
2018
|
);
|
|
1945
2019
|
}
|
|
1946
2020
|
|
|
@@ -1950,12 +2024,11 @@ function assertProperty (name, val, msg) {
|
|
|
1950
2024
|
Assertion.addMethod('property', assertProperty);
|
|
1951
2025
|
|
|
1952
2026
|
/**
|
|
1953
|
-
*
|
|
1954
|
-
* @param {unknown}
|
|
1955
|
-
* @param {
|
|
1956
|
-
* @param {string} msg
|
|
2027
|
+
* @param {unknown} _name
|
|
2028
|
+
* @param {unknown} _value
|
|
2029
|
+
* @param {string} _msg
|
|
1957
2030
|
*/
|
|
1958
|
-
function assertOwnProperty
|
|
2031
|
+
function assertOwnProperty(_name, _value, _msg) {
|
|
1959
2032
|
flag(this, 'own', true);
|
|
1960
2033
|
assertProperty.apply(this, arguments);
|
|
1961
2034
|
}
|
|
@@ -2081,29 +2154,39 @@ Assertion.addMethod('haveOwnProperty', assertOwnProperty);
|
|
|
2081
2154
|
* @namespace BDD
|
|
2082
2155
|
* @public
|
|
2083
2156
|
*/
|
|
2084
|
-
function assertOwnPropertyDescriptor
|
|
2157
|
+
function assertOwnPropertyDescriptor(name, descriptor, msg) {
|
|
2085
2158
|
if (typeof descriptor === 'string') {
|
|
2086
2159
|
msg = descriptor;
|
|
2087
2160
|
descriptor = null;
|
|
2088
2161
|
}
|
|
2089
2162
|
if (msg) flag(this, 'message', msg);
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2163
|
+
let obj = flag(this, 'object');
|
|
2164
|
+
let actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
|
|
2165
|
+
let eql = flag(this, 'eql');
|
|
2093
2166
|
if (actualDescriptor && descriptor) {
|
|
2094
2167
|
this.assert(
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2168
|
+
eql(descriptor, actualDescriptor),
|
|
2169
|
+
'expected the own property descriptor for ' +
|
|
2170
|
+
_.inspect(name) +
|
|
2171
|
+
' on #{this} to match ' +
|
|
2172
|
+
_.inspect(descriptor) +
|
|
2173
|
+
', got ' +
|
|
2174
|
+
_.inspect(actualDescriptor),
|
|
2175
|
+
'expected the own property descriptor for ' +
|
|
2176
|
+
_.inspect(name) +
|
|
2177
|
+
' on #{this} to not match ' +
|
|
2178
|
+
_.inspect(descriptor),
|
|
2179
|
+
descriptor,
|
|
2180
|
+
actualDescriptor,
|
|
2181
|
+
true
|
|
2101
2182
|
);
|
|
2102
2183
|
} else {
|
|
2103
2184
|
this.assert(
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2185
|
+
actualDescriptor,
|
|
2186
|
+
'expected #{this} to have an own property descriptor for ' +
|
|
2187
|
+
_.inspect(name),
|
|
2188
|
+
'expected #{this} to not have an own property descriptor for ' +
|
|
2189
|
+
_.inspect(name)
|
|
2107
2190
|
);
|
|
2108
2191
|
}
|
|
2109
2192
|
flag(this, 'object', actualDescriptor);
|
|
@@ -2112,10 +2195,8 @@ function assertOwnPropertyDescriptor (name, descriptor, msg) {
|
|
|
2112
2195
|
Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
|
|
2113
2196
|
Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
|
|
2114
2197
|
|
|
2115
|
-
/**
|
|
2116
|
-
|
|
2117
|
-
*/
|
|
2118
|
-
function assertLengthChain () {
|
|
2198
|
+
/** */
|
|
2199
|
+
function assertLengthChain() {
|
|
2119
2200
|
flag(this, 'doLength', true);
|
|
2120
2201
|
}
|
|
2121
2202
|
|
|
@@ -2176,14 +2257,14 @@ function assertLengthChain () {
|
|
|
2176
2257
|
* @namespace BDD
|
|
2177
2258
|
* @public
|
|
2178
2259
|
*/
|
|
2179
|
-
function assertLength
|
|
2260
|
+
function assertLength(n, msg) {
|
|
2180
2261
|
if (msg) flag(this, 'message', msg);
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2262
|
+
let obj = flag(this, 'object'),
|
|
2263
|
+
objType = _.type(obj).toLowerCase(),
|
|
2264
|
+
flagMsg = flag(this, 'message'),
|
|
2265
|
+
ssfi = flag(this, 'ssfi'),
|
|
2266
|
+
descriptor = 'length',
|
|
2267
|
+
itemsCount;
|
|
2187
2268
|
|
|
2188
2269
|
switch (objType) {
|
|
2189
2270
|
case 'map':
|
|
@@ -2197,11 +2278,11 @@ function assertLength (n, msg) {
|
|
|
2197
2278
|
}
|
|
2198
2279
|
|
|
2199
2280
|
this.assert(
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
,
|
|
2204
|
-
|
|
2281
|
+
itemsCount == n,
|
|
2282
|
+
'expected #{this} to have a ' + descriptor + ' of #{exp} but got #{act}',
|
|
2283
|
+
'expected #{this} to not have a ' + descriptor + ' of #{act}',
|
|
2284
|
+
n,
|
|
2285
|
+
itemsCount
|
|
2205
2286
|
);
|
|
2206
2287
|
}
|
|
2207
2288
|
|
|
@@ -2237,11 +2318,11 @@ Assertion.addChainableMethod('lengthOf', assertLength, assertLengthChain);
|
|
|
2237
2318
|
*/
|
|
2238
2319
|
function assertMatch(re, msg) {
|
|
2239
2320
|
if (msg) flag(this, 'message', msg);
|
|
2240
|
-
|
|
2321
|
+
let obj = flag(this, 'object');
|
|
2241
2322
|
this.assert(
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2323
|
+
re.exec(obj),
|
|
2324
|
+
'expected #{this} to match ' + re,
|
|
2325
|
+
'expected #{this} not to match ' + re
|
|
2245
2326
|
);
|
|
2246
2327
|
}
|
|
2247
2328
|
|
|
@@ -2274,15 +2355,15 @@ Assertion.addMethod('matches', assertMatch);
|
|
|
2274
2355
|
*/
|
|
2275
2356
|
Assertion.addMethod('string', function (str, msg) {
|
|
2276
2357
|
if (msg) flag(this, 'message', msg);
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2358
|
+
let obj = flag(this, 'object'),
|
|
2359
|
+
flagMsg = flag(this, 'message'),
|
|
2360
|
+
ssfi = flag(this, 'ssfi');
|
|
2280
2361
|
new Assertion(obj, flagMsg, ssfi, true).is.a('string');
|
|
2281
2362
|
|
|
2282
2363
|
this.assert(
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2364
|
+
~obj.indexOf(str),
|
|
2365
|
+
'expected #{this} to contain ' + _.inspect(str),
|
|
2366
|
+
'expected #{this} to not contain ' + _.inspect(str)
|
|
2286
2367
|
);
|
|
2287
2368
|
});
|
|
2288
2369
|
|
|
@@ -2389,27 +2470,31 @@ Assertion.addMethod('string', function (str, msg) {
|
|
|
2389
2470
|
* @namespace BDD
|
|
2390
2471
|
* @public
|
|
2391
2472
|
*/
|
|
2392
|
-
function assertKeys
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
,
|
|
2399
|
-
|
|
2400
|
-
,
|
|
2401
|
-
|
|
2402
|
-
|
|
2473
|
+
function assertKeys(keys) {
|
|
2474
|
+
let obj = flag(this, 'object'),
|
|
2475
|
+
objType = _.type(obj),
|
|
2476
|
+
keysType = _.type(keys),
|
|
2477
|
+
ssfi = flag(this, 'ssfi'),
|
|
2478
|
+
isDeep = flag(this, 'deep'),
|
|
2479
|
+
str,
|
|
2480
|
+
deepStr = '',
|
|
2481
|
+
actual,
|
|
2482
|
+
ok = true,
|
|
2483
|
+
flagMsg = flag(this, 'message');
|
|
2403
2484
|
|
|
2404
2485
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
2405
|
-
|
|
2486
|
+
let mixedArgsMsg =
|
|
2487
|
+
flagMsg +
|
|
2488
|
+
'when testing keys against an object or an array you must give a single Array|Object|String argument or multiple String arguments';
|
|
2406
2489
|
|
|
2407
2490
|
if (objType === 'Map' || objType === 'Set') {
|
|
2408
2491
|
deepStr = isDeep ? 'deeply ' : '';
|
|
2409
2492
|
actual = [];
|
|
2410
2493
|
|
|
2411
2494
|
// Map and Set '.keys' aren't supported in IE 11. Therefore, use .forEach.
|
|
2412
|
-
obj.forEach(function (val, key) {
|
|
2495
|
+
obj.forEach(function (val, key) {
|
|
2496
|
+
actual.push(key);
|
|
2497
|
+
});
|
|
2413
2498
|
|
|
2414
2499
|
if (keysType !== 'Array') {
|
|
2415
2500
|
keys = Array.prototype.slice.call(arguments);
|
|
@@ -2443,11 +2528,11 @@ function assertKeys (keys) {
|
|
|
2443
2528
|
throw new AssertionError(flagMsg + 'keys required', undefined, ssfi);
|
|
2444
2529
|
}
|
|
2445
2530
|
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2531
|
+
let len = keys.length,
|
|
2532
|
+
any = flag(this, 'any'),
|
|
2533
|
+
all = flag(this, 'all'),
|
|
2534
|
+
expected = keys,
|
|
2535
|
+
isEql = isDeep ? flag(this, 'eql') : (val1, val2) => val1 === val2;
|
|
2451
2536
|
|
|
2452
2537
|
if (!any && !all) {
|
|
2453
2538
|
all = true;
|
|
@@ -2455,8 +2540,8 @@ function assertKeys (keys) {
|
|
|
2455
2540
|
|
|
2456
2541
|
// Has any
|
|
2457
2542
|
if (any) {
|
|
2458
|
-
ok = expected.some(function(expectedKey) {
|
|
2459
|
-
return actual.some(function(actualKey) {
|
|
2543
|
+
ok = expected.some(function (expectedKey) {
|
|
2544
|
+
return actual.some(function (actualKey) {
|
|
2460
2545
|
return isEql(expectedKey, actualKey);
|
|
2461
2546
|
});
|
|
2462
2547
|
});
|
|
@@ -2464,8 +2549,8 @@ function assertKeys (keys) {
|
|
|
2464
2549
|
|
|
2465
2550
|
// Has all
|
|
2466
2551
|
if (all) {
|
|
2467
|
-
ok = expected.every(function(expectedKey) {
|
|
2468
|
-
return actual.some(function(actualKey) {
|
|
2552
|
+
ok = expected.every(function (expectedKey) {
|
|
2553
|
+
return actual.some(function (actualKey) {
|
|
2469
2554
|
return isEql(expectedKey, actualKey);
|
|
2470
2555
|
});
|
|
2471
2556
|
});
|
|
@@ -2477,10 +2562,10 @@ function assertKeys (keys) {
|
|
|
2477
2562
|
|
|
2478
2563
|
// Key string
|
|
2479
2564
|
if (len > 1) {
|
|
2480
|
-
keys = keys.map(function(key) {
|
|
2565
|
+
keys = keys.map(function (key) {
|
|
2481
2566
|
return _.inspect(key);
|
|
2482
2567
|
});
|
|
2483
|
-
|
|
2568
|
+
let last = keys.pop();
|
|
2484
2569
|
if (all) {
|
|
2485
2570
|
str = keys.join(', ') + ', and ' + last;
|
|
2486
2571
|
}
|
|
@@ -2499,12 +2584,12 @@ function assertKeys (keys) {
|
|
|
2499
2584
|
|
|
2500
2585
|
// Assertion
|
|
2501
2586
|
this.assert(
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2587
|
+
ok,
|
|
2588
|
+
'expected #{this} to ' + deepStr + str,
|
|
2589
|
+
'expected #{this} to not ' + deepStr + str,
|
|
2590
|
+
expected.slice(0).sort(_.compareByInspect),
|
|
2591
|
+
actual.sort(_.compareByInspect),
|
|
2592
|
+
true
|
|
2508
2593
|
);
|
|
2509
2594
|
}
|
|
2510
2595
|
|
|
@@ -2670,12 +2755,12 @@ Assertion.addMethod('key', assertKeys);
|
|
|
2670
2755
|
* @namespace BDD
|
|
2671
2756
|
* @public
|
|
2672
2757
|
*/
|
|
2673
|
-
function assertThrows
|
|
2758
|
+
function assertThrows(errorLike, errMsgMatcher, msg) {
|
|
2674
2759
|
if (msg) flag(this, 'message', msg);
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2760
|
+
let obj = flag(this, 'object'),
|
|
2761
|
+
ssfi = flag(this, 'ssfi'),
|
|
2762
|
+
flagMsg = flag(this, 'message'),
|
|
2763
|
+
negate = flag(this, 'negate') || false;
|
|
2679
2764
|
new Assertion(obj, flagMsg, ssfi, true).is.a('function');
|
|
2680
2765
|
|
|
2681
2766
|
if (_.isRegExp(errorLike) || typeof errorLike === 'string') {
|
|
@@ -2694,18 +2779,19 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2694
2779
|
|
|
2695
2780
|
// If we have the negate flag enabled and at least one valid argument it means we do expect an error
|
|
2696
2781
|
// but we want it to match a given set of criteria
|
|
2697
|
-
|
|
2782
|
+
let everyArgIsUndefined =
|
|
2783
|
+
errorLike === undefined && errMsgMatcher === undefined;
|
|
2698
2784
|
|
|
2699
2785
|
// If we've got the negate flag enabled and both args, we should only fail if both aren't compatible
|
|
2700
2786
|
// See Issue #551 and PR #683@GitHub
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2787
|
+
let everyArgIsDefined = Boolean(errorLike && errMsgMatcher);
|
|
2788
|
+
let errorLikeFail = false;
|
|
2789
|
+
let errMsgMatcherFail = false;
|
|
2704
2790
|
|
|
2705
2791
|
// Checking if error was thrown
|
|
2706
|
-
if (everyArgIsUndefined || !everyArgIsUndefined && !negate) {
|
|
2792
|
+
if (everyArgIsUndefined || (!everyArgIsUndefined && !negate)) {
|
|
2707
2793
|
// We need this to display results correctly according to their types
|
|
2708
|
-
|
|
2794
|
+
let errorLikeString = 'an error';
|
|
2709
2795
|
if (errorLike instanceof Error) {
|
|
2710
2796
|
errorLikeString = '#{exp}';
|
|
2711
2797
|
} else if (errorLike) {
|
|
@@ -2717,7 +2803,10 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2717
2803
|
actual = caughtErr.toString();
|
|
2718
2804
|
} else if (typeof caughtErr === 'string') {
|
|
2719
2805
|
actual = caughtErr;
|
|
2720
|
-
} else if (
|
|
2806
|
+
} else if (
|
|
2807
|
+
caughtErr &&
|
|
2808
|
+
(typeof caughtErr === 'object' || typeof caughtErr === 'function')
|
|
2809
|
+
) {
|
|
2721
2810
|
try {
|
|
2722
2811
|
actual = _.checkError.getConstructorName(caughtErr);
|
|
2723
2812
|
} catch (_err) {
|
|
@@ -2727,18 +2816,21 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2727
2816
|
}
|
|
2728
2817
|
|
|
2729
2818
|
this.assert(
|
|
2730
|
-
errorWasThrown
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2819
|
+
errorWasThrown,
|
|
2820
|
+
'expected #{this} to throw ' + errorLikeString,
|
|
2821
|
+
'expected #{this} to not throw an error but #{act} was thrown',
|
|
2822
|
+
errorLike && errorLike.toString(),
|
|
2823
|
+
actual
|
|
2735
2824
|
);
|
|
2736
2825
|
}
|
|
2737
2826
|
|
|
2738
2827
|
if (errorLike && caughtErr) {
|
|
2739
2828
|
// We should compare instances only if `errorLike` is an instance of `Error`
|
|
2740
2829
|
if (errorLike instanceof Error) {
|
|
2741
|
-
|
|
2830
|
+
let isCompatibleInstance = _.checkError.compatibleInstance(
|
|
2831
|
+
caughtErr,
|
|
2832
|
+
errorLike
|
|
2833
|
+
);
|
|
2742
2834
|
|
|
2743
2835
|
if (isCompatibleInstance === negate) {
|
|
2744
2836
|
// These checks were created to ensure we won't fail too soon when we've got both args and a negate
|
|
@@ -2747,27 +2839,36 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2747
2839
|
errorLikeFail = true;
|
|
2748
2840
|
} else {
|
|
2749
2841
|
this.assert(
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2842
|
+
negate,
|
|
2843
|
+
'expected #{this} to throw #{exp} but #{act} was thrown',
|
|
2844
|
+
'expected #{this} to not throw #{exp}' +
|
|
2845
|
+
(caughtErr && !negate ? ' but #{act} was thrown' : ''),
|
|
2846
|
+
errorLike.toString(),
|
|
2847
|
+
caughtErr.toString()
|
|
2755
2848
|
);
|
|
2756
2849
|
}
|
|
2757
2850
|
}
|
|
2758
2851
|
}
|
|
2759
2852
|
|
|
2760
|
-
|
|
2853
|
+
let isCompatibleConstructor = _.checkError.compatibleConstructor(
|
|
2854
|
+
caughtErr,
|
|
2855
|
+
errorLike
|
|
2856
|
+
);
|
|
2761
2857
|
if (isCompatibleConstructor === negate) {
|
|
2762
2858
|
if (everyArgIsDefined && negate) {
|
|
2763
|
-
|
|
2859
|
+
errorLikeFail = true;
|
|
2764
2860
|
} else {
|
|
2765
2861
|
this.assert(
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2862
|
+
negate,
|
|
2863
|
+
'expected #{this} to throw #{exp} but #{act} was thrown',
|
|
2864
|
+
'expected #{this} to not throw #{exp}' +
|
|
2865
|
+
(caughtErr ? ' but #{act} was thrown' : ''),
|
|
2866
|
+
errorLike instanceof Error
|
|
2867
|
+
? errorLike.toString()
|
|
2868
|
+
: errorLike && _.checkError.getConstructorName(errorLike),
|
|
2869
|
+
caughtErr instanceof Error
|
|
2870
|
+
? caughtErr.toString()
|
|
2871
|
+
: caughtErr && _.checkError.getConstructorName(caughtErr)
|
|
2771
2872
|
);
|
|
2772
2873
|
}
|
|
2773
2874
|
}
|
|
@@ -2775,22 +2876,27 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2775
2876
|
|
|
2776
2877
|
if (caughtErr && errMsgMatcher !== undefined && errMsgMatcher !== null) {
|
|
2777
2878
|
// Here we check compatible messages
|
|
2778
|
-
|
|
2879
|
+
let placeholder = 'including';
|
|
2779
2880
|
if (_.isRegExp(errMsgMatcher)) {
|
|
2780
|
-
placeholder = 'matching'
|
|
2881
|
+
placeholder = 'matching';
|
|
2781
2882
|
}
|
|
2782
2883
|
|
|
2783
|
-
|
|
2884
|
+
let isCompatibleMessage = _.checkError.compatibleMessage(
|
|
2885
|
+
caughtErr,
|
|
2886
|
+
errMsgMatcher
|
|
2887
|
+
);
|
|
2784
2888
|
if (isCompatibleMessage === negate) {
|
|
2785
2889
|
if (everyArgIsDefined && negate) {
|
|
2786
|
-
|
|
2890
|
+
errMsgMatcherFail = true;
|
|
2787
2891
|
} else {
|
|
2788
2892
|
this.assert(
|
|
2789
|
-
negate
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
,
|
|
2893
|
+
negate,
|
|
2894
|
+
'expected #{this} to throw error ' +
|
|
2895
|
+
placeholder +
|
|
2896
|
+
' #{exp} but got #{act}',
|
|
2897
|
+
'expected #{this} to throw error not ' + placeholder + ' #{exp}',
|
|
2898
|
+
errMsgMatcher,
|
|
2899
|
+
_.checkError.getMessage(caughtErr)
|
|
2794
2900
|
);
|
|
2795
2901
|
}
|
|
2796
2902
|
}
|
|
@@ -2799,16 +2905,21 @@ function assertThrows (errorLike, errMsgMatcher, msg) {
|
|
|
2799
2905
|
// If both assertions failed and both should've matched we throw an error
|
|
2800
2906
|
if (errorLikeFail && errMsgMatcherFail) {
|
|
2801
2907
|
this.assert(
|
|
2802
|
-
negate
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2908
|
+
negate,
|
|
2909
|
+
'expected #{this} to throw #{exp} but #{act} was thrown',
|
|
2910
|
+
'expected #{this} to not throw #{exp}' +
|
|
2911
|
+
(caughtErr ? ' but #{act} was thrown' : ''),
|
|
2912
|
+
errorLike instanceof Error
|
|
2913
|
+
? errorLike.toString()
|
|
2914
|
+
: errorLike && _.checkError.getConstructorName(errorLike),
|
|
2915
|
+
caughtErr instanceof Error
|
|
2916
|
+
? caughtErr.toString()
|
|
2917
|
+
: caughtErr && _.checkError.getConstructorName(caughtErr)
|
|
2807
2918
|
);
|
|
2808
2919
|
}
|
|
2809
2920
|
|
|
2810
2921
|
flag(this, 'object', caughtErr);
|
|
2811
|
-
}
|
|
2922
|
+
}
|
|
2812
2923
|
|
|
2813
2924
|
Assertion.addMethod('throw', assertThrows);
|
|
2814
2925
|
Assertion.addMethod('throws', assertThrows);
|
|
@@ -2878,18 +2989,19 @@ Assertion.addMethod('Throw', assertThrows);
|
|
|
2878
2989
|
* @namespace BDD
|
|
2879
2990
|
* @public
|
|
2880
2991
|
*/
|
|
2881
|
-
function respondTo
|
|
2992
|
+
function respondTo(method, msg) {
|
|
2882
2993
|
if (msg) flag(this, 'message', msg);
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2994
|
+
let obj = flag(this, 'object'),
|
|
2995
|
+
itself = flag(this, 'itself'),
|
|
2996
|
+
context =
|
|
2997
|
+
'function' === typeof obj && !itself
|
|
2998
|
+
? obj.prototype[method]
|
|
2999
|
+
: obj[method];
|
|
2888
3000
|
|
|
2889
3001
|
this.assert(
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
3002
|
+
'function' === typeof context,
|
|
3003
|
+
'expected #{this} to respond to ' + _.inspect(method),
|
|
3004
|
+
'expected #{this} to not respond to ' + _.inspect(method)
|
|
2893
3005
|
);
|
|
2894
3006
|
}
|
|
2895
3007
|
|
|
@@ -2956,16 +3068,16 @@ Assertion.addProperty('itself', function () {
|
|
|
2956
3068
|
* @namespace BDD
|
|
2957
3069
|
* @public
|
|
2958
3070
|
*/
|
|
2959
|
-
function satisfy
|
|
3071
|
+
function satisfy(matcher, msg) {
|
|
2960
3072
|
if (msg) flag(this, 'message', msg);
|
|
2961
|
-
|
|
2962
|
-
|
|
3073
|
+
let obj = flag(this, 'object');
|
|
3074
|
+
let result = matcher(obj);
|
|
2963
3075
|
this.assert(
|
|
2964
|
-
|
|
2965
|
-
|
|
2966
|
-
|
|
2967
|
-
|
|
2968
|
-
|
|
3076
|
+
result,
|
|
3077
|
+
'expected #{this} to satisfy ' + _.objDisplay(matcher),
|
|
3078
|
+
'expected #{this} to not satisfy' + _.objDisplay(matcher),
|
|
3079
|
+
flag(this, 'negate') ? false : true,
|
|
3080
|
+
result
|
|
2969
3081
|
);
|
|
2970
3082
|
}
|
|
2971
3083
|
|
|
@@ -3011,24 +3123,40 @@ Assertion.addMethod('satisfies', satisfy);
|
|
|
3011
3123
|
*/
|
|
3012
3124
|
function closeTo(expected, delta, msg) {
|
|
3013
3125
|
if (msg) flag(this, 'message', msg);
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3126
|
+
let obj = flag(this, 'object'),
|
|
3127
|
+
flagMsg = flag(this, 'message'),
|
|
3128
|
+
ssfi = flag(this, 'ssfi');
|
|
3017
3129
|
|
|
3018
3130
|
new Assertion(obj, flagMsg, ssfi, true).is.numeric;
|
|
3019
|
-
let message =
|
|
3020
|
-
if (delta == undefined)
|
|
3131
|
+
let message = 'A `delta` value is required for `closeTo`';
|
|
3132
|
+
if (delta == undefined) {
|
|
3133
|
+
throw new AssertionError(
|
|
3134
|
+
flagMsg ? `${flagMsg}: ${message}` : message,
|
|
3135
|
+
undefined,
|
|
3136
|
+
ssfi
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
3021
3139
|
new Assertion(delta, flagMsg, ssfi, true).is.numeric;
|
|
3022
|
-
message =
|
|
3023
|
-
if (expected == undefined)
|
|
3140
|
+
message = 'A `expected` value is required for `closeTo`';
|
|
3141
|
+
if (expected == undefined) {
|
|
3142
|
+
throw new AssertionError(
|
|
3143
|
+
flagMsg ? `${flagMsg}: ${message}` : message,
|
|
3144
|
+
undefined,
|
|
3145
|
+
ssfi
|
|
3146
|
+
);
|
|
3147
|
+
}
|
|
3024
3148
|
new Assertion(expected, flagMsg, ssfi, true).is.numeric;
|
|
3025
3149
|
|
|
3026
|
-
const abs = (x) => x < 0n ? -x : x;
|
|
3150
|
+
const abs = (x) => (x < 0n ? -x : x);
|
|
3151
|
+
|
|
3152
|
+
// Used to round floating point number precision arithmetics
|
|
3153
|
+
// See: https://stackoverflow.com/a/3644302
|
|
3154
|
+
const strip = (number) => parseFloat(parseFloat(number).toPrecision(12));
|
|
3027
3155
|
|
|
3028
3156
|
this.assert(
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3157
|
+
strip(abs(obj - expected)) <= delta,
|
|
3158
|
+
'expected #{this} to be close to ' + expected + ' +/- ' + delta,
|
|
3159
|
+
'expected #{this} not to be close to ' + expected + ' +/- ' + delta
|
|
3032
3160
|
);
|
|
3033
3161
|
}
|
|
3034
3162
|
|
|
@@ -3051,11 +3179,11 @@ function isSubsetOf(_subset, _superset, cmp, contains, ordered) {
|
|
|
3051
3179
|
superset = superset.slice();
|
|
3052
3180
|
}
|
|
3053
3181
|
|
|
3054
|
-
return subset.every(function(elem, idx) {
|
|
3182
|
+
return subset.every(function (elem, idx) {
|
|
3055
3183
|
if (ordered) return cmp ? cmp(elem, superset[idx]) : elem === superset[idx];
|
|
3056
3184
|
|
|
3057
3185
|
if (!cmp) {
|
|
3058
|
-
|
|
3186
|
+
let matchIdx = superset.indexOf(elem);
|
|
3059
3187
|
if (matchIdx === -1) return false;
|
|
3060
3188
|
|
|
3061
3189
|
// Remove match from superset so not counted twice if duplicate in subset.
|
|
@@ -3063,7 +3191,7 @@ function isSubsetOf(_subset, _superset, cmp, contains, ordered) {
|
|
|
3063
3191
|
return true;
|
|
3064
3192
|
}
|
|
3065
3193
|
|
|
3066
|
-
return superset.some(function(elem2, matchIdx) {
|
|
3194
|
+
return superset.some(function (elem2, matchIdx) {
|
|
3067
3195
|
if (!cmp(elem, elem2)) return false;
|
|
3068
3196
|
|
|
3069
3197
|
// Remove match from superset so not counted twice if duplicate in subset.
|
|
@@ -3143,17 +3271,17 @@ function isSubsetOf(_subset, _superset, cmp, contains, ordered) {
|
|
|
3143
3271
|
*/
|
|
3144
3272
|
Assertion.addMethod('members', function (subset, msg) {
|
|
3145
3273
|
if (msg) flag(this, 'message', msg);
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3274
|
+
let obj = flag(this, 'object'),
|
|
3275
|
+
flagMsg = flag(this, 'message'),
|
|
3276
|
+
ssfi = flag(this, 'ssfi');
|
|
3149
3277
|
|
|
3150
3278
|
new Assertion(obj, flagMsg, ssfi, true).to.be.iterable;
|
|
3151
3279
|
new Assertion(subset, flagMsg, ssfi, true).to.be.iterable;
|
|
3152
3280
|
|
|
3153
|
-
|
|
3154
|
-
|
|
3281
|
+
let contains = flag(this, 'contains');
|
|
3282
|
+
let ordered = flag(this, 'ordered');
|
|
3155
3283
|
|
|
3156
|
-
|
|
3284
|
+
let subject, failMsg, failNegateMsg;
|
|
3157
3285
|
|
|
3158
3286
|
if (contains) {
|
|
3159
3287
|
subject = ordered ? 'an ordered superset' : 'a superset';
|
|
@@ -3162,18 +3290,19 @@ Assertion.addMethod('members', function (subset, msg) {
|
|
|
3162
3290
|
} else {
|
|
3163
3291
|
subject = ordered ? 'ordered members' : 'members';
|
|
3164
3292
|
failMsg = 'expected #{this} to have the same ' + subject + ' as #{exp}';
|
|
3165
|
-
failNegateMsg =
|
|
3293
|
+
failNegateMsg =
|
|
3294
|
+
'expected #{this} to not have the same ' + subject + ' as #{exp}';
|
|
3166
3295
|
}
|
|
3167
3296
|
|
|
3168
|
-
|
|
3297
|
+
let cmp = flag(this, 'deep') ? flag(this, 'eql') : undefined;
|
|
3169
3298
|
|
|
3170
3299
|
this.assert(
|
|
3171
|
-
|
|
3172
|
-
,
|
|
3173
|
-
,
|
|
3174
|
-
,
|
|
3175
|
-
,
|
|
3176
|
-
|
|
3300
|
+
isSubsetOf(subset, obj, cmp, contains, ordered),
|
|
3301
|
+
failMsg,
|
|
3302
|
+
failNegateMsg,
|
|
3303
|
+
subset,
|
|
3304
|
+
obj,
|
|
3305
|
+
true
|
|
3177
3306
|
);
|
|
3178
3307
|
});
|
|
3179
3308
|
|
|
@@ -3198,15 +3327,15 @@ Assertion.addMethod('members', function (subset, msg) {
|
|
|
3198
3327
|
* @namespace BDD
|
|
3199
3328
|
* @public
|
|
3200
3329
|
*/
|
|
3201
|
-
Assertion.addProperty('iterable', function(msg) {
|
|
3330
|
+
Assertion.addProperty('iterable', function (msg) {
|
|
3202
3331
|
if (msg) flag(this, 'message', msg);
|
|
3203
|
-
|
|
3332
|
+
let obj = flag(this, 'object');
|
|
3204
3333
|
|
|
3205
3334
|
this.assert(
|
|
3206
|
-
obj != undefined && obj[Symbol.iterator]
|
|
3207
|
-
|
|
3208
|
-
|
|
3209
|
-
|
|
3335
|
+
obj != undefined && obj[Symbol.iterator],
|
|
3336
|
+
'expected #{this} to be an iterable',
|
|
3337
|
+
'expected #{this} to not be an iterable',
|
|
3338
|
+
obj
|
|
3210
3339
|
);
|
|
3211
3340
|
});
|
|
3212
3341
|
|
|
@@ -3247,40 +3376,44 @@ Assertion.addProperty('iterable', function(msg) {
|
|
|
3247
3376
|
* @namespace BDD
|
|
3248
3377
|
* @public
|
|
3249
3378
|
*/
|
|
3250
|
-
function oneOf
|
|
3379
|
+
function oneOf(list, msg) {
|
|
3251
3380
|
if (msg) flag(this, 'message', msg);
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3381
|
+
let expected = flag(this, 'object'),
|
|
3382
|
+
flagMsg = flag(this, 'message'),
|
|
3383
|
+
ssfi = flag(this, 'ssfi'),
|
|
3384
|
+
contains = flag(this, 'contains'),
|
|
3385
|
+
isDeep = flag(this, 'deep'),
|
|
3386
|
+
eql = flag(this, 'eql');
|
|
3258
3387
|
new Assertion(list, flagMsg, ssfi, true).to.be.an('array');
|
|
3259
3388
|
|
|
3260
3389
|
if (contains) {
|
|
3261
3390
|
this.assert(
|
|
3262
|
-
list.some(function(possibility) {
|
|
3263
|
-
|
|
3264
|
-
,
|
|
3265
|
-
,
|
|
3266
|
-
,
|
|
3391
|
+
list.some(function (possibility) {
|
|
3392
|
+
return expected.indexOf(possibility) > -1;
|
|
3393
|
+
}),
|
|
3394
|
+
'expected #{this} to contain one of #{exp}',
|
|
3395
|
+
'expected #{this} to not contain one of #{exp}',
|
|
3396
|
+
list,
|
|
3397
|
+
expected
|
|
3267
3398
|
);
|
|
3268
3399
|
} else {
|
|
3269
3400
|
if (isDeep) {
|
|
3270
3401
|
this.assert(
|
|
3271
|
-
list.some(function(possibility) {
|
|
3272
|
-
|
|
3273
|
-
,
|
|
3274
|
-
,
|
|
3275
|
-
,
|
|
3402
|
+
list.some(function (possibility) {
|
|
3403
|
+
return eql(expected, possibility);
|
|
3404
|
+
}),
|
|
3405
|
+
'expected #{this} to deeply equal one of #{exp}',
|
|
3406
|
+
'expected #{this} to deeply equal one of #{exp}',
|
|
3407
|
+
list,
|
|
3408
|
+
expected
|
|
3276
3409
|
);
|
|
3277
3410
|
} else {
|
|
3278
3411
|
this.assert(
|
|
3279
|
-
list.indexOf(expected) > -1
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
,
|
|
3283
|
-
|
|
3412
|
+
list.indexOf(expected) > -1,
|
|
3413
|
+
'expected #{this} to be one of #{exp}',
|
|
3414
|
+
'expected #{this} to not be one of #{exp}',
|
|
3415
|
+
list,
|
|
3416
|
+
expected
|
|
3284
3417
|
);
|
|
3285
3418
|
}
|
|
3286
3419
|
}
|
|
@@ -3382,14 +3515,14 @@ Assertion.addMethod('oneOf', oneOf);
|
|
|
3382
3515
|
* @namespace BDD
|
|
3383
3516
|
* @public
|
|
3384
3517
|
*/
|
|
3385
|
-
function assertChanges
|
|
3518
|
+
function assertChanges(subject, prop, msg) {
|
|
3386
3519
|
if (msg) flag(this, 'message', msg);
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3520
|
+
let fn = flag(this, 'object'),
|
|
3521
|
+
flagMsg = flag(this, 'message'),
|
|
3522
|
+
ssfi = flag(this, 'ssfi');
|
|
3390
3523
|
new Assertion(fn, flagMsg, ssfi, true).is.a('function');
|
|
3391
3524
|
|
|
3392
|
-
|
|
3525
|
+
let initial;
|
|
3393
3526
|
if (!prop) {
|
|
3394
3527
|
new Assertion(subject, flagMsg, ssfi, true).is.a('function');
|
|
3395
3528
|
initial = subject();
|
|
@@ -3400,8 +3533,8 @@ function assertChanges (subject, prop, msg) {
|
|
|
3400
3533
|
|
|
3401
3534
|
fn();
|
|
3402
3535
|
|
|
3403
|
-
|
|
3404
|
-
|
|
3536
|
+
let final = prop === undefined || prop === null ? subject() : subject[prop];
|
|
3537
|
+
let msgObj = prop === undefined || prop === null ? initial : '.' + prop;
|
|
3405
3538
|
|
|
3406
3539
|
// This gets flagged because of the .by(delta) assertion
|
|
3407
3540
|
flag(this, 'deltaMsgObj', msgObj);
|
|
@@ -3411,9 +3544,9 @@ function assertChanges (subject, prop, msg) {
|
|
|
3411
3544
|
flag(this, 'realDelta', final !== initial);
|
|
3412
3545
|
|
|
3413
3546
|
this.assert(
|
|
3414
|
-
initial !== final
|
|
3415
|
-
|
|
3416
|
-
|
|
3547
|
+
initial !== final,
|
|
3548
|
+
'expected ' + msgObj + ' to change',
|
|
3549
|
+
'expected ' + msgObj + ' to not change'
|
|
3417
3550
|
);
|
|
3418
3551
|
}
|
|
3419
3552
|
|
|
@@ -3498,14 +3631,14 @@ Assertion.addMethod('changes', assertChanges);
|
|
|
3498
3631
|
* @namespace BDD
|
|
3499
3632
|
* @public
|
|
3500
3633
|
*/
|
|
3501
|
-
function assertIncreases
|
|
3634
|
+
function assertIncreases(subject, prop, msg) {
|
|
3502
3635
|
if (msg) flag(this, 'message', msg);
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3636
|
+
let fn = flag(this, 'object'),
|
|
3637
|
+
flagMsg = flag(this, 'message'),
|
|
3638
|
+
ssfi = flag(this, 'ssfi');
|
|
3506
3639
|
new Assertion(fn, flagMsg, ssfi, true).is.a('function');
|
|
3507
3640
|
|
|
3508
|
-
|
|
3641
|
+
let initial;
|
|
3509
3642
|
if (!prop) {
|
|
3510
3643
|
new Assertion(subject, flagMsg, ssfi, true).is.a('function');
|
|
3511
3644
|
initial = subject();
|
|
@@ -3519,8 +3652,8 @@ function assertIncreases (subject, prop, msg) {
|
|
|
3519
3652
|
|
|
3520
3653
|
fn();
|
|
3521
3654
|
|
|
3522
|
-
|
|
3523
|
-
|
|
3655
|
+
let final = prop === undefined || prop === null ? subject() : subject[prop];
|
|
3656
|
+
let msgObj = prop === undefined || prop === null ? initial : '.' + prop;
|
|
3524
3657
|
|
|
3525
3658
|
flag(this, 'deltaMsgObj', msgObj);
|
|
3526
3659
|
flag(this, 'initialDeltaValue', initial);
|
|
@@ -3529,9 +3662,9 @@ function assertIncreases (subject, prop, msg) {
|
|
|
3529
3662
|
flag(this, 'realDelta', final - initial);
|
|
3530
3663
|
|
|
3531
3664
|
this.assert(
|
|
3532
|
-
final - initial > 0
|
|
3533
|
-
|
|
3534
|
-
|
|
3665
|
+
final - initial > 0,
|
|
3666
|
+
'expected ' + msgObj + ' to increase',
|
|
3667
|
+
'expected ' + msgObj + ' to not increase'
|
|
3535
3668
|
);
|
|
3536
3669
|
}
|
|
3537
3670
|
|
|
@@ -3616,14 +3749,14 @@ Assertion.addMethod('increases', assertIncreases);
|
|
|
3616
3749
|
* @namespace BDD
|
|
3617
3750
|
* @public
|
|
3618
3751
|
*/
|
|
3619
|
-
function assertDecreases
|
|
3752
|
+
function assertDecreases(subject, prop, msg) {
|
|
3620
3753
|
if (msg) flag(this, 'message', msg);
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3754
|
+
let fn = flag(this, 'object'),
|
|
3755
|
+
flagMsg = flag(this, 'message'),
|
|
3756
|
+
ssfi = flag(this, 'ssfi');
|
|
3624
3757
|
new Assertion(fn, flagMsg, ssfi, true).is.a('function');
|
|
3625
3758
|
|
|
3626
|
-
|
|
3759
|
+
let initial;
|
|
3627
3760
|
if (!prop) {
|
|
3628
3761
|
new Assertion(subject, flagMsg, ssfi, true).is.a('function');
|
|
3629
3762
|
initial = subject();
|
|
@@ -3637,8 +3770,8 @@ function assertDecreases (subject, prop, msg) {
|
|
|
3637
3770
|
|
|
3638
3771
|
fn();
|
|
3639
3772
|
|
|
3640
|
-
|
|
3641
|
-
|
|
3773
|
+
let final = prop === undefined || prop === null ? subject() : subject[prop];
|
|
3774
|
+
let msgObj = prop === undefined || prop === null ? initial : '.' + prop;
|
|
3642
3775
|
|
|
3643
3776
|
flag(this, 'deltaMsgObj', msgObj);
|
|
3644
3777
|
flag(this, 'initialDeltaValue', initial);
|
|
@@ -3647,9 +3780,9 @@ function assertDecreases (subject, prop, msg) {
|
|
|
3647
3780
|
flag(this, 'realDelta', initial - final);
|
|
3648
3781
|
|
|
3649
3782
|
this.assert(
|
|
3650
|
-
final - initial < 0
|
|
3651
|
-
|
|
3652
|
-
|
|
3783
|
+
final - initial < 0,
|
|
3784
|
+
'expected ' + msgObj + ' to decrease',
|
|
3785
|
+
'expected ' + msgObj + ' to not decrease'
|
|
3653
3786
|
);
|
|
3654
3787
|
}
|
|
3655
3788
|
|
|
@@ -3724,13 +3857,13 @@ Assertion.addMethod('decreases', assertDecreases);
|
|
|
3724
3857
|
function assertDelta(delta, msg) {
|
|
3725
3858
|
if (msg) flag(this, 'message', msg);
|
|
3726
3859
|
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3860
|
+
let msgObj = flag(this, 'deltaMsgObj');
|
|
3861
|
+
let initial = flag(this, 'initialDeltaValue');
|
|
3862
|
+
let final = flag(this, 'finalDeltaValue');
|
|
3863
|
+
let behavior = flag(this, 'deltaBehavior');
|
|
3864
|
+
let realDelta = flag(this, 'realDelta');
|
|
3732
3865
|
|
|
3733
|
-
|
|
3866
|
+
let expression;
|
|
3734
3867
|
if (behavior === 'change') {
|
|
3735
3868
|
expression = Math.abs(final - initial) === Math.abs(delta);
|
|
3736
3869
|
} else {
|
|
@@ -3738,9 +3871,9 @@ function assertDelta(delta, msg) {
|
|
|
3738
3871
|
}
|
|
3739
3872
|
|
|
3740
3873
|
this.assert(
|
|
3741
|
-
expression
|
|
3742
|
-
|
|
3743
|
-
|
|
3874
|
+
expression,
|
|
3875
|
+
'expected ' + msgObj + ' to ' + behavior + ' by ' + delta,
|
|
3876
|
+
'expected ' + msgObj + ' to not ' + behavior + ' by ' + delta
|
|
3744
3877
|
);
|
|
3745
3878
|
}
|
|
3746
3879
|
|
|
@@ -3773,20 +3906,20 @@ Assertion.addMethod('by', assertDelta);
|
|
|
3773
3906
|
* @namespace BDD
|
|
3774
3907
|
* @public
|
|
3775
3908
|
*/
|
|
3776
|
-
Assertion.addProperty('extensible', function() {
|
|
3777
|
-
|
|
3909
|
+
Assertion.addProperty('extensible', function () {
|
|
3910
|
+
let obj = flag(this, 'object');
|
|
3778
3911
|
|
|
3779
3912
|
// In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
|
|
3780
3913
|
// In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
|
|
3781
3914
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
|
|
3782
3915
|
// The following provides ES6 behavior for ES5 environments.
|
|
3783
3916
|
|
|
3784
|
-
|
|
3917
|
+
let isExtensible = obj === Object(obj) && Object.isExtensible(obj);
|
|
3785
3918
|
|
|
3786
3919
|
this.assert(
|
|
3787
|
-
isExtensible
|
|
3788
|
-
|
|
3789
|
-
|
|
3920
|
+
isExtensible,
|
|
3921
|
+
'expected #{this} to be extensible',
|
|
3922
|
+
'expected #{this} to not be extensible'
|
|
3790
3923
|
);
|
|
3791
3924
|
});
|
|
3792
3925
|
|
|
@@ -3817,20 +3950,20 @@ Assertion.addProperty('extensible', function() {
|
|
|
3817
3950
|
* @namespace BDD
|
|
3818
3951
|
* @public
|
|
3819
3952
|
*/
|
|
3820
|
-
Assertion.addProperty('sealed', function() {
|
|
3821
|
-
|
|
3953
|
+
Assertion.addProperty('sealed', function () {
|
|
3954
|
+
let obj = flag(this, 'object');
|
|
3822
3955
|
|
|
3823
3956
|
// In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
|
|
3824
3957
|
// In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
|
|
3825
3958
|
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
|
|
3826
3959
|
// The following provides ES6 behavior for ES5 environments.
|
|
3827
3960
|
|
|
3828
|
-
|
|
3961
|
+
let isSealed = obj === Object(obj) ? Object.isSealed(obj) : true;
|
|
3829
3962
|
|
|
3830
3963
|
this.assert(
|
|
3831
|
-
isSealed
|
|
3832
|
-
|
|
3833
|
-
|
|
3964
|
+
isSealed,
|
|
3965
|
+
'expected #{this} to be sealed',
|
|
3966
|
+
'expected #{this} to not be sealed'
|
|
3834
3967
|
);
|
|
3835
3968
|
});
|
|
3836
3969
|
|
|
@@ -3858,20 +3991,20 @@ Assertion.addProperty('sealed', function() {
|
|
|
3858
3991
|
* @namespace BDD
|
|
3859
3992
|
* @public
|
|
3860
3993
|
*/
|
|
3861
|
-
Assertion.addProperty('frozen', function() {
|
|
3862
|
-
|
|
3994
|
+
Assertion.addProperty('frozen', function () {
|
|
3995
|
+
let obj = flag(this, 'object');
|
|
3863
3996
|
|
|
3864
3997
|
// In ES5, if the argument to this method is a primitive, then it will cause a TypeError.
|
|
3865
3998
|
// In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
|
|
3866
3999
|
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
|
|
3867
4000
|
// The following provides ES6 behavior for ES5 environments.
|
|
3868
4001
|
|
|
3869
|
-
|
|
4002
|
+
let isFrozen = obj === Object(obj) ? Object.isFrozen(obj) : true;
|
|
3870
4003
|
|
|
3871
4004
|
this.assert(
|
|
3872
|
-
isFrozen
|
|
3873
|
-
|
|
3874
|
-
|
|
4005
|
+
isFrozen,
|
|
4006
|
+
'expected #{this} to be frozen',
|
|
4007
|
+
'expected #{this} to not be frozen'
|
|
3875
4008
|
);
|
|
3876
4009
|
});
|
|
3877
4010
|
|
|
@@ -3923,12 +4056,101 @@ Assertion.addProperty('frozen', function() {
|
|
|
3923
4056
|
* @namespace BDD
|
|
3924
4057
|
* @public
|
|
3925
4058
|
*/
|
|
3926
|
-
Assertion.addProperty('finite', function(
|
|
3927
|
-
|
|
4059
|
+
Assertion.addProperty('finite', function (_msg) {
|
|
4060
|
+
let obj = flag(this, 'object');
|
|
4061
|
+
|
|
4062
|
+
this.assert(
|
|
4063
|
+
typeof obj === 'number' && isFinite(obj),
|
|
4064
|
+
'expected #{this} to be a finite number',
|
|
4065
|
+
'expected #{this} to not be a finite number'
|
|
4066
|
+
);
|
|
4067
|
+
});
|
|
4068
|
+
|
|
4069
|
+
/**
|
|
4070
|
+
* A subset-aware compare function
|
|
4071
|
+
*
|
|
4072
|
+
* @param {unknown} expected
|
|
4073
|
+
* @param {unknown} actual
|
|
4074
|
+
* @returns {boolean}
|
|
4075
|
+
*/
|
|
4076
|
+
function compareSubset(expected, actual) {
|
|
4077
|
+
if (expected === actual) {
|
|
4078
|
+
return true;
|
|
4079
|
+
}
|
|
4080
|
+
if (typeof actual !== typeof expected) {
|
|
4081
|
+
return false;
|
|
4082
|
+
}
|
|
4083
|
+
if (typeof expected !== 'object' || expected === null) {
|
|
4084
|
+
return expected === actual;
|
|
4085
|
+
}
|
|
4086
|
+
if (!actual) {
|
|
4087
|
+
return false;
|
|
4088
|
+
}
|
|
4089
|
+
|
|
4090
|
+
if (Array.isArray(expected)) {
|
|
4091
|
+
if (!Array.isArray(actual)) {
|
|
4092
|
+
return false;
|
|
4093
|
+
}
|
|
4094
|
+
return expected.every(function (exp) {
|
|
4095
|
+
return actual.some(function (act) {
|
|
4096
|
+
return compareSubset(exp, act);
|
|
4097
|
+
});
|
|
4098
|
+
});
|
|
4099
|
+
}
|
|
4100
|
+
|
|
4101
|
+
if (expected instanceof Date) {
|
|
4102
|
+
if (actual instanceof Date) {
|
|
4103
|
+
return expected.getTime() === actual.getTime();
|
|
4104
|
+
} else {
|
|
4105
|
+
return false;
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
|
|
4109
|
+
return Object.keys(expected).every(function (key) {
|
|
4110
|
+
let expectedValue = expected[key];
|
|
4111
|
+
let actualValue = actual[key];
|
|
4112
|
+
if (
|
|
4113
|
+
typeof expectedValue === 'object' &&
|
|
4114
|
+
expectedValue !== null &&
|
|
4115
|
+
actualValue !== null
|
|
4116
|
+
) {
|
|
4117
|
+
return compareSubset(expectedValue, actualValue);
|
|
4118
|
+
}
|
|
4119
|
+
if (typeof expectedValue === 'function') {
|
|
4120
|
+
return expectedValue(actualValue);
|
|
4121
|
+
}
|
|
4122
|
+
return actualValue === expectedValue;
|
|
4123
|
+
});
|
|
4124
|
+
}
|
|
4125
|
+
|
|
4126
|
+
/**
|
|
4127
|
+
* ### .containSubset
|
|
4128
|
+
*
|
|
4129
|
+
* Asserts that the target primitive/object/array structure deeply contains all provided fields
|
|
4130
|
+
* at the same key/depth as the provided structure.
|
|
4131
|
+
*
|
|
4132
|
+
* When comparing arrays, the target must contain the subset of at least one of each object/value in the subset array.
|
|
4133
|
+
* Order does not matter.
|
|
4134
|
+
*
|
|
4135
|
+
* expect({name: {first: "John", last: "Smith"}}).to.containSubset({name: {first: "John"}});
|
|
4136
|
+
*
|
|
4137
|
+
* Add `.not` earlier in the chain to negate the assertion. This will cause the assertion to fail
|
|
4138
|
+
* only if the target DOES contains the provided data at the expected keys/depths.
|
|
4139
|
+
*
|
|
4140
|
+
* @name containSubset
|
|
4141
|
+
* @namespace BDD
|
|
4142
|
+
* @public
|
|
4143
|
+
*/
|
|
4144
|
+
Assertion.addMethod('containSubset', function (expected) {
|
|
4145
|
+
const actual = _.flag(this, 'object');
|
|
4146
|
+
const showDiff = config.showDiff;
|
|
3928
4147
|
|
|
3929
4148
|
this.assert(
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
4149
|
+
compareSubset(expected, actual),
|
|
4150
|
+
'expected #{act} to contain subset #{exp}',
|
|
4151
|
+
'expected #{act} to not contain subset #{exp}',
|
|
4152
|
+
expected,
|
|
4153
|
+
actual,
|
|
4154
|
+
showDiff
|
|
3933
4155
|
);
|
|
3934
4156
|
});
|