chai 4.1.2 → 4.2.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/CONTRIBUTING.md +2 -2
- package/README.md +4 -4
- package/chai.js +421 -274
- package/lib/chai/config.js +1 -1
- package/lib/chai/core/assertions.js +168 -93
- package/lib/chai/interface/assert.js +69 -54
- package/lib/chai/interface/expect.js +13 -0
- package/lib/chai/interface/should.js +14 -0
- package/lib/chai/utils/addLengthGuard.js +0 -2
- package/lib/chai/utils/compareByInspect.js +2 -2
- package/lib/chai/utils/getMessage.js +1 -2
- package/lib/chai/utils/getOwnEnumerableProperties.js +1 -1
- package/lib/chai/utils/inspect.js +1 -8
- package/lib/chai/utils/isProxyEnabled.js +1 -1
- package/lib/chai/utils/objDisplay.js +1 -1
- package/lib/chai/utils/overwriteChainableMethod.js +1 -1
- package/lib/chai/utils/overwriteMethod.js +1 -1
- package/lib/chai/utils/overwriteProperty.js +1 -1
- package/lib/chai/utils/proxify.js +54 -32
- package/lib/chai/utils/test.js +1 -1
- package/lib/chai/utils/transferFlags.js +1 -1
- package/lib/chai.js +1 -1
- package/package.json +11 -10
- package/sauce.browsers.js +0 -9
- package/.npmignore +0 -14
package/lib/chai/config.js
CHANGED
|
@@ -33,16 +33,17 @@ module.exports = function (chai, _) {
|
|
|
33
33
|
* - same
|
|
34
34
|
* - but
|
|
35
35
|
* - does
|
|
36
|
+
* - still
|
|
36
37
|
*
|
|
37
38
|
* @name language chains
|
|
38
39
|
* @namespace BDD
|
|
39
40
|
* @api public
|
|
40
41
|
*/
|
|
41
42
|
|
|
42
|
-
[ 'to', 'be', 'been'
|
|
43
|
-
, '
|
|
44
|
-
, '
|
|
45
|
-
, '
|
|
43
|
+
[ 'to', 'be', 'been', 'is'
|
|
44
|
+
, 'and', 'has', 'have', 'with'
|
|
45
|
+
, 'that', 'which', 'at', 'of'
|
|
46
|
+
, 'same', 'but', 'does', 'still' ].forEach(function (chain) {
|
|
46
47
|
Assertion.addProperty(chain);
|
|
47
48
|
});
|
|
48
49
|
|
|
@@ -149,7 +150,8 @@ module.exports = function (chai, _) {
|
|
|
149
150
|
* Object.prototype.b = 2;
|
|
150
151
|
*
|
|
151
152
|
* expect({a: 1}).to.have.own.property('a');
|
|
152
|
-
* expect({a: 1}).to.have.property('b')
|
|
153
|
+
* expect({a: 1}).to.have.property('b');
|
|
154
|
+
* expect({a: 1}).to.not.have.own.property('b');
|
|
153
155
|
*
|
|
154
156
|
* expect({a: 1}).to.own.include({a: 1});
|
|
155
157
|
* expect({a: 1}).to.include({b: 2}).but.not.own.include({b: 2});
|
|
@@ -210,7 +212,6 @@ module.exports = function (chai, _) {
|
|
|
210
212
|
flag(this, 'all', false);
|
|
211
213
|
});
|
|
212
214
|
|
|
213
|
-
|
|
214
215
|
/**
|
|
215
216
|
* ### .all
|
|
216
217
|
*
|
|
@@ -282,7 +283,7 @@ module.exports = function (chai, _) {
|
|
|
282
283
|
* expect(1, 'nooo why fail??').to.be.a('string');
|
|
283
284
|
*
|
|
284
285
|
* `.a` can also be used as a language chain to improve the readability of
|
|
285
|
-
* your assertions.
|
|
286
|
+
* your assertions.
|
|
286
287
|
*
|
|
287
288
|
* expect({b: 2}).to.have.a.property('b');
|
|
288
289
|
*
|
|
@@ -396,7 +397,7 @@ module.exports = function (chai, _) {
|
|
|
396
397
|
*
|
|
397
398
|
* expect('foobar').to.not.include('taco');
|
|
398
399
|
* expect([1, 2, 3]).to.not.include(4);
|
|
399
|
-
*
|
|
400
|
+
*
|
|
400
401
|
* However, it's dangerous to negate `.include` when the target is an object.
|
|
401
402
|
* The problem is that it creates uncertain expectations by asserting that the
|
|
402
403
|
* target object doesn't have all of `val`'s key/value pairs but may or may
|
|
@@ -469,7 +470,7 @@ module.exports = function (chai, _) {
|
|
|
469
470
|
|
|
470
471
|
function include (val, msg) {
|
|
471
472
|
if (msg) flag(this, 'message', msg);
|
|
472
|
-
|
|
473
|
+
|
|
473
474
|
var obj = flag(this, 'object')
|
|
474
475
|
, objType = _.type(obj).toLowerCase()
|
|
475
476
|
, flagMsg = flag(this, 'message')
|
|
@@ -542,17 +543,17 @@ module.exports = function (chai, _) {
|
|
|
542
543
|
var props = Object.keys(val)
|
|
543
544
|
, firstErr = null
|
|
544
545
|
, numErrs = 0;
|
|
545
|
-
|
|
546
|
+
|
|
546
547
|
props.forEach(function (prop) {
|
|
547
548
|
var propAssertion = new Assertion(obj);
|
|
548
549
|
_.transferFlags(this, propAssertion, true);
|
|
549
550
|
flag(propAssertion, 'lockSsfi', true);
|
|
550
|
-
|
|
551
|
+
|
|
551
552
|
if (!negate || props.length === 1) {
|
|
552
553
|
propAssertion.property(prop, val[prop]);
|
|
553
554
|
return;
|
|
554
555
|
}
|
|
555
|
-
|
|
556
|
+
|
|
556
557
|
try {
|
|
557
558
|
propAssertion.property(prop, val[prop]);
|
|
558
559
|
} catch (err) {
|
|
@@ -563,7 +564,7 @@ module.exports = function (chai, _) {
|
|
|
563
564
|
numErrs++;
|
|
564
565
|
}
|
|
565
566
|
}, this);
|
|
566
|
-
|
|
567
|
+
|
|
567
568
|
// When validating .not.include with multiple properties, we only want
|
|
568
569
|
// to throw an assertion error if all of the properties are included,
|
|
569
570
|
// in which case we throw the first property assertion error that we
|
|
@@ -589,9 +590,9 @@ module.exports = function (chai, _) {
|
|
|
589
590
|
/**
|
|
590
591
|
* ### .ok
|
|
591
592
|
*
|
|
592
|
-
* Asserts that the target is
|
|
593
|
-
* often best to assert that the target is strictly (`===`) or
|
|
594
|
-
* its expected value.
|
|
593
|
+
* Asserts that the target is a truthy value (considered `true` in boolean context).
|
|
594
|
+
* However, it's often best to assert that the target is strictly (`===`) or
|
|
595
|
+
* deeply equal to its expected value.
|
|
595
596
|
*
|
|
596
597
|
* expect(1).to.equal(1); // Recommended
|
|
597
598
|
* expect(1).to.be.ok; // Not recommended
|
|
@@ -975,7 +976,7 @@ module.exports = function (chai, _) {
|
|
|
975
976
|
*
|
|
976
977
|
* expect(1).to.equal(1);
|
|
977
978
|
* expect('foo').to.equal('foo');
|
|
978
|
-
*
|
|
979
|
+
*
|
|
979
980
|
* Add `.deep` earlier in the chain to use deep equality instead. See the
|
|
980
981
|
* `deep-eql` project page for info on the deep equality algorithm:
|
|
981
982
|
* https://github.com/chaijs/deep-eql.
|
|
@@ -1017,7 +1018,10 @@ module.exports = function (chai, _) {
|
|
|
1017
1018
|
if (msg) flag(this, 'message', msg);
|
|
1018
1019
|
var obj = flag(this, 'object');
|
|
1019
1020
|
if (flag(this, 'deep')) {
|
|
1020
|
-
|
|
1021
|
+
var prevLockSsfi = flag(this, 'lockSsfi');
|
|
1022
|
+
flag(this, 'lockSsfi', true);
|
|
1023
|
+
this.eql(val);
|
|
1024
|
+
flag(this, 'lockSsfi', prevLockSsfi);
|
|
1021
1025
|
} else {
|
|
1022
1026
|
this.assert(
|
|
1023
1027
|
val === obj
|
|
@@ -1100,8 +1104,8 @@ module.exports = function (chai, _) {
|
|
|
1100
1104
|
* expect(2).to.equal(2); // Recommended
|
|
1101
1105
|
* expect(2).to.be.above(1); // Not recommended
|
|
1102
1106
|
*
|
|
1103
|
-
* Add `.lengthOf` earlier in the chain to assert that the
|
|
1104
|
-
*
|
|
1107
|
+
* Add `.lengthOf` earlier in the chain to assert that the target's `length`
|
|
1108
|
+
* or `size` is greater than the given number `n`.
|
|
1105
1109
|
*
|
|
1106
1110
|
* expect('foo').to.have.lengthOf(3); // Recommended
|
|
1107
1111
|
* expect('foo').to.have.lengthOf.above(2); // Not recommended
|
|
@@ -1142,12 +1146,13 @@ module.exports = function (chai, _) {
|
|
|
1142
1146
|
, ssfi = flag(this, 'ssfi')
|
|
1143
1147
|
, objType = _.type(obj).toLowerCase()
|
|
1144
1148
|
, nType = _.type(n).toLowerCase()
|
|
1149
|
+
, errorMessage
|
|
1145
1150
|
, shouldThrow = true;
|
|
1146
1151
|
|
|
1147
|
-
if (doLength) {
|
|
1152
|
+
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1148
1153
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1149
1154
|
}
|
|
1150
|
-
|
|
1155
|
+
|
|
1151
1156
|
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1152
1157
|
errorMessage = msgPrefix + 'the argument to above must be a date';
|
|
1153
1158
|
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
@@ -1164,13 +1169,20 @@ module.exports = function (chai, _) {
|
|
|
1164
1169
|
}
|
|
1165
1170
|
|
|
1166
1171
|
if (doLength) {
|
|
1167
|
-
var
|
|
1172
|
+
var descriptor = 'length'
|
|
1173
|
+
, itemsCount;
|
|
1174
|
+
if (objType === 'map' || objType === 'set') {
|
|
1175
|
+
descriptor = 'size';
|
|
1176
|
+
itemsCount = obj.size;
|
|
1177
|
+
} else {
|
|
1178
|
+
itemsCount = obj.length;
|
|
1179
|
+
}
|
|
1168
1180
|
this.assert(
|
|
1169
|
-
|
|
1170
|
-
, 'expected #{this} to have a
|
|
1171
|
-
, 'expected #{this} to not have a
|
|
1181
|
+
itemsCount > n
|
|
1182
|
+
, 'expected #{this} to have a ' + descriptor + ' above #{exp} but got #{act}'
|
|
1183
|
+
, 'expected #{this} to not have a ' + descriptor + ' above #{exp}'
|
|
1172
1184
|
, n
|
|
1173
|
-
,
|
|
1185
|
+
, itemsCount
|
|
1174
1186
|
);
|
|
1175
1187
|
} else {
|
|
1176
1188
|
this.assert(
|
|
@@ -1197,9 +1209,8 @@ module.exports = function (chai, _) {
|
|
|
1197
1209
|
* expect(2).to.be.at.least(1); // Not recommended
|
|
1198
1210
|
* expect(2).to.be.at.least(2); // Not recommended
|
|
1199
1211
|
*
|
|
1200
|
-
* Add `.lengthOf` earlier in the chain to assert that the
|
|
1201
|
-
*
|
|
1202
|
-
* `n`.
|
|
1212
|
+
* Add `.lengthOf` earlier in the chain to assert that the target's `length`
|
|
1213
|
+
* or `size` is greater than or equal to the given number `n`.
|
|
1203
1214
|
*
|
|
1204
1215
|
* expect('foo').to.have.lengthOf(3); // Recommended
|
|
1205
1216
|
* expect('foo').to.have.lengthOf.at.least(2); // Not recommended
|
|
@@ -1238,9 +1249,10 @@ module.exports = function (chai, _) {
|
|
|
1238
1249
|
, ssfi = flag(this, 'ssfi')
|
|
1239
1250
|
, objType = _.type(obj).toLowerCase()
|
|
1240
1251
|
, nType = _.type(n).toLowerCase()
|
|
1252
|
+
, errorMessage
|
|
1241
1253
|
, shouldThrow = true;
|
|
1242
1254
|
|
|
1243
|
-
if (doLength) {
|
|
1255
|
+
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1244
1256
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1245
1257
|
}
|
|
1246
1258
|
|
|
@@ -1260,13 +1272,20 @@ module.exports = function (chai, _) {
|
|
|
1260
1272
|
}
|
|
1261
1273
|
|
|
1262
1274
|
if (doLength) {
|
|
1263
|
-
var
|
|
1275
|
+
var descriptor = 'length'
|
|
1276
|
+
, itemsCount;
|
|
1277
|
+
if (objType === 'map' || objType === 'set') {
|
|
1278
|
+
descriptor = 'size';
|
|
1279
|
+
itemsCount = obj.size;
|
|
1280
|
+
} else {
|
|
1281
|
+
itemsCount = obj.length;
|
|
1282
|
+
}
|
|
1264
1283
|
this.assert(
|
|
1265
|
-
|
|
1266
|
-
, 'expected #{this} to have a
|
|
1267
|
-
, 'expected #{this} to have a
|
|
1284
|
+
itemsCount >= n
|
|
1285
|
+
, 'expected #{this} to have a ' + descriptor + ' at least #{exp} but got #{act}'
|
|
1286
|
+
, 'expected #{this} to have a ' + descriptor + ' below #{exp}'
|
|
1268
1287
|
, n
|
|
1269
|
-
,
|
|
1288
|
+
, itemsCount
|
|
1270
1289
|
);
|
|
1271
1290
|
} else {
|
|
1272
1291
|
this.assert(
|
|
@@ -1291,8 +1310,8 @@ module.exports = function (chai, _) {
|
|
|
1291
1310
|
* expect(1).to.equal(1); // Recommended
|
|
1292
1311
|
* expect(1).to.be.below(2); // Not recommended
|
|
1293
1312
|
*
|
|
1294
|
-
* Add `.lengthOf` earlier in the chain to assert that the
|
|
1295
|
-
*
|
|
1313
|
+
* Add `.lengthOf` earlier in the chain to assert that the target's `length`
|
|
1314
|
+
* or `size` is less than the given number `n`.
|
|
1296
1315
|
*
|
|
1297
1316
|
* expect('foo').to.have.lengthOf(3); // Recommended
|
|
1298
1317
|
* expect('foo').to.have.lengthOf.below(4); // Not recommended
|
|
@@ -1333,9 +1352,10 @@ module.exports = function (chai, _) {
|
|
|
1333
1352
|
, ssfi = flag(this, 'ssfi')
|
|
1334
1353
|
, objType = _.type(obj).toLowerCase()
|
|
1335
1354
|
, nType = _.type(n).toLowerCase()
|
|
1355
|
+
, errorMessage
|
|
1336
1356
|
, shouldThrow = true;
|
|
1337
1357
|
|
|
1338
|
-
if (doLength) {
|
|
1358
|
+
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1339
1359
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1340
1360
|
}
|
|
1341
1361
|
|
|
@@ -1355,13 +1375,20 @@ module.exports = function (chai, _) {
|
|
|
1355
1375
|
}
|
|
1356
1376
|
|
|
1357
1377
|
if (doLength) {
|
|
1358
|
-
var
|
|
1378
|
+
var descriptor = 'length'
|
|
1379
|
+
, itemsCount;
|
|
1380
|
+
if (objType === 'map' || objType === 'set') {
|
|
1381
|
+
descriptor = 'size';
|
|
1382
|
+
itemsCount = obj.size;
|
|
1383
|
+
} else {
|
|
1384
|
+
itemsCount = obj.length;
|
|
1385
|
+
}
|
|
1359
1386
|
this.assert(
|
|
1360
|
-
|
|
1361
|
-
, 'expected #{this} to have a
|
|
1362
|
-
, 'expected #{this} to not have a
|
|
1387
|
+
itemsCount < n
|
|
1388
|
+
, 'expected #{this} to have a ' + descriptor + ' below #{exp} but got #{act}'
|
|
1389
|
+
, 'expected #{this} to not have a ' + descriptor + ' below #{exp}'
|
|
1363
1390
|
, n
|
|
1364
|
-
,
|
|
1391
|
+
, itemsCount
|
|
1365
1392
|
);
|
|
1366
1393
|
} else {
|
|
1367
1394
|
this.assert(
|
|
@@ -1388,8 +1415,8 @@ module.exports = function (chai, _) {
|
|
|
1388
1415
|
* expect(1).to.be.at.most(2); // Not recommended
|
|
1389
1416
|
* expect(1).to.be.at.most(1); // Not recommended
|
|
1390
1417
|
*
|
|
1391
|
-
* Add `.lengthOf` earlier in the chain to assert that the
|
|
1392
|
-
*
|
|
1418
|
+
* Add `.lengthOf` earlier in the chain to assert that the target's `length`
|
|
1419
|
+
* or `size` is less than or equal to the given number `n`.
|
|
1393
1420
|
*
|
|
1394
1421
|
* expect('foo').to.have.lengthOf(3); // Recommended
|
|
1395
1422
|
* expect('foo').to.have.lengthOf.at.most(4); // Not recommended
|
|
@@ -1428,12 +1455,13 @@ module.exports = function (chai, _) {
|
|
|
1428
1455
|
, ssfi = flag(this, 'ssfi')
|
|
1429
1456
|
, objType = _.type(obj).toLowerCase()
|
|
1430
1457
|
, nType = _.type(n).toLowerCase()
|
|
1458
|
+
, errorMessage
|
|
1431
1459
|
, shouldThrow = true;
|
|
1432
1460
|
|
|
1433
|
-
if (doLength) {
|
|
1461
|
+
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1434
1462
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1435
1463
|
}
|
|
1436
|
-
|
|
1464
|
+
|
|
1437
1465
|
if (!doLength && (objType === 'date' && nType !== 'date')) {
|
|
1438
1466
|
errorMessage = msgPrefix + 'the argument to most must be a date';
|
|
1439
1467
|
} else if (nType !== 'number' && (doLength || objType === 'number')) {
|
|
@@ -1450,13 +1478,20 @@ module.exports = function (chai, _) {
|
|
|
1450
1478
|
}
|
|
1451
1479
|
|
|
1452
1480
|
if (doLength) {
|
|
1453
|
-
var
|
|
1481
|
+
var descriptor = 'length'
|
|
1482
|
+
, itemsCount;
|
|
1483
|
+
if (objType === 'map' || objType === 'set') {
|
|
1484
|
+
descriptor = 'size';
|
|
1485
|
+
itemsCount = obj.size;
|
|
1486
|
+
} else {
|
|
1487
|
+
itemsCount = obj.length;
|
|
1488
|
+
}
|
|
1454
1489
|
this.assert(
|
|
1455
|
-
|
|
1456
|
-
, 'expected #{this} to have a
|
|
1457
|
-
, 'expected #{this} to have a
|
|
1490
|
+
itemsCount <= n
|
|
1491
|
+
, 'expected #{this} to have a ' + descriptor + ' at most #{exp} but got #{act}'
|
|
1492
|
+
, 'expected #{this} to have a ' + descriptor + ' above #{exp}'
|
|
1458
1493
|
, n
|
|
1459
|
-
,
|
|
1494
|
+
, itemsCount
|
|
1460
1495
|
);
|
|
1461
1496
|
} else {
|
|
1462
1497
|
this.assert(
|
|
@@ -1484,9 +1519,9 @@ module.exports = function (chai, _) {
|
|
|
1484
1519
|
* expect(2).to.be.within(2, 3); // Not recommended
|
|
1485
1520
|
* expect(2).to.be.within(1, 2); // Not recommended
|
|
1486
1521
|
*
|
|
1487
|
-
* Add `.lengthOf` earlier in the chain to assert that the
|
|
1488
|
-
*
|
|
1489
|
-
*
|
|
1522
|
+
* Add `.lengthOf` earlier in the chain to assert that the target's `length`
|
|
1523
|
+
* or `size` is greater than or equal to the given number `start`, and less
|
|
1524
|
+
* than or equal to the given number `finish`.
|
|
1490
1525
|
*
|
|
1491
1526
|
* expect('foo').to.have.lengthOf(3); // Recommended
|
|
1492
1527
|
* expect('foo').to.have.lengthOf.within(2, 4); // Not recommended
|
|
@@ -1524,12 +1559,13 @@ module.exports = function (chai, _) {
|
|
|
1524
1559
|
, objType = _.type(obj).toLowerCase()
|
|
1525
1560
|
, startType = _.type(start).toLowerCase()
|
|
1526
1561
|
, finishType = _.type(finish).toLowerCase()
|
|
1562
|
+
, errorMessage
|
|
1527
1563
|
, shouldThrow = true
|
|
1528
1564
|
, range = (startType === 'date' && finishType === 'date')
|
|
1529
1565
|
? start.toUTCString() + '..' + finish.toUTCString()
|
|
1530
1566
|
: start + '..' + finish;
|
|
1531
1567
|
|
|
1532
|
-
if (doLength) {
|
|
1568
|
+
if (doLength && objType !== 'map' && objType !== 'set') {
|
|
1533
1569
|
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
1534
1570
|
}
|
|
1535
1571
|
|
|
@@ -1549,11 +1585,18 @@ module.exports = function (chai, _) {
|
|
|
1549
1585
|
}
|
|
1550
1586
|
|
|
1551
1587
|
if (doLength) {
|
|
1552
|
-
var
|
|
1588
|
+
var descriptor = 'length'
|
|
1589
|
+
, itemsCount;
|
|
1590
|
+
if (objType === 'map' || objType === 'set') {
|
|
1591
|
+
descriptor = 'size';
|
|
1592
|
+
itemsCount = obj.size;
|
|
1593
|
+
} else {
|
|
1594
|
+
itemsCount = obj.length;
|
|
1595
|
+
}
|
|
1553
1596
|
this.assert(
|
|
1554
|
-
|
|
1555
|
-
, 'expected #{this} to have a
|
|
1556
|
-
, 'expected #{this} to not have a
|
|
1597
|
+
itemsCount >= start && itemsCount <= finish
|
|
1598
|
+
, 'expected #{this} to have a ' + descriptor + ' within ' + range
|
|
1599
|
+
, 'expected #{this} to not have a ' + descriptor + ' within ' + range
|
|
1557
1600
|
);
|
|
1558
1601
|
} else {
|
|
1559
1602
|
this.assert(
|
|
@@ -1669,7 +1712,8 @@ module.exports = function (chai, _) {
|
|
|
1669
1712
|
*
|
|
1670
1713
|
* expect({a: 1}).to.have.own.property('a');
|
|
1671
1714
|
* expect({a: 1}).to.have.own.property('a', 1);
|
|
1672
|
-
* expect({a: 1}).to.have.property('b')
|
|
1715
|
+
* expect({a: 1}).to.have.property('b');
|
|
1716
|
+
* expect({a: 1}).to.not.have.own.property('b');
|
|
1673
1717
|
*
|
|
1674
1718
|
* `.deep` and `.own` can be combined.
|
|
1675
1719
|
*
|
|
@@ -1696,7 +1740,7 @@ module.exports = function (chai, _) {
|
|
|
1696
1740
|
* Add `.not` earlier in the chain to negate `.property`.
|
|
1697
1741
|
*
|
|
1698
1742
|
* expect({a: 1}).to.not.have.property('b');
|
|
1699
|
-
*
|
|
1743
|
+
*
|
|
1700
1744
|
* However, it's dangerous to negate `.property` when providing `val`. The
|
|
1701
1745
|
* problem is that it creates uncertain expectations by asserting that the
|
|
1702
1746
|
* target either doesn't have a property with the given key `name`, or that it
|
|
@@ -1734,7 +1778,7 @@ module.exports = function (chai, _) {
|
|
|
1734
1778
|
*
|
|
1735
1779
|
* // Not recommended
|
|
1736
1780
|
* expect({a: 1}).to.have.property('b', undefined, 'nooo why fail??');
|
|
1737
|
-
*
|
|
1781
|
+
*
|
|
1738
1782
|
* The above assertion isn't the same thing as not providing `val`. Instead,
|
|
1739
1783
|
* it's asserting that the target object has a `b` property that's equal to
|
|
1740
1784
|
* `undefined`.
|
|
@@ -1758,10 +1802,30 @@ module.exports = function (chai, _) {
|
|
|
1758
1802
|
, isOwn = flag(this, 'own')
|
|
1759
1803
|
, flagMsg = flag(this, 'message')
|
|
1760
1804
|
, obj = flag(this, 'object')
|
|
1761
|
-
, ssfi = flag(this, 'ssfi')
|
|
1805
|
+
, ssfi = flag(this, 'ssfi')
|
|
1806
|
+
, nameType = typeof name;
|
|
1807
|
+
|
|
1808
|
+
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1809
|
+
|
|
1810
|
+
if (isNested) {
|
|
1811
|
+
if (nameType !== 'string') {
|
|
1812
|
+
throw new AssertionError(
|
|
1813
|
+
flagMsg + 'the argument to property must be a string when using nested syntax',
|
|
1814
|
+
undefined,
|
|
1815
|
+
ssfi
|
|
1816
|
+
);
|
|
1817
|
+
}
|
|
1818
|
+
} else {
|
|
1819
|
+
if (nameType !== 'string' && nameType !== 'number' && nameType !== 'symbol') {
|
|
1820
|
+
throw new AssertionError(
|
|
1821
|
+
flagMsg + 'the argument to property must be a string, number, or symbol',
|
|
1822
|
+
undefined,
|
|
1823
|
+
ssfi
|
|
1824
|
+
);
|
|
1825
|
+
}
|
|
1826
|
+
}
|
|
1762
1827
|
|
|
1763
1828
|
if (isNested && isOwn) {
|
|
1764
|
-
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1765
1829
|
throw new AssertionError(
|
|
1766
1830
|
flagMsg + 'The "nested" and "own" flags cannot be combined.',
|
|
1767
1831
|
undefined,
|
|
@@ -1770,7 +1834,6 @@ module.exports = function (chai, _) {
|
|
|
1770
1834
|
}
|
|
1771
1835
|
|
|
1772
1836
|
if (obj === null || obj === undefined) {
|
|
1773
|
-
flagMsg = flagMsg ? flagMsg + ': ' : '';
|
|
1774
1837
|
throw new AssertionError(
|
|
1775
1838
|
flagMsg + 'Target cannot be null or undefined.',
|
|
1776
1839
|
undefined,
|
|
@@ -1853,7 +1916,7 @@ module.exports = function (chai, _) {
|
|
|
1853
1916
|
* Add `.not` earlier in the chain to negate `.ownPropertyDescriptor`.
|
|
1854
1917
|
*
|
|
1855
1918
|
* expect({a: 1}).to.not.have.ownPropertyDescriptor('b');
|
|
1856
|
-
*
|
|
1919
|
+
*
|
|
1857
1920
|
* However, it's dangerous to negate `.ownPropertyDescriptor` when providing
|
|
1858
1921
|
* a `descriptor`. The problem is that it creates uncertain expectations by
|
|
1859
1922
|
* asserting that the target either doesn't have a property descriptor with
|
|
@@ -1924,7 +1987,7 @@ module.exports = function (chai, _) {
|
|
|
1924
1987
|
* writable: true,
|
|
1925
1988
|
* value: 2,
|
|
1926
1989
|
* });
|
|
1927
|
-
*
|
|
1990
|
+
*
|
|
1928
1991
|
* // Recommended
|
|
1929
1992
|
* expect({a: 1}, 'nooo why fail??').to.have.ownPropertyDescriptor('b');
|
|
1930
1993
|
*
|
|
@@ -1981,11 +2044,13 @@ module.exports = function (chai, _) {
|
|
|
1981
2044
|
/**
|
|
1982
2045
|
* ### .lengthOf(n[, msg])
|
|
1983
2046
|
*
|
|
1984
|
-
* Asserts that the target's `length`
|
|
2047
|
+
* Asserts that the target's `length` or `size` is equal to the given number
|
|
1985
2048
|
* `n`.
|
|
1986
2049
|
*
|
|
1987
2050
|
* expect([1, 2, 3]).to.have.lengthOf(3);
|
|
1988
2051
|
* expect('foo').to.have.lengthOf(3);
|
|
2052
|
+
* expect(new Set([1, 2, 3])).to.have.lengthOf(3);
|
|
2053
|
+
* expect(new Map([['a', 1], ['b', 2], ['c', 3]])).to.have.lengthOf(3);
|
|
1989
2054
|
*
|
|
1990
2055
|
* Add `.not` earlier in the chain to negate `.lengthOf`. However, it's often
|
|
1991
2056
|
* best to assert that the target's `length` property is equal to its expected
|
|
@@ -2041,17 +2106,29 @@ module.exports = function (chai, _) {
|
|
|
2041
2106
|
function assertLength (n, msg) {
|
|
2042
2107
|
if (msg) flag(this, 'message', msg);
|
|
2043
2108
|
var obj = flag(this, 'object')
|
|
2109
|
+
, objType = _.type(obj).toLowerCase()
|
|
2044
2110
|
, flagMsg = flag(this, 'message')
|
|
2045
|
-
, ssfi = flag(this, 'ssfi')
|
|
2046
|
-
|
|
2047
|
-
|
|
2111
|
+
, ssfi = flag(this, 'ssfi')
|
|
2112
|
+
, descriptor = 'length'
|
|
2113
|
+
, itemsCount;
|
|
2114
|
+
|
|
2115
|
+
switch (objType) {
|
|
2116
|
+
case 'map':
|
|
2117
|
+
case 'set':
|
|
2118
|
+
descriptor = 'size';
|
|
2119
|
+
itemsCount = obj.size;
|
|
2120
|
+
break;
|
|
2121
|
+
default:
|
|
2122
|
+
new Assertion(obj, flagMsg, ssfi, true).to.have.property('length');
|
|
2123
|
+
itemsCount = obj.length;
|
|
2124
|
+
}
|
|
2048
2125
|
|
|
2049
2126
|
this.assert(
|
|
2050
|
-
|
|
2051
|
-
, 'expected #{this} to have a
|
|
2052
|
-
, 'expected #{this} to not have a
|
|
2127
|
+
itemsCount == n
|
|
2128
|
+
, 'expected #{this} to have a ' + descriptor + ' of #{exp} but got #{act}'
|
|
2129
|
+
, 'expected #{this} to not have a ' + descriptor + ' of #{act}'
|
|
2053
2130
|
, n
|
|
2054
|
-
,
|
|
2131
|
+
, itemsCount
|
|
2055
2132
|
);
|
|
2056
2133
|
}
|
|
2057
2134
|
|
|
@@ -2113,8 +2190,8 @@ module.exports = function (chai, _) {
|
|
|
2113
2190
|
* message to show when the assertion fails. The message can also be given as
|
|
2114
2191
|
* the second argument to `expect`.
|
|
2115
2192
|
*
|
|
2116
|
-
* expect('foobar').to.have.string(
|
|
2117
|
-
* expect('foobar', 'nooo why fail??').to.have.string(
|
|
2193
|
+
* expect('foobar').to.have.string('taco', 'nooo why fail??');
|
|
2194
|
+
* expect('foobar', 'nooo why fail??').to.have.string('taco');
|
|
2118
2195
|
*
|
|
2119
2196
|
* @name string
|
|
2120
2197
|
* @param {String} str
|
|
@@ -2141,7 +2218,7 @@ module.exports = function (chai, _) {
|
|
|
2141
2218
|
* ### .keys(key1[, key2[, ...]])
|
|
2142
2219
|
*
|
|
2143
2220
|
* Asserts that the target object, array, map, or set has the given keys. Only
|
|
2144
|
-
* the target's own inherited properties are included in the search.
|
|
2221
|
+
* the target's own inherited properties are included in the search.
|
|
2145
2222
|
*
|
|
2146
2223
|
* When the target is an object or array, keys can be provided as one or more
|
|
2147
2224
|
* string arguments, a single array argument, or a single object argument. In
|
|
@@ -2249,6 +2326,7 @@ module.exports = function (chai, _) {
|
|
|
2249
2326
|
, isDeep = flag(this, 'deep')
|
|
2250
2327
|
, str
|
|
2251
2328
|
, deepStr = ''
|
|
2329
|
+
, actual
|
|
2252
2330
|
, ok = true
|
|
2253
2331
|
, flagMsg = flag(this, 'message');
|
|
2254
2332
|
|
|
@@ -2265,7 +2343,6 @@ module.exports = function (chai, _) {
|
|
|
2265
2343
|
if (keysType !== 'Array') {
|
|
2266
2344
|
keys = Array.prototype.slice.call(arguments);
|
|
2267
2345
|
}
|
|
2268
|
-
|
|
2269
2346
|
} else {
|
|
2270
2347
|
actual = _.getOwnEnumerableProperties(obj);
|
|
2271
2348
|
|
|
@@ -2298,8 +2375,7 @@ module.exports = function (chai, _) {
|
|
|
2298
2375
|
var len = keys.length
|
|
2299
2376
|
, any = flag(this, 'any')
|
|
2300
2377
|
, all = flag(this, 'all')
|
|
2301
|
-
, expected = keys
|
|
2302
|
-
, actual;
|
|
2378
|
+
, expected = keys;
|
|
2303
2379
|
|
|
2304
2380
|
if (!any && !all) {
|
|
2305
2381
|
all = true;
|
|
@@ -2376,7 +2452,7 @@ module.exports = function (chai, _) {
|
|
|
2376
2452
|
*
|
|
2377
2453
|
* When no arguments are provided, `.throw` invokes the target function and
|
|
2378
2454
|
* asserts that an error is thrown.
|
|
2379
|
-
*
|
|
2455
|
+
*
|
|
2380
2456
|
* var badFn = function () { throw new TypeError('Illegal salmon!'); };
|
|
2381
2457
|
*
|
|
2382
2458
|
* expect(badFn).to.throw();
|
|
@@ -2428,11 +2504,11 @@ module.exports = function (chai, _) {
|
|
|
2428
2504
|
* expect(badFn).to.throw(err, /salmon/);
|
|
2429
2505
|
*
|
|
2430
2506
|
* Add `.not` earlier in the chain to negate `.throw`.
|
|
2431
|
-
*
|
|
2507
|
+
*
|
|
2432
2508
|
* var goodFn = function () {};
|
|
2433
2509
|
*
|
|
2434
2510
|
* expect(goodFn).to.not.throw();
|
|
2435
|
-
*
|
|
2511
|
+
*
|
|
2436
2512
|
* However, it's dangerous to negate `.throw` when providing any arguments.
|
|
2437
2513
|
* The problem is that it creates uncertain expectations by asserting that the
|
|
2438
2514
|
* target either doesn't throw an error, or that it throws an error but of a
|
|
@@ -2780,7 +2856,7 @@ module.exports = function (chai, _) {
|
|
|
2780
2856
|
* first argument, and asserts that the value returned is truthy.
|
|
2781
2857
|
*
|
|
2782
2858
|
* expect(1).to.satisfy(function(num) {
|
|
2783
|
-
* return num > 0;
|
|
2859
|
+
* return num > 0;
|
|
2784
2860
|
* });
|
|
2785
2861
|
*
|
|
2786
2862
|
* Add `.not` earlier in the chain to negate `.satisfy`.
|
|
@@ -3001,7 +3077,7 @@ module.exports = function (chai, _) {
|
|
|
3001
3077
|
var contains = flag(this, 'contains');
|
|
3002
3078
|
var ordered = flag(this, 'ordered');
|
|
3003
3079
|
|
|
3004
|
-
var subject, failMsg, failNegateMsg
|
|
3080
|
+
var subject, failMsg, failNegateMsg;
|
|
3005
3081
|
|
|
3006
3082
|
if (contains) {
|
|
3007
3083
|
subject = ordered ? 'an ordered superset' : 'a superset';
|
|
@@ -3073,7 +3149,6 @@ module.exports = function (chai, _) {
|
|
|
3073
3149
|
|
|
3074
3150
|
Assertion.addMethod('oneOf', oneOf);
|
|
3075
3151
|
|
|
3076
|
-
|
|
3077
3152
|
/**
|
|
3078
3153
|
* ### .change(subject[, prop[, msg]])
|
|
3079
3154
|
*
|
|
@@ -3249,7 +3324,7 @@ module.exports = function (chai, _) {
|
|
|
3249
3324
|
*
|
|
3250
3325
|
* expect(subtractTwo).to.decrease(myObj, 'val').by(2); // Recommended
|
|
3251
3326
|
* expect(subtractTwo).to.not.increase(myObj, 'val'); // Not recommended
|
|
3252
|
-
*
|
|
3327
|
+
*
|
|
3253
3328
|
* When the subject is expected to stay the same, it's often best to assert
|
|
3254
3329
|
* exactly that.
|
|
3255
3330
|
*
|
|
@@ -3346,7 +3421,7 @@ module.exports = function (chai, _) {
|
|
|
3346
3421
|
*
|
|
3347
3422
|
* When two arguments are provided, `.decrease` asserts that the value of the
|
|
3348
3423
|
* given object `subject`'s `prop` property is lesser after invoking the
|
|
3349
|
-
* target function compared to beforehand.
|
|
3424
|
+
* target function compared to beforehand.
|
|
3350
3425
|
*
|
|
3351
3426
|
* var myObj = {val: 1}
|
|
3352
3427
|
* , subtractTwo = function () { myObj.val -= 2; };
|
|
@@ -3368,7 +3443,7 @@ module.exports = function (chai, _) {
|
|
|
3368
3443
|
*
|
|
3369
3444
|
* expect(addTwo).to.increase(myObj, 'val').by(2); // Recommended
|
|
3370
3445
|
* expect(addTwo).to.not.decrease(myObj, 'val'); // Not recommended
|
|
3371
|
-
*
|
|
3446
|
+
*
|
|
3372
3447
|
* When the subject is expected to stay the same, it's often best to assert
|
|
3373
3448
|
* exactly that.
|
|
3374
3449
|
*
|
|
@@ -3721,7 +3796,7 @@ module.exports = function (chai, _) {
|
|
|
3721
3796
|
var obj = flag(this, 'object');
|
|
3722
3797
|
|
|
3723
3798
|
this.assert(
|
|
3724
|
-
typeof obj ===
|
|
3799
|
+
typeof obj === 'number' && isFinite(obj)
|
|
3725
3800
|
, 'expected #{this} to be a finite number'
|
|
3726
3801
|
, 'expected #{this} to not be a finite number'
|
|
3727
3802
|
);
|