chai 4.0.0-canary.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CODEOWNERS +1 -0
- package/README.md +1 -1
- package/chai.js +408 -145
- package/lib/chai/core/assertions.js +195 -78
- package/lib/chai/interface/assert.js +191 -0
- package/lib/chai/utils/addChainableMethod.js +10 -1
- 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,25 +459,24 @@ 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
472
|
|
|
465
|
-
_.expectTypes(this, [
|
|
473
|
+
_.expectTypes(this, [
|
|
474
|
+
'array', 'object', 'string',
|
|
475
|
+
'map', 'set', 'weakset',
|
|
476
|
+
]);
|
|
466
477
|
|
|
467
478
|
var obj = flag(this, 'object')
|
|
468
|
-
, objType = _.type(obj).toLowerCase()
|
|
469
|
-
, isDeep = flag(this, 'deep')
|
|
470
|
-
, descriptor = isDeep ? 'deep ' : '';
|
|
479
|
+
, objType = _.type(obj).toLowerCase();
|
|
471
480
|
|
|
472
481
|
// This block is for asserting a subset of properties in an object.
|
|
473
482
|
if (objType === 'object') {
|
|
@@ -504,10 +513,62 @@ module.exports = function (chai, _) {
|
|
|
504
513
|
return;
|
|
505
514
|
}
|
|
506
515
|
|
|
507
|
-
|
|
516
|
+
var isDeep = flag(this, 'deep')
|
|
517
|
+
, descriptor = isDeep ? 'deep ' : ''
|
|
518
|
+
, included = false;
|
|
519
|
+
|
|
520
|
+
switch (objType) {
|
|
521
|
+
case 'string':
|
|
522
|
+
included = obj.indexOf(val) !== -1;
|
|
523
|
+
break;
|
|
524
|
+
|
|
525
|
+
case 'weakset':
|
|
526
|
+
if (isDeep) {
|
|
527
|
+
var flagMsg = flag(this, 'message')
|
|
528
|
+
, ssfi = flag(this, 'ssfi');
|
|
529
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
530
|
+
|
|
531
|
+
throw new AssertionError(
|
|
532
|
+
flagMsg + 'unable to use .deep.include with WeakSet',
|
|
533
|
+
undefined,
|
|
534
|
+
ssfi
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
included = obj.has(val);
|
|
539
|
+
break;
|
|
540
|
+
|
|
541
|
+
case 'map':
|
|
542
|
+
var isEql = isDeep ? _.eql : SameValueZero;
|
|
543
|
+
obj.forEach(function (item) {
|
|
544
|
+
included = included || isEql(item, val);
|
|
545
|
+
});
|
|
546
|
+
break;
|
|
547
|
+
|
|
548
|
+
case 'set':
|
|
549
|
+
if (isDeep) {
|
|
550
|
+
obj.forEach(function (item) {
|
|
551
|
+
included = included || _.eql(item, val);
|
|
552
|
+
});
|
|
553
|
+
} else {
|
|
554
|
+
included = obj.has(val);
|
|
555
|
+
}
|
|
556
|
+
break;
|
|
557
|
+
|
|
558
|
+
case 'array':
|
|
559
|
+
if (isDeep) {
|
|
560
|
+
included = obj.some(function (item) {
|
|
561
|
+
return _.eql(item, val);
|
|
562
|
+
})
|
|
563
|
+
} else {
|
|
564
|
+
included = obj.indexOf(val) !== -1;
|
|
565
|
+
}
|
|
566
|
+
break;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// Assert inclusion in collection or substring in a string.
|
|
508
570
|
this.assert(
|
|
509
|
-
|
|
510
|
-
: isDeepIncluded(obj, val)
|
|
571
|
+
included
|
|
511
572
|
, 'expected #{this} to ' + descriptor + 'include ' + _.inspect(val)
|
|
512
573
|
, 'expected #{this} to not ' + descriptor + 'include ' + _.inspect(val));
|
|
513
574
|
}
|
|
@@ -1024,7 +1085,7 @@ module.exports = function (chai, _) {
|
|
|
1024
1085
|
/**
|
|
1025
1086
|
* ### .above(n[, msg])
|
|
1026
1087
|
*
|
|
1027
|
-
* Asserts that the target is a number greater than the given number `n
|
|
1088
|
+
* Asserts that the target is a number or a date greater than the given number or date `n` respectively.
|
|
1028
1089
|
* However, it's often best to assert that the target is equal to its expected
|
|
1029
1090
|
* value.
|
|
1030
1091
|
*
|
|
@@ -1069,21 +1130,29 @@ module.exports = function (chai, _) {
|
|
|
1069
1130
|
var obj = flag(this, 'object')
|
|
1070
1131
|
, doLength = flag(this, 'doLength')
|
|
1071
1132
|
, flagMsg = flag(this, 'message')
|
|
1072
|
-
,
|
|
1133
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1134
|
+
, ssfi = flag(this, 'ssfi')
|
|
1135
|
+
, objType = _.type(obj).toLowerCase()
|
|
1136
|
+
, nType = _.type(n).toLowerCase()
|
|
1137
|
+
, shouldThrow = true;
|
|
1073
1138
|
|
|
1074
1139
|
if (doLength) {
|
|
1075
1140
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1144
|
+
errorMessage = msgPrefix + 'the argument to above must be a date';
|
|
1145
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1146
|
+
errorMessage = msgPrefix + 'the argument to above must be a number';
|
|
1147
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1148
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1149
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1076
1150
|
} else {
|
|
1077
|
-
|
|
1151
|
+
shouldThrow = false;
|
|
1078
1152
|
}
|
|
1079
1153
|
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1082
|
-
throw new AssertionError(
|
|
1083
|
-
flagMsg + 'the argument to above must be a number',
|
|
1084
|
-
undefined,
|
|
1085
|
-
ssfi
|
|
1086
|
-
);
|
|
1154
|
+
if (shouldThrow) {
|
|
1155
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1087
1156
|
}
|
|
1088
1157
|
|
|
1089
1158
|
if (doLength) {
|
|
@@ -1098,8 +1167,9 @@ module.exports = function (chai, _) {
|
|
|
1098
1167
|
} else {
|
|
1099
1168
|
this.assert(
|
|
1100
1169
|
obj > n
|
|
1101
|
-
, 'expected #{this} to be above '
|
|
1102
|
-
, 'expected #{this} to be at most '
|
|
1170
|
+
, 'expected #{this} to be above #{exp}'
|
|
1171
|
+
, 'expected #{this} to be at most #{exp}'
|
|
1172
|
+
, n
|
|
1103
1173
|
);
|
|
1104
1174
|
}
|
|
1105
1175
|
}
|
|
@@ -1111,8 +1181,8 @@ module.exports = function (chai, _) {
|
|
|
1111
1181
|
/**
|
|
1112
1182
|
* ### .least(n[, msg])
|
|
1113
1183
|
*
|
|
1114
|
-
* Asserts that the target is a number greater than or equal to the given
|
|
1115
|
-
* number `n
|
|
1184
|
+
* Asserts that the target is a number or a date greater than or equal to the given
|
|
1185
|
+
* number or date `n` respectively. However, it's often best to assert that the target is equal to
|
|
1116
1186
|
* its expected value.
|
|
1117
1187
|
*
|
|
1118
1188
|
* expect(2).to.equal(2); // Recommended
|
|
@@ -1156,21 +1226,29 @@ module.exports = function (chai, _) {
|
|
|
1156
1226
|
var obj = flag(this, 'object')
|
|
1157
1227
|
, doLength = flag(this, 'doLength')
|
|
1158
1228
|
, flagMsg = flag(this, 'message')
|
|
1159
|
-
,
|
|
1229
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1230
|
+
, ssfi = flag(this, 'ssfi')
|
|
1231
|
+
, objType = _.type(obj).toLowerCase()
|
|
1232
|
+
, nType = _.type(n).toLowerCase()
|
|
1233
|
+
, shouldThrow = true;
|
|
1160
1234
|
|
|
1161
1235
|
if (doLength) {
|
|
1162
1236
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1240
|
+
errorMessage = msgPrefix + 'the argument to least must be a date';
|
|
1241
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1242
|
+
errorMessage = msgPrefix + 'the argument to least must be a number';
|
|
1243
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1244
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1245
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1163
1246
|
} else {
|
|
1164
|
-
|
|
1247
|
+
shouldThrow = false;
|
|
1165
1248
|
}
|
|
1166
1249
|
|
|
1167
|
-
if (
|
|
1168
|
-
|
|
1169
|
-
throw new AssertionError(
|
|
1170
|
-
flagMsg + 'the argument to least must be a number',
|
|
1171
|
-
undefined,
|
|
1172
|
-
ssfi
|
|
1173
|
-
);
|
|
1250
|
+
if (shouldThrow) {
|
|
1251
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1174
1252
|
}
|
|
1175
1253
|
|
|
1176
1254
|
if (doLength) {
|
|
@@ -1185,8 +1263,9 @@ module.exports = function (chai, _) {
|
|
|
1185
1263
|
} else {
|
|
1186
1264
|
this.assert(
|
|
1187
1265
|
obj >= n
|
|
1188
|
-
, 'expected #{this} to be at least '
|
|
1189
|
-
, 'expected #{this} to be below '
|
|
1266
|
+
, 'expected #{this} to be at least #{exp}'
|
|
1267
|
+
, 'expected #{this} to be below #{exp}'
|
|
1268
|
+
, n
|
|
1190
1269
|
);
|
|
1191
1270
|
}
|
|
1192
1271
|
}
|
|
@@ -1197,7 +1276,7 @@ module.exports = function (chai, _) {
|
|
|
1197
1276
|
/**
|
|
1198
1277
|
* ### .below(n[, msg])
|
|
1199
1278
|
*
|
|
1200
|
-
* Asserts that the target is a number less than the given number `n
|
|
1279
|
+
* Asserts that the target is a number or a date less than the given number or date `n` respectively.
|
|
1201
1280
|
* However, it's often best to assert that the target is equal to its expected
|
|
1202
1281
|
* value.
|
|
1203
1282
|
*
|
|
@@ -1242,21 +1321,29 @@ module.exports = function (chai, _) {
|
|
|
1242
1321
|
var obj = flag(this, 'object')
|
|
1243
1322
|
, doLength = flag(this, 'doLength')
|
|
1244
1323
|
, flagMsg = flag(this, 'message')
|
|
1245
|
-
,
|
|
1324
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1325
|
+
, ssfi = flag(this, 'ssfi')
|
|
1326
|
+
, objType = _.type(obj).toLowerCase()
|
|
1327
|
+
, nType = _.type(n).toLowerCase()
|
|
1328
|
+
, shouldThrow = true;
|
|
1246
1329
|
|
|
1247
1330
|
if (doLength) {
|
|
1248
1331
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1335
|
+
errorMessage = msgPrefix + 'the argument to below must be a date';
|
|
1336
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1337
|
+
errorMessage = msgPrefix + 'the argument to below must be a number';
|
|
1338
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1339
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1340
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1249
1341
|
} else {
|
|
1250
|
-
|
|
1342
|
+
shouldThrow = false;
|
|
1251
1343
|
}
|
|
1252
1344
|
|
|
1253
|
-
if (
|
|
1254
|
-
|
|
1255
|
-
throw new AssertionError(
|
|
1256
|
-
flagMsg + 'the argument to below must be a number',
|
|
1257
|
-
undefined,
|
|
1258
|
-
ssfi
|
|
1259
|
-
);
|
|
1345
|
+
if (shouldThrow) {
|
|
1346
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1260
1347
|
}
|
|
1261
1348
|
|
|
1262
1349
|
if (doLength) {
|
|
@@ -1271,8 +1358,9 @@ module.exports = function (chai, _) {
|
|
|
1271
1358
|
} else {
|
|
1272
1359
|
this.assert(
|
|
1273
1360
|
obj < n
|
|
1274
|
-
, 'expected #{this} to be below '
|
|
1275
|
-
, 'expected #{this} to be at least '
|
|
1361
|
+
, 'expected #{this} to be below #{exp}'
|
|
1362
|
+
, 'expected #{this} to be at least #{exp}'
|
|
1363
|
+
, n
|
|
1276
1364
|
);
|
|
1277
1365
|
}
|
|
1278
1366
|
}
|
|
@@ -1284,8 +1372,8 @@ module.exports = function (chai, _) {
|
|
|
1284
1372
|
/**
|
|
1285
1373
|
* ### .most(n[, msg])
|
|
1286
1374
|
*
|
|
1287
|
-
* Asserts that the target is a number less than or equal to the given number
|
|
1288
|
-
* `n
|
|
1375
|
+
* Asserts that the target is a number or a date less than or equal to the given number
|
|
1376
|
+
* or date `n` respectively. However, it's often best to assert that the target is equal to its
|
|
1289
1377
|
* expected value.
|
|
1290
1378
|
*
|
|
1291
1379
|
* expect(1).to.equal(1); // Recommended
|
|
@@ -1328,21 +1416,29 @@ module.exports = function (chai, _) {
|
|
|
1328
1416
|
var obj = flag(this, 'object')
|
|
1329
1417
|
, doLength = flag(this, 'doLength')
|
|
1330
1418
|
, flagMsg = flag(this, 'message')
|
|
1331
|
-
,
|
|
1419
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1420
|
+
, ssfi = flag(this, 'ssfi')
|
|
1421
|
+
, objType = _.type(obj).toLowerCase()
|
|
1422
|
+
, nType = _.type(n).toLowerCase()
|
|
1423
|
+
, shouldThrow = true;
|
|
1332
1424
|
|
|
1333
1425
|
if (doLength) {
|
|
1334
1426
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1430
|
+
errorMessage = msgPrefix + 'the argument to most must be a date';
|
|
1431
|
+
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
1432
|
+
errorMessage = msgPrefix + 'the argument to most must be a number';
|
|
1433
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1434
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1435
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1335
1436
|
} else {
|
|
1336
|
-
|
|
1437
|
+
shouldThrow = false;
|
|
1337
1438
|
}
|
|
1338
1439
|
|
|
1339
|
-
if (
|
|
1340
|
-
|
|
1341
|
-
throw new AssertionError(
|
|
1342
|
-
flagMsg + 'the argument to most must be a number',
|
|
1343
|
-
undefined,
|
|
1344
|
-
ssfi
|
|
1345
|
-
);
|
|
1440
|
+
if (shouldThrow) {
|
|
1441
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1346
1442
|
}
|
|
1347
1443
|
|
|
1348
1444
|
if (doLength) {
|
|
@@ -1357,8 +1453,9 @@ module.exports = function (chai, _) {
|
|
|
1357
1453
|
} else {
|
|
1358
1454
|
this.assert(
|
|
1359
1455
|
obj <= n
|
|
1360
|
-
, 'expected #{this} to be at most '
|
|
1361
|
-
, 'expected #{this} to be above '
|
|
1456
|
+
, 'expected #{this} to be at most #{exp}'
|
|
1457
|
+
, 'expected #{this} to be above #{exp}'
|
|
1458
|
+
, n
|
|
1362
1459
|
);
|
|
1363
1460
|
}
|
|
1364
1461
|
}
|
|
@@ -1369,8 +1466,8 @@ module.exports = function (chai, _) {
|
|
|
1369
1466
|
/**
|
|
1370
1467
|
* ### .within(start, finish[, msg])
|
|
1371
1468
|
*
|
|
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
|
|
1469
|
+
* Asserts that the target is a number or a date greater than or equal to the given
|
|
1470
|
+
* number or date `start`, and less than or equal to the given number or date `finish` respectively.
|
|
1374
1471
|
* However, it's often best to assert that the target is equal to its expected
|
|
1375
1472
|
* value.
|
|
1376
1473
|
*
|
|
@@ -1412,24 +1509,35 @@ module.exports = function (chai, _) {
|
|
|
1412
1509
|
Assertion.addMethod('within', function (start, finish, msg) {
|
|
1413
1510
|
if (msg) flag(this, 'message', msg);
|
|
1414
1511
|
var obj = flag(this, 'object')
|
|
1415
|
-
, range = start + '..' + finish
|
|
1416
1512
|
, doLength = flag(this, 'doLength')
|
|
1417
1513
|
, flagMsg = flag(this, 'message')
|
|
1418
|
-
,
|
|
1514
|
+
, msgPrefix = ((flagMsg) ? flagMsg + ': ' : '')
|
|
1515
|
+
, ssfi = flag(this, 'ssfi')
|
|
1516
|
+
, objType = _.type(obj).toLowerCase()
|
|
1517
|
+
, startType = _.type(start).toLowerCase()
|
|
1518
|
+
, finishType = _.type(finish).toLowerCase()
|
|
1519
|
+
, shouldThrow = true
|
|
1520
|
+
, range = (startType === 'date' && finishType === 'date')
|
|
1521
|
+
? start.toUTCString() + '..' + finish.toUTCString()
|
|
1522
|
+
: start + '..' + finish;
|
|
1419
1523
|
|
|
1420
1524
|
if (doLength) {
|
|
1421
1525
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
if (!doLength && (objType === 'date' && (startType !== 'date' || finishType !== 'date'))) {
|
|
1529
|
+
errorMessage = msgPrefix + 'the arguments to within must be dates';
|
|
1530
|
+
} else if ((startType !== 'number' || finishType !== 'number') && (doLength || objType === 'number')) {
|
|
1531
|
+
errorMessage = msgPrefix + 'the arguments to within must be numbers';
|
|
1532
|
+
} else if (!doLength && (objType !== 'date' && objType !== 'number')) {
|
|
1533
|
+
var printObj = (objType === 'string') ? "'" + obj + "'" : obj;
|
|
1534
|
+
errorMessage = msgPrefix + 'expected ' + printObj + ' to be a number or a date';
|
|
1422
1535
|
} else {
|
|
1423
|
-
|
|
1536
|
+
shouldThrow = false;
|
|
1424
1537
|
}
|
|
1425
1538
|
|
|
1426
|
-
if (
|
|
1427
|
-
|
|
1428
|
-
throw new AssertionError(
|
|
1429
|
-
flagMsg + 'the arguments to within must be numbers',
|
|
1430
|
-
undefined,
|
|
1431
|
-
ssfi
|
|
1432
|
-
);
|
|
1539
|
+
if (shouldThrow) {
|
|
1540
|
+
throw new AssertionError(errorMessage, undefined, ssfi);
|
|
1433
1541
|
}
|
|
1434
1542
|
|
|
1435
1543
|
if (doLength) {
|
|
@@ -1644,6 +1752,7 @@ module.exports = function (chai, _) {
|
|
|
1644
1752
|
var isNested = flag(this, 'nested')
|
|
1645
1753
|
, isOwn = flag(this, 'own')
|
|
1646
1754
|
, flagMsg = flag(this, 'message')
|
|
1755
|
+
, obj = flag(this, 'object')
|
|
1647
1756
|
, ssfi = flag(this, 'ssfi');
|
|
1648
1757
|
|
|
1649
1758
|
if (isNested && isOwn) {
|
|
@@ -1655,9 +1764,17 @@ module.exports = function (chai, _) {
|
|
|
1655
1764
|
);
|
|
1656
1765
|
}
|
|
1657
1766
|
|
|
1767
|
+
if (obj === null || obj === undefined) {
|
|
1768
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1769
|
+
throw new AssertionError(
|
|
1770
|
+
flagMsg + 'Target cannot be null or undefined.',
|
|
1771
|
+
undefined,
|
|
1772
|
+
ssfi
|
|
1773
|
+
);
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1658
1776
|
var isDeep = flag(this, 'deep')
|
|
1659
1777
|
, negate = flag(this, 'negate')
|
|
1660
|
-
, obj = flag(this, 'object')
|
|
1661
1778
|
, pathInfo = isNested ? _.getPathInfo(obj, name) : null
|
|
1662
1779
|
, value = isNested ? pathInfo.value : obj[name];
|
|
1663
1780
|
|
|
@@ -1012,6 +1012,197 @@ module.exports = function (chai, util) {
|
|
|
1012
1012
|
new Assertion(exp, msg, assert.notDeepInclude, true).not.deep.include(inc);
|
|
1013
1013
|
};
|
|
1014
1014
|
|
|
1015
|
+
/**
|
|
1016
|
+
* ### .nestedInclude(haystack, needle, [message])
|
|
1017
|
+
*
|
|
1018
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1019
|
+
* Can be used to assert the inclusion of a subset of properties in an
|
|
1020
|
+
* object.
|
|
1021
|
+
* Enables the use of dot- and bracket-notation for referencing nested
|
|
1022
|
+
* properties.
|
|
1023
|
+
* '[]' and '.' in property names can be escaped using double backslashes.
|
|
1024
|
+
*
|
|
1025
|
+
* assert.nestedInclude({'.a': {'b': 'x'}}, {'\\.a.[b]': 'x'});
|
|
1026
|
+
* assert.nestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'x'});
|
|
1027
|
+
*
|
|
1028
|
+
* @name nestedInclude
|
|
1029
|
+
* @param {Object} haystack
|
|
1030
|
+
* @param {Object} needle
|
|
1031
|
+
* @param {String} message
|
|
1032
|
+
* @namespace Assert
|
|
1033
|
+
* @api public
|
|
1034
|
+
*/
|
|
1035
|
+
|
|
1036
|
+
assert.nestedInclude = function (exp, inc, msg) {
|
|
1037
|
+
new Assertion(exp, msg, assert.nestedInclude, true).nested.include(inc);
|
|
1038
|
+
};
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* ### .notNestedInclude(haystack, needle, [message])
|
|
1042
|
+
*
|
|
1043
|
+
* Asserts that 'haystack' does not include 'needle'.
|
|
1044
|
+
* Can be used to assert the absence of a subset of properties in an
|
|
1045
|
+
* object.
|
|
1046
|
+
* Enables the use of dot- and bracket-notation for referencing nested
|
|
1047
|
+
* properties.
|
|
1048
|
+
* '[]' and '.' in property names can be escaped using double backslashes.
|
|
1049
|
+
*
|
|
1050
|
+
* assert.notNestedInclude({'.a': {'b': 'x'}}, {'\\.a.b': 'y'});
|
|
1051
|
+
* assert.notNestedInclude({'a': {'[b]': 'x'}}, {'a.\\[b\\]': 'y'});
|
|
1052
|
+
*
|
|
1053
|
+
* @name notNestedInclude
|
|
1054
|
+
* @param {Object} haystack
|
|
1055
|
+
* @param {Object} needle
|
|
1056
|
+
* @param {String} message
|
|
1057
|
+
* @namespace Assert
|
|
1058
|
+
* @api public
|
|
1059
|
+
*/
|
|
1060
|
+
|
|
1061
|
+
assert.notNestedInclude = function (exp, inc, msg) {
|
|
1062
|
+
new Assertion(exp, msg, assert.notNestedInclude, true)
|
|
1063
|
+
.not.nested.include(inc);
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* ### .deepNestedInclude(haystack, needle, [message])
|
|
1068
|
+
*
|
|
1069
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1070
|
+
* Can be used to assert the inclusion of a subset of properties in an
|
|
1071
|
+
* object while checking for deep equality.
|
|
1072
|
+
* Enables the use of dot- and bracket-notation for referencing nested
|
|
1073
|
+
* properties.
|
|
1074
|
+
* '[]' and '.' in property names can be escaped using double backslashes.
|
|
1075
|
+
*
|
|
1076
|
+
* assert.deepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {x: 1}});
|
|
1077
|
+
* assert.deepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {x: 1}});
|
|
1078
|
+
*
|
|
1079
|
+
* @name deepNestedInclude
|
|
1080
|
+
* @param {Object} haystack
|
|
1081
|
+
* @param {Object} needle
|
|
1082
|
+
* @param {String} message
|
|
1083
|
+
* @namespace Assert
|
|
1084
|
+
* @api public
|
|
1085
|
+
*/
|
|
1086
|
+
|
|
1087
|
+
assert.deepNestedInclude = function(exp, inc, msg) {
|
|
1088
|
+
new Assertion(exp, msg, assert.deepNestedInclude, true)
|
|
1089
|
+
.deep.nested.include(inc);
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* ### .notDeepNestedInclude(haystack, needle, [message])
|
|
1094
|
+
*
|
|
1095
|
+
* Asserts that 'haystack' does not include 'needle'.
|
|
1096
|
+
* Can be used to assert the absence of a subset of properties in an
|
|
1097
|
+
* object while checking for deep equality.
|
|
1098
|
+
* Enables the use of dot- and bracket-notation for referencing nested
|
|
1099
|
+
* properties.
|
|
1100
|
+
* '[]' and '.' in property names can be escaped using double backslashes.
|
|
1101
|
+
*
|
|
1102
|
+
* assert.notDeepNestedInclude({a: {b: [{x: 1}]}}, {'a.b[0]': {y: 1}})
|
|
1103
|
+
* assert.notDeepNestedInclude({'.a': {'[b]': {x: 1}}}, {'\\.a.\\[b\\]': {y: 2}});
|
|
1104
|
+
*
|
|
1105
|
+
* @name notDeepNestedInclude
|
|
1106
|
+
* @param {Object} haystack
|
|
1107
|
+
* @param {Object} needle
|
|
1108
|
+
* @param {String} message
|
|
1109
|
+
* @namespace Assert
|
|
1110
|
+
* @api public
|
|
1111
|
+
*/
|
|
1112
|
+
|
|
1113
|
+
assert.notDeepNestedInclude = function(exp, inc, msg) {
|
|
1114
|
+
new Assertion(exp, msg, assert.notDeepNestedInclude, true)
|
|
1115
|
+
.not.deep.nested.include(inc);
|
|
1116
|
+
};
|
|
1117
|
+
|
|
1118
|
+
/**
|
|
1119
|
+
* ### .ownInclude(haystack, needle, [message])
|
|
1120
|
+
*
|
|
1121
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1122
|
+
* Can be used to assert the inclusion of a subset of properties in an
|
|
1123
|
+
* object while ignoring inherited properties.
|
|
1124
|
+
*
|
|
1125
|
+
* assert.ownInclude({ a: 1 }, { a: 1 });
|
|
1126
|
+
*
|
|
1127
|
+
* @name ownInclude
|
|
1128
|
+
* @param {Object} haystack
|
|
1129
|
+
* @param {Object} needle
|
|
1130
|
+
* @param {String} message
|
|
1131
|
+
* @namespace Assert
|
|
1132
|
+
* @api public
|
|
1133
|
+
*/
|
|
1134
|
+
|
|
1135
|
+
assert.ownInclude = function(exp, inc, msg) {
|
|
1136
|
+
new Assertion(exp, msg, assert.ownInclude, true).own.include(inc);
|
|
1137
|
+
};
|
|
1138
|
+
|
|
1139
|
+
/**
|
|
1140
|
+
* ### .notOwnInclude(haystack, needle, [message])
|
|
1141
|
+
*
|
|
1142
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1143
|
+
* Can be used to assert the absence of a subset of properties in an
|
|
1144
|
+
* object while ignoring inherited properties.
|
|
1145
|
+
*
|
|
1146
|
+
* Object.prototype.b = 2;
|
|
1147
|
+
*
|
|
1148
|
+
* assert.notOwnInclude({ a: 1 }, { b: 2 });
|
|
1149
|
+
*
|
|
1150
|
+
* @name notOwnInclude
|
|
1151
|
+
* @param {Object} haystack
|
|
1152
|
+
* @param {Object} needle
|
|
1153
|
+
* @param {String} message
|
|
1154
|
+
* @namespace Assert
|
|
1155
|
+
* @api public
|
|
1156
|
+
*/
|
|
1157
|
+
|
|
1158
|
+
assert.notOwnInclude = function(exp, inc, msg) {
|
|
1159
|
+
new Assertion(exp, msg, assert.notOwnInclude, true).not.own.include(inc);
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
/**
|
|
1163
|
+
* ### .deepOwnInclude(haystack, needle, [message])
|
|
1164
|
+
*
|
|
1165
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1166
|
+
* Can be used to assert the inclusion of a subset of properties in an
|
|
1167
|
+
* object while ignoring inherited properties and checking for deep equality.
|
|
1168
|
+
*
|
|
1169
|
+
* assert.deepOwnInclude({a: {b: 2}}, {a: {b: 2}});
|
|
1170
|
+
*
|
|
1171
|
+
* @name deepOwnInclude
|
|
1172
|
+
* @param {Object} haystack
|
|
1173
|
+
* @param {Object} needle
|
|
1174
|
+
* @param {String} message
|
|
1175
|
+
* @namespace Assert
|
|
1176
|
+
* @api public
|
|
1177
|
+
*/
|
|
1178
|
+
|
|
1179
|
+
assert.deepOwnInclude = function(exp, inc, msg) {
|
|
1180
|
+
new Assertion(exp, msg, assert.deepOwnInclude, true)
|
|
1181
|
+
.deep.own.include(inc);
|
|
1182
|
+
};
|
|
1183
|
+
|
|
1184
|
+
/**
|
|
1185
|
+
* ### .notDeepOwnInclude(haystack, needle, [message])
|
|
1186
|
+
*
|
|
1187
|
+
* Asserts that 'haystack' includes 'needle'.
|
|
1188
|
+
* Can be used to assert the absence of a subset of properties in an
|
|
1189
|
+
* object while ignoring inherited properties and checking for deep equality.
|
|
1190
|
+
*
|
|
1191
|
+
* assert.notDeepOwnInclude({a: {b: 2}}, {a: {c: 3}});
|
|
1192
|
+
*
|
|
1193
|
+
* @name notDeepOwnInclude
|
|
1194
|
+
* @param {Object} haystack
|
|
1195
|
+
* @param {Object} needle
|
|
1196
|
+
* @param {String} message
|
|
1197
|
+
* @namespace Assert
|
|
1198
|
+
* @api public
|
|
1199
|
+
*/
|
|
1200
|
+
|
|
1201
|
+
assert.notDeepOwnInclude = function(exp, inc, msg) {
|
|
1202
|
+
new Assertion(exp, msg, assert.notDeepOwnInclude, true)
|
|
1203
|
+
.not.deep.own.include(inc);
|
|
1204
|
+
};
|
|
1205
|
+
|
|
1015
1206
|
/**
|
|
1016
1207
|
* ### .match(value, regexp, [message])
|
|
1017
1208
|
*
|
|
@@ -25,7 +25,16 @@ var canSetPrototype = typeof Object.setPrototypeOf === 'function';
|
|
|
25
25
|
// However, some of functions' own props are not configurable and should be skipped.
|
|
26
26
|
var testFn = function() {};
|
|
27
27
|
var excludeNames = Object.getOwnPropertyNames(testFn).filter(function(name) {
|
|
28
|
-
|
|
28
|
+
var propDesc = Object.getOwnPropertyDescriptor(testFn, name);
|
|
29
|
+
|
|
30
|
+
// Note: PhantomJS 1.x includes `callee` as one of `testFn`'s own properties,
|
|
31
|
+
// but then returns `undefined` as the property descriptor for `callee`. As a
|
|
32
|
+
// workaround, we perform an otherwise unnecessary type-check for `propDesc`,
|
|
33
|
+
// and then filter it out if it's not an object as it should be.
|
|
34
|
+
if (typeof propDesc !== 'object')
|
|
35
|
+
return true;
|
|
36
|
+
|
|
37
|
+
return !propDesc.configurable;
|
|
29
38
|
});
|
|
30
39
|
|
|
31
40
|
// Cache `Function` properties
|