chai 4.0.0 → 4.1.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/CODEOWNERS +1 -0
- package/README.md +1 -1
- package/chai.js +254 -190
- package/lib/chai/core/assertions.js +244 -122
- package/lib/chai/interface/assert.js +4 -4
- package/lib/chai/utils/expectTypes.js +3 -4
- package/lib/chai/utils/inspect.js +1 -1
- package/lib/chai.js +1 -1
- package/package.json +2 -3
|
@@ -330,6 +330,16 @@ module.exports = function (chai, _) {
|
|
|
330
330
|
*
|
|
331
331
|
* expect({a: 1, b: 2, c: 3}).to.include({a: 1, b: 2});
|
|
332
332
|
*
|
|
333
|
+
* When the target is a Set or WeakSet, `.include` asserts that the given `val` is a
|
|
334
|
+
* member of the target. SameValueZero equality algorithm is used.
|
|
335
|
+
*
|
|
336
|
+
* expect(new Set([1, 2])).to.include(2);
|
|
337
|
+
*
|
|
338
|
+
* When the target is a Map, `.include` asserts that the given `val` is one of
|
|
339
|
+
* the values of the target. SameValueZero equality algorithm is used.
|
|
340
|
+
*
|
|
341
|
+
* expect(new Map([['a', 1], ['b', 2]])).to.include(2);
|
|
342
|
+
*
|
|
333
343
|
* Because `.include` does different things based on the target's type, it's
|
|
334
344
|
* important to check the target's type before using `.include`. See the `.a`
|
|
335
345
|
* doc for info on testing a target's type.
|
|
@@ -338,8 +348,8 @@ module.exports = function (chai, _) {
|
|
|
338
348
|
*
|
|
339
349
|
* By default, strict (`===`) equality is used to compare array members and
|
|
340
350
|
* object properties. Add `.deep` earlier in the chain to use deep equality
|
|
341
|
-
* instead. See the `deep-eql` project
|
|
342
|
-
* algorithm: https://github.com/chaijs/deep-eql.
|
|
351
|
+
* instead (WeakSet targets are not supported). See the `deep-eql` project
|
|
352
|
+
* page for info on the deep equality algorithm: https://github.com/chaijs/deep-eql.
|
|
343
353
|
*
|
|
344
354
|
* // Target array deeply (but not strictly) includes `{a: 1}`
|
|
345
355
|
* expect([{a: 1}]).to.deep.include({a: 1});
|
|
@@ -449,65 +459,124 @@ module.exports = function (chai, _) {
|
|
|
449
459
|
* @api public
|
|
450
460
|
*/
|
|
451
461
|
|
|
452
|
-
function
|
|
453
|
-
|
|
462
|
+
function SameValueZero(a, b) {
|
|
463
|
+
return (_.isNaN(a) && _.isNaN(b)) || a === b;
|
|
454
464
|
}
|
|
455
465
|
|
|
456
|
-
function
|
|
457
|
-
|
|
458
|
-
return _.eql(arrVal, val);
|
|
459
|
-
});
|
|
466
|
+
function includeChainingBehavior () {
|
|
467
|
+
flag(this, 'contains', true);
|
|
460
468
|
}
|
|
461
469
|
|
|
462
470
|
function include (val, msg) {
|
|
463
471
|
if (msg) flag(this, 'message', msg);
|
|
464
|
-
|
|
465
|
-
_.expectTypes(this, ['array', 'object', 'string'], flag(this, 'ssfi'));
|
|
466
|
-
|
|
472
|
+
|
|
467
473
|
var obj = flag(this, 'object')
|
|
468
474
|
, objType = _.type(obj).toLowerCase()
|
|
475
|
+
, flagMsg = flag(this, 'message')
|
|
476
|
+
, negate = flag(this, 'negate')
|
|
477
|
+
, ssfi = flag(this, 'ssfi')
|
|
469
478
|
, isDeep = flag(this, 'deep')
|
|
470
479
|
, descriptor = isDeep ? 'deep ' : '';
|
|
471
480
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
481
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
482
|
+
|
|
483
|
+
var included = false;
|
|
484
|
+
|
|
485
|
+
switch (objType) {
|
|
486
|
+
case 'string':
|
|
487
|
+
included = obj.indexOf(val) !== -1;
|
|
488
|
+
break;
|
|
489
|
+
|
|
490
|
+
case 'weakset':
|
|
491
|
+
if (isDeep) {
|
|
492
|
+
throw new AssertionError(
|
|
493
|
+
flagMsg + 'unable to use .deep.include with WeakSet',
|
|
494
|
+
undefined,
|
|
495
|
+
ssfi
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
included = obj.has(val);
|
|
500
|
+
break;
|
|
501
|
+
|
|
502
|
+
case 'map':
|
|
503
|
+
var isEql = isDeep ? _.eql : SameValueZero;
|
|
504
|
+
obj.forEach(function (item) {
|
|
505
|
+
included = included || isEql(item, val);
|
|
506
|
+
});
|
|
507
|
+
break;
|
|
508
|
+
|
|
509
|
+
case 'set':
|
|
510
|
+
if (isDeep) {
|
|
511
|
+
obj.forEach(function (item) {
|
|
512
|
+
included = included || _.eql(item, val);
|
|
513
|
+
});
|
|
514
|
+
} else {
|
|
515
|
+
included = obj.has(val);
|
|
487
516
|
}
|
|
517
|
+
break;
|
|
488
518
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
519
|
+
case 'array':
|
|
520
|
+
if (isDeep) {
|
|
521
|
+
included = obj.some(function (item) {
|
|
522
|
+
return _.eql(item, val);
|
|
523
|
+
})
|
|
524
|
+
} else {
|
|
525
|
+
included = obj.indexOf(val) !== -1;
|
|
495
526
|
}
|
|
496
|
-
|
|
527
|
+
break;
|
|
497
528
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
529
|
+
default:
|
|
530
|
+
// This block is for asserting a subset of properties in an object.
|
|
531
|
+
// `_.expectTypes` isn't used here because `.include` should work with
|
|
532
|
+
// objects with a custom `@@toStringTag`.
|
|
533
|
+
if (val !== Object(val)) {
|
|
534
|
+
throw new AssertionError(
|
|
535
|
+
flagMsg + 'object tested must be an array, a map, an object,'
|
|
536
|
+
+ ' a set, a string, or a weakset, but ' + objType + ' given',
|
|
537
|
+
undefined,
|
|
538
|
+
ssfi
|
|
539
|
+
);
|
|
540
|
+
}
|
|
503
541
|
|
|
504
|
-
|
|
542
|
+
var props = Object.keys(val)
|
|
543
|
+
, firstErr = null
|
|
544
|
+
, numErrs = 0;
|
|
545
|
+
|
|
546
|
+
props.forEach(function (prop) {
|
|
547
|
+
var propAssertion = new Assertion(obj);
|
|
548
|
+
_.transferFlags(this, propAssertion, true);
|
|
549
|
+
flag(propAssertion, 'lockSsfi', true);
|
|
550
|
+
|
|
551
|
+
if (!negate || props.length === 1) {
|
|
552
|
+
propAssertion.property(prop, val[prop]);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
try {
|
|
557
|
+
propAssertion.property(prop, val[prop]);
|
|
558
|
+
} catch (err) {
|
|
559
|
+
if (!_.checkError.compatibleConstructor(err, AssertionError)) {
|
|
560
|
+
throw err;
|
|
561
|
+
}
|
|
562
|
+
if (firstErr === null) firstErr = err;
|
|
563
|
+
numErrs++;
|
|
564
|
+
}
|
|
565
|
+
}, this);
|
|
566
|
+
|
|
567
|
+
// When validating .not.include with multiple properties, we only want
|
|
568
|
+
// to throw an assertion error if all of the properties are included,
|
|
569
|
+
// in which case we throw the first property assertion error that we
|
|
570
|
+
// encountered.
|
|
571
|
+
if (negate && props.length > 1 && numErrs === props.length) {
|
|
572
|
+
throw firstErr;
|
|
573
|
+
}
|
|
574
|
+
return;
|
|
505
575
|
}
|
|
506
576
|
|
|
507
|
-
// Assert inclusion in
|
|
577
|
+
// Assert inclusion in collection or substring in a string.
|
|
508
578
|
this.assert(
|
|
509
|
-
|
|
510
|
-
: isDeepIncluded(obj, val)
|
|
579
|
+
included
|
|
511
580
|
, 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val)
|
|
512
581
|
, 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val));
|
|
513
582
|
}
|
|
@@ -1024,7 +1093,7 @@ module.exports = function (chai, _) {
|
|
|
1024
1093
|
/**
|
|
1025
1094
|
* ### .above(n[, msg])
|
|
1026
1095
|
*
|
|
1027
|
-
* Asserts that the target is a number greater than the given number `n
|
|
1096
|
+
* Asserts that the target is a number or a date greater than the given number or date `n` respectively.
|
|
1028
1097
|
* However, it's often best to assert that the target is equal to its expected
|
|
1029
1098
|
* value.
|
|
1030
1099
|
*
|
|
@@ -1069,21 +1138,29 @@ module.exports = function (chai, _) {
|
|
|
1069
1138
|
var obj = flag(this, 'object')
|
|
1070
1139
|
, doLength = flag(this, 'doLength')
|
|
1071
1140
|
, flagMsg = flag(this, 'message')
|
|
1072
|
-
,
|
|
1141
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1142
|
+
, ssfi = flag(this, 'ssfi')
|
|
1143
|
+
, objType = _.type(obj).toLowerCase()
|
|
1144
|
+
, nType = _.type(n).toLowerCase()
|
|
1145
|
+
, shouldThrow = true;
|
|
1073
1146
|
|
|
1074
1147
|
if (doLength) {
|
|
1075
1148
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1152
|
+
errorMessage = msgPrefix + 'the argument to above must be a date';
|
|
1153
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1154
|
+
errorMessage = msgPrefix + 'the argument to above must be a number';
|
|
1155
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1156
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1157
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1076
1158
|
} else {
|
|
1077
|
-
|
|
1159
|
+
shouldThrow = false;
|
|
1078
1160
|
}
|
|
1079
1161
|
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1082
|
-
throw new AssertionError(
|
|
1083
|
-
flagMsg + 'the argument to above must be a number',
|
|
1084
|
-
undefined,
|
|
1085
|
-
ssfi
|
|
1086
|
-
);
|
|
1162
|
+
if (shouldThrow) {
|
|
1163
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1087
1164
|
}
|
|
1088
1165
|
|
|
1089
1166
|
if (doLength) {
|
|
@@ -1098,8 +1175,9 @@ module.exports = function (chai, _) {
|
|
|
1098
1175
|
} else {
|
|
1099
1176
|
this.assert(
|
|
1100
1177
|
obj > n
|
|
1101
|
-
, 'expected #{this} to be above '
|
|
1102
|
-
, 'expected #{this} to be at most '
|
|
1178
|
+
, 'expected #{this} to be above #{exp}'
|
|
1179
|
+
, 'expected #{this} to be at most #{exp}'
|
|
1180
|
+
, n
|
|
1103
1181
|
);
|
|
1104
1182
|
}
|
|
1105
1183
|
}
|
|
@@ -1111,8 +1189,8 @@ module.exports = function (chai, _) {
|
|
|
1111
1189
|
/**
|
|
1112
1190
|
* ### .least(n[, msg])
|
|
1113
1191
|
*
|
|
1114
|
-
* Asserts that the target is a number greater than or equal to the given
|
|
1115
|
-
* number `n
|
|
1192
|
+
* Asserts that the target is a number or a date greater than or equal to the given
|
|
1193
|
+
* number or date `n` respectively. However, it's often best to assert that the target is equal to
|
|
1116
1194
|
* its expected value.
|
|
1117
1195
|
*
|
|
1118
1196
|
* expect(2).to.equal(2); // Recommended
|
|
@@ -1156,21 +1234,29 @@ module.exports = function (chai, _) {
|
|
|
1156
1234
|
var obj = flag(this, 'object')
|
|
1157
1235
|
, doLength = flag(this, 'doLength')
|
|
1158
1236
|
, flagMsg = flag(this, 'message')
|
|
1159
|
-
,
|
|
1237
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1238
|
+
, ssfi = flag(this, 'ssfi')
|
|
1239
|
+
, objType = _.type(obj).toLowerCase()
|
|
1240
|
+
, nType = _.type(n).toLowerCase()
|
|
1241
|
+
, shouldThrow = true;
|
|
1160
1242
|
|
|
1161
1243
|
if (doLength) {
|
|
1162
1244
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1248
|
+
errorMessage = msgPrefix + 'the argument to least must be a date';
|
|
1249
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1250
|
+
errorMessage = msgPrefix + 'the argument to least must be a number';
|
|
1251
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1252
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1253
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1163
1254
|
} else {
|
|
1164
|
-
|
|
1255
|
+
shouldThrow = false;
|
|
1165
1256
|
}
|
|
1166
1257
|
|
|
1167
|
-
if (
|
|
1168
|
-
|
|
1169
|
-
throw new AssertionError(
|
|
1170
|
-
flagMsg + 'the argument to least must be a number',
|
|
1171
|
-
undefined,
|
|
1172
|
-
ssfi
|
|
1173
|
-
);
|
|
1258
|
+
if (shouldThrow) {
|
|
1259
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1174
1260
|
}
|
|
1175
1261
|
|
|
1176
1262
|
if (doLength) {
|
|
@@ -1185,8 +1271,9 @@ module.exports = function (chai, _) {
|
|
|
1185
1271
|
} else {
|
|
1186
1272
|
this.assert(
|
|
1187
1273
|
obj >= n
|
|
1188
|
-
, 'expected #{this} to be at least '
|
|
1189
|
-
, 'expected #{this} to be below '
|
|
1274
|
+
, 'expected #{this} to be at least #{exp}'
|
|
1275
|
+
, 'expected #{this} to be below #{exp}'
|
|
1276
|
+
, n
|
|
1190
1277
|
);
|
|
1191
1278
|
}
|
|
1192
1279
|
}
|
|
@@ -1197,7 +1284,7 @@ module.exports = function (chai, _) {
|
|
|
1197
1284
|
/**
|
|
1198
1285
|
* ### .below(n[, msg])
|
|
1199
1286
|
*
|
|
1200
|
-
* Asserts that the target is a number less than the given number `n
|
|
1287
|
+
* Asserts that the target is a number or a date less than the given number or date `n` respectively.
|
|
1201
1288
|
* However, it's often best to assert that the target is equal to its expected
|
|
1202
1289
|
* value.
|
|
1203
1290
|
*
|
|
@@ -1242,21 +1329,29 @@ module.exports = function (chai, _) {
|
|
|
1242
1329
|
var obj = flag(this, 'object')
|
|
1243
1330
|
, doLength = flag(this, 'doLength')
|
|
1244
1331
|
, flagMsg = flag(this, 'message')
|
|
1245
|
-
,
|
|
1332
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1333
|
+
, ssfi = flag(this, 'ssfi')
|
|
1334
|
+
, objType = _.type(obj).toLowerCase()
|
|
1335
|
+
, nType = _.type(n).toLowerCase()
|
|
1336
|
+
, shouldThrow = true;
|
|
1246
1337
|
|
|
1247
1338
|
if (doLength) {
|
|
1248
1339
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1343
|
+
errorMessage = msgPrefix + 'the argument to below must be a date';
|
|
1344
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1345
|
+
errorMessage = msgPrefix + 'the argument to below must be a number';
|
|
1346
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1347
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1348
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1249
1349
|
} else {
|
|
1250
|
-
|
|
1350
|
+
shouldThrow = false;
|
|
1251
1351
|
}
|
|
1252
1352
|
|
|
1253
|
-
if (
|
|
1254
|
-
|
|
1255
|
-
throw new AssertionError(
|
|
1256
|
-
flagMsg + 'the argument to below must be a number',
|
|
1257
|
-
undefined,
|
|
1258
|
-
ssfi
|
|
1259
|
-
);
|
|
1353
|
+
if (shouldThrow) {
|
|
1354
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1260
1355
|
}
|
|
1261
1356
|
|
|
1262
1357
|
if (doLength) {
|
|
@@ -1271,8 +1366,9 @@ module.exports = function (chai, _) {
|
|
|
1271
1366
|
} else {
|
|
1272
1367
|
this.assert(
|
|
1273
1368
|
obj < n
|
|
1274
|
-
, 'expected #{this} to be below '
|
|
1275
|
-
, 'expected #{this} to be at least '
|
|
1369
|
+
, 'expected #{this} to be below #{exp}'
|
|
1370
|
+
, 'expected #{this} to be at least #{exp}'
|
|
1371
|
+
, n
|
|
1276
1372
|
);
|
|
1277
1373
|
}
|
|
1278
1374
|
}
|
|
@@ -1284,8 +1380,8 @@ module.exports = function (chai, _) {
|
|
|
1284
1380
|
/**
|
|
1285
1381
|
* ### .most(n[, msg])
|
|
1286
1382
|
*
|
|
1287
|
-
* Asserts that the target is a number less than or equal to the given number
|
|
1288
|
-
* `n
|
|
1383
|
+
* Asserts that the target is a number or a date less than or equal to the given number
|
|
1384
|
+
* or date `n` respectively. However, it's often best to assert that the target is equal to its
|
|
1289
1385
|
* expected value.
|
|
1290
1386
|
*
|
|
1291
1387
|
* expect(1).to.equal(1); // Recommended
|
|
@@ -1328,21 +1424,29 @@ module.exports = function (chai, _) {
|
|
|
1328
1424
|
var obj = flag(this, 'object')
|
|
1329
1425
|
, doLength = flag(this, 'doLength')
|
|
1330
1426
|
, flagMsg = flag(this, 'message')
|
|
1331
|
-
,
|
|
1427
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1428
|
+
, ssfi = flag(this, 'ssfi')
|
|
1429
|
+
, objType = _.type(obj).toLowerCase()
|
|
1430
|
+
, nType = _.type(n).toLowerCase()
|
|
1431
|
+
, shouldThrow = true;
|
|
1332
1432
|
|
|
1333
1433
|
if (doLength) {
|
|
1334
1434
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1435
|
+
}
|
|
1436
|
+
|
|
1437
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1438
|
+
errorMessage = msgPrefix + 'the argument to most must be a date';
|
|
1439
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1440
|
+
errorMessage = msgPrefix + 'the argument to most must be a number';
|
|
1441
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1442
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1443
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1335
1444
|
} else {
|
|
1336
|
-
|
|
1445
|
+
shouldThrow = false;
|
|
1337
1446
|
}
|
|
1338
1447
|
|
|
1339
|
-
if (
|
|
1340
|
-
|
|
1341
|
-
throw new AssertionError(
|
|
1342
|
-
flagMsg + 'the argument to most must be a number',
|
|
1343
|
-
undefined,
|
|
1344
|
-
ssfi
|
|
1345
|
-
);
|
|
1448
|
+
if (shouldThrow) {
|
|
1449
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1346
1450
|
}
|
|
1347
1451
|
|
|
1348
1452
|
if (doLength) {
|
|
@@ -1357,8 +1461,9 @@ module.exports = function (chai, _) {
|
|
|
1357
1461
|
} else {
|
|
1358
1462
|
this.assert(
|
|
1359
1463
|
obj <= n
|
|
1360
|
-
, 'expected #{this} to be at most '
|
|
1361
|
-
, 'expected #{this} to be above '
|
|
1464
|
+
, 'expected #{this} to be at most #{exp}'
|
|
1465
|
+
, 'expected #{this} to be above #{exp}'
|
|
1466
|
+
, n
|
|
1362
1467
|
);
|
|
1363
1468
|
}
|
|
1364
1469
|
}
|
|
@@ -1369,8 +1474,8 @@ module.exports = function (chai, _) {
|
|
|
1369
1474
|
/**
|
|
1370
1475
|
* ### .within(start, finish[, msg])
|
|
1371
1476
|
*
|
|
1372
|
-
* Asserts that the target is a number greater than or equal to the given
|
|
1373
|
-
* number `start`, and less than or equal to the given number `finish
|
|
1477
|
+
* Asserts that the target is a number or a date greater than or equal to the given
|
|
1478
|
+
* number or date `start`, and less than or equal to the given number or date `finish` respectively.
|
|
1374
1479
|
* However, it's often best to assert that the target is equal to its expected
|
|
1375
1480
|
* value.
|
|
1376
1481
|
*
|
|
@@ -1412,24 +1517,35 @@ module.exports = function (chai, _) {
|
|
|
1412
1517
|
Assertion.addMethod('within', function (start, finish, msg) {
|
|
1413
1518
|
if (msg) flag(this, 'message', msg);
|
|
1414
1519
|
var obj = flag(this, 'object')
|
|
1415
|
-
, range = start + '..' + finish
|
|
1416
1520
|
, doLength = flag(this, 'doLength')
|
|
1417
1521
|
, flagMsg = flag(this, 'message')
|
|
1418
|
-
,
|
|
1522
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1523
|
+
, ssfi = flag(this, 'ssfi')
|
|
1524
|
+
, objType = _.type(obj).toLowerCase()
|
|
1525
|
+
, startType = _.type(start).toLowerCase()
|
|
1526
|
+
, finishType = _.type(finish).toLowerCase()
|
|
1527
|
+
, shouldThrow = true
|
|
1528
|
+
, range = (startType === 'date' && finishType === 'date')
|
|
1529
|
+
? start.toUTCString() + '..' + finish.toUTCString()
|
|
1530
|
+
: start + '..' + finish;
|
|
1419
1531
|
|
|
1420
1532
|
if (doLength) {
|
|
1421
1533
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) {
|
|
1537
|
+
errorMessage = msgPrefix + 'the arguments to within must be dates';
|
|
1538
|
+
} else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) {
|
|
1539
|
+
errorMessage = msgPrefix + 'the arguments to within must be numbers';
|
|
1540
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1541
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1542
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1422
1543
|
} else {
|
|
1423
|
-
|
|
1544
|
+
shouldThrow = false;
|
|
1424
1545
|
}
|
|
1425
1546
|
|
|
1426
|
-
if (
|
|
1427
|
-
|
|
1428
|
-
throw new AssertionError(
|
|
1429
|
-
flagMsg + 'the arguments to within must be numbers',
|
|
1430
|
-
undefined,
|
|
1431
|
-
ssfi
|
|
1432
|
-
);
|
|
1547
|
+
if (shouldThrow) {
|
|
1548
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1433
1549
|
}
|
|
1434
1550
|
|
|
1435
1551
|
if (doLength) {
|
|
@@ -1493,28 +1609,25 @@ module.exports = function (chai, _) {
|
|
|
1493
1609
|
var target = flag(this, 'object')
|
|
1494
1610
|
var ssfi = flag(this, 'ssfi');
|
|
1495
1611
|
var flagMsg = flag(this, 'message');
|
|
1496
|
-
var validInstanceOfTarget = constructor === Object(constructor) && (
|
|
1497
|
-
typeof constructor === 'function' ||
|
|
1498
|
-
(typeof Symbol !== 'undefined' &&
|
|
1499
|
-
typeof Symbol.hasInstance !== 'undefined' &&
|
|
1500
|
-
Symbol.hasInstance in constructor)
|
|
1501
|
-
);
|
|
1502
1612
|
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
flagMsg
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1613
|
+
try {
|
|
1614
|
+
var isInstanceOf = target instanceof constructor;
|
|
1615
|
+
} catch (err) {
|
|
1616
|
+
if (err instanceof TypeError) {
|
|
1617
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1618
|
+
throw new AssertionError(
|
|
1619
|
+
flagMsg + 'The instanceof assertion needs a constructor but '
|
|
1620
|
+
+ _.type(constructor) + ' was given.',
|
|
1621
|
+
undefined,
|
|
1622
|
+
ssfi
|
|
1623
|
+
);
|
|
1624
|
+
}
|
|
1625
|
+
throw err;
|
|
1511
1626
|
}
|
|
1512
1627
|
|
|
1513
|
-
var isInstanceOf = target instanceof constructor
|
|
1514
|
-
|
|
1515
1628
|
var name = _.getName(constructor);
|
|
1516
1629
|
if (name === null) {
|
|
1517
|
-
|
|
1630
|
+
name = 'an unnamed constructor';
|
|
1518
1631
|
}
|
|
1519
1632
|
|
|
1520
1633
|
this.assert(
|
|
@@ -1644,6 +1757,7 @@ module.exports = function (chai, _) {
|
|
|
1644
1757
|
var isNested = flag(this, 'nested')
|
|
1645
1758
|
, isOwn = flag(this, 'own')
|
|
1646
1759
|
, flagMsg = flag(this, 'message')
|
|
1760
|
+
, obj = flag(this, 'object')
|
|
1647
1761
|
, ssfi = flag(this, 'ssfi');
|
|
1648
1762
|
|
|
1649
1763
|
if (isNested && isOwn) {
|
|
@@ -1655,9 +1769,17 @@ module.exports = function (chai, _) {
|
|
|
1655
1769
|
);
|
|
1656
1770
|
}
|
|
1657
1771
|
|
|
1772
|
+
if (obj === null || obj === undefined) {
|
|
1773
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1774
|
+
throw new AssertionError(
|
|
1775
|
+
flagMsg + 'Target cannot be null or undefined.',
|
|
1776
|
+
undefined,
|
|
1777
|
+
ssfi
|
|
1778
|
+
);
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1658
1781
|
var isDeep = flag(this, 'deep')
|
|
1659
1782
|
, negate = flag(this, 'negate')
|
|
1660
|
-
, obj = flag(this, 'object')
|
|
1661
1783
|
, pathInfo = isNested ? _.getPathInfo(obj, name) : null
|
|
1662
1784
|
, value = isNested ? pathInfo.value : obj[name];
|
|
1663
1785
|
|
|
@@ -1675,10 +1675,10 @@ module.exports = function (chai, util) {
|
|
|
1675
1675
|
* You can also provide a single object instead of a `keys` array and its keys
|
|
1676
1676
|
* will be used as the expected set of keys.
|
|
1677
1677
|
*
|
|
1678
|
-
* assert.
|
|
1679
|
-
* assert.
|
|
1680
|
-
* assert.
|
|
1681
|
-
* assert.
|
|
1678
|
+
* assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, ['foo', 'iDontExist', 'baz']);
|
|
1679
|
+
* assert.hasAnyKeys({foo: 1, bar: 2, baz: 3}, {foo: 30, iDontExist: 99, baz: 1337});
|
|
1680
|
+
* assert.hasAnyKeys(new Map([[{foo: 1}, 'bar'], ['key', 'value']]), [{foo: 1}, 'key']);
|
|
1681
|
+
* assert.hasAnyKeys(new Set([{foo: 'bar'}, 'anotherKey']), [{foo: 'bar'}, 'anotherKey']);
|
|
1682
1682
|
*
|
|
1683
1683
|
* @name hasAnyKeys
|
|
1684
1684
|
* @param {Mixed} object
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @param {Mixed} obj constructed Assertion
|
|
15
15
|
* @param {Array} type A list of allowed types for this assertion
|
|
16
|
-
* @param {Function} ssfi starting point for removing implementation frames from
|
|
17
|
-
* stack trace of AssertionError
|
|
18
16
|
* @namespace Utils
|
|
19
17
|
* @name expectTypes
|
|
20
18
|
* @api public
|
|
@@ -24,8 +22,9 @@ var AssertionError = require('assertion-error');
|
|
|
24
22
|
var flag = require('./flag');
|
|
25
23
|
var type = require('type-detect');
|
|
26
24
|
|
|
27
|
-
module.exports = function expectTypes(obj, types
|
|
25
|
+
module.exports = function expectTypes(obj, types) {
|
|
28
26
|
var flagMsg = flag(obj, 'message');
|
|
27
|
+
var ssfi = flag(obj, 'ssfi');
|
|
29
28
|
|
|
30
29
|
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
31
30
|
|
|
@@ -33,7 +32,7 @@ module.exports = function expectTypes(obj, types, ssfi) {
|
|
|
33
32
|
types = types.map(function (t) { return t.toLowerCase(); });
|
|
34
33
|
types.sort();
|
|
35
34
|
|
|
36
|
-
// Transforms ['lorem', 'ipsum'] into 'a
|
|
35
|
+
// Transforms ['lorem', 'ipsum'] into 'a lorem, or an ipsum'
|
|
37
36
|
var str = types.map(function (t, index) {
|
|
38
37
|
var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
|
|
39
38
|
var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
|
|
@@ -86,7 +86,7 @@ function formatValue(ctx, value, recurseTimes) {
|
|
|
86
86
|
var container = document.createElementNS(ns, '_');
|
|
87
87
|
|
|
88
88
|
container.appendChild(value.cloneNode(false));
|
|
89
|
-
html = container.innerHTML
|
|
89
|
+
var html = container.innerHTML
|
|
90
90
|
.replace('><', '>' + value.innerHTML + '<');
|
|
91
91
|
container.innerHTML = '';
|
|
92
92
|
return html;
|
package/lib/chai.js
CHANGED
package/package.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"Veselin Todorov <hi@vesln.com>",
|
|
18
18
|
"John Firebaugh <john.firebaugh@gmail.com>"
|
|
19
19
|
],
|
|
20
|
-
"version": "4.
|
|
20
|
+
"version": "4.1.1",
|
|
21
21
|
"repository": {
|
|
22
22
|
"type": "git",
|
|
23
23
|
"url": "https://github.com/chaijs/chai"
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
"url": "https://github.com/chaijs/chai/issues"
|
|
27
27
|
},
|
|
28
28
|
"main": "./index",
|
|
29
|
-
"browser": "./chai.js",
|
|
30
29
|
"scripts": {
|
|
31
30
|
"test": "make test"
|
|
32
31
|
},
|
|
@@ -42,7 +41,7 @@
|
|
|
42
41
|
"type-detect": "^4.0.0"
|
|
43
42
|
},
|
|
44
43
|
"devDependencies": {
|
|
45
|
-
"browserify": "^
|
|
44
|
+
"browserify": "^14.4.0",
|
|
46
45
|
"bump-cli": "^1.1.3",
|
|
47
46
|
"istanbul": "^0.4.3",
|
|
48
47
|
"karma": "^1.0.0",
|