chai 5.0.0-rc.0 → 5.0.2

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/README.md CHANGED
@@ -71,32 +71,12 @@ You can also use it within the browser; install via npm and use the `chai.js` fi
71
71
  Import the library in your code, and then pick one of the styles you'd like to use - either `assert`, `expect` or `should`:
72
72
 
73
73
  ```js
74
- var chai = require('chai');
75
- var assert = chai.assert; // Using Assert style
76
- var expect = chai.expect; // Using Expect style
77
- var should = chai.should(); // Using Should style
78
- ```
79
-
80
- ### Pre-Native Modules Usage (_registers the chai testing style globally_)
81
-
82
- ```js
83
- require('chai/register-assert'); // Using Assert style
84
- require('chai/register-expect'); // Using Expect style
85
- require('chai/register-should'); // Using Should style
86
- ```
87
-
88
- ### Pre-Native Modules Usage (_as local variables_)
89
-
90
- ```js
91
- const { assert } = require('chai'); // Using Assert style
92
- const { expect } = require('chai'); // Using Expect style
93
- const { should } = require('chai'); // Using Should style
94
- should(); // Modifies `Object.prototype`
95
-
96
- const { expect, use } = require('chai'); // Creates local variables `expect` and `use`; useful for plugin use
74
+ import { assert } from 'chai'; // Using Assert style
75
+ import { expect } from 'chai'; // Using Expect style
76
+ import { should } from 'chai'; // Using Should style
97
77
  ```
98
78
 
99
- ### Native Modules Usage (_registers the chai testing style globally_)
79
+ ### Register the chai testing style globally
100
80
 
101
81
  ```js
102
82
  import 'chai/register-assert'; // Using Assert style
@@ -104,13 +84,15 @@ import 'chai/register-expect'; // Using Expect style
104
84
  import 'chai/register-should'; // Using Should style
105
85
  ```
106
86
 
107
- ### Native Modules Usage (_local import only_)
87
+ ### Import assertion styles as local variables
108
88
 
109
89
  ```js
110
90
  import { assert } from 'chai'; // Using Assert style
111
91
  import { expect } from 'chai'; // Using Expect style
112
92
  import { should } from 'chai'; // Using Should style
113
93
  should(); // Modifies `Object.prototype`
94
+
95
+ import { expect, use } from 'chai'; // Creates local variables `expect` and `use`; useful for plugin use
114
96
  ```
115
97
 
116
98
  ### Usage with Mocha
@@ -40,6 +40,8 @@ import * as util from './utils/index.js';
40
40
  * from within another assertion. It's also temporarily set to `true` before
41
41
  * an overwritten assertion gets called by the overwriting assertion.
42
42
  *
43
+ * - `eql`: This flag contains the deepEqual function to be used by the assertion.
44
+ *
43
45
  * @param {Mixed} obj target of the assertion
44
46
  * @param {String} msg (optional) custom error message
45
47
  * @param {Function} ssfi (optional) starting point for removing stack frames
@@ -52,6 +54,7 @@ export function Assertion (obj, msg, ssfi, lockSsfi) {
52
54
  util.flag(this, 'lockSsfi', lockSsfi);
53
55
  util.flag(this, 'object', obj);
54
56
  util.flag(this, 'message', msg);
57
+ util.flag(this, 'eql', config.deepEqual || util.eql);
55
58
 
56
59
  return util.proxify(this);
57
60
  }
@@ -90,5 +90,31 @@ export const config = {
90
90
  * @api public
91
91
  */
92
92
 
93
- proxyExcludedKeys: ['then', 'catch', 'inspect', 'toJSON']
93
+ proxyExcludedKeys: ['then', 'catch', 'inspect', 'toJSON'],
94
+
95
+ /**
96
+ * ### config.deepEqual
97
+ *
98
+ * User configurable property, defines which a custom function to use for deepEqual
99
+ * comparisons.
100
+ * By default, the function used is the one from the `deep-eql` package without custom comparator.
101
+ *
102
+ * // use a custom comparator
103
+ * chai.config.deepEqual = (expected, actual) => {
104
+ * return chai.util.eql(expected, actual, {
105
+ * comparator: (expected, actual) => {
106
+ * // for non number comparison, use the default behavior
107
+ * if(typeof expected !== 'number') return null;
108
+ * // allow a difference of 10 between compared numbers
109
+ * return typeof actual === 'number' && Math.abs(actual - expected) < 10
110
+ * }
111
+ * })
112
+ * };
113
+ *
114
+ * @param {Function}
115
+ * @api public
116
+ */
117
+
118
+ deepEqual: null
119
+
94
120
  };
@@ -239,6 +239,13 @@ Assertion.addProperty('all', function () {
239
239
  flag(this, 'any', false);
240
240
  });
241
241
 
242
+ const functionTypes = {
243
+ 'function': ['function', 'asyncfunction', 'generatorfunction', 'asyncgeneratorfunction'],
244
+ 'asyncfunction': ['asyncfunction', 'asyncgeneratorfunction'],
245
+ 'generatorfunction': ['generatorfunction', 'asyncgeneratorfunction'],
246
+ 'asyncgeneratorfunction': ['asyncgeneratorfunction']
247
+ }
248
+
242
249
  /**
243
250
  * ### .a(type[, msg])
244
251
  *
@@ -298,18 +305,27 @@ Assertion.addProperty('all', function () {
298
305
  * @namespace BDD
299
306
  * @api public
300
307
  */
301
-
302
308
  function an (type, msg) {
303
309
  if (msg) flag(this, 'message', msg);
304
310
  type = type.toLowerCase();
305
311
  var obj = flag(this, 'object')
306
312
  , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
307
313
 
308
- this.assert(
309
- type === _.type(obj).toLowerCase()
310
- , 'expected #{this} to be ' + article + type
311
- , 'expected #{this} not to be ' + article + type
312
- );
314
+ const detectedType = _.type(obj).toLowerCase();
315
+
316
+ if (functionTypes['function'].includes(type)) {
317
+ this.assert(
318
+ functionTypes[type].includes(detectedType)
319
+ , 'expected #{this} to be ' + article + type
320
+ , 'expected #{this} not to be ' + article + type
321
+ );
322
+ } else {
323
+ this.assert(
324
+ type === detectedType
325
+ , 'expected #{this} to be ' + article + type
326
+ , 'expected #{this} not to be ' + article + type
327
+ );
328
+ }
313
329
  }
314
330
 
315
331
  Assertion.addChainableMethod('an', an);
@@ -479,7 +495,8 @@ function include (val, msg) {
479
495
  , negate = flag(this, 'negate')
480
496
  , ssfi = flag(this, 'ssfi')
481
497
  , isDeep = flag(this, 'deep')
482
- , descriptor = isDeep ? 'deep ' : '';
498
+ , descriptor = isDeep ? 'deep ' : ''
499
+ , isEql = isDeep ? flag(this, 'eql') : SameValueZero;
483
500
 
484
501
  flagMsg = flagMsg ? flagMsg + ': ' : '';
485
502
 
@@ -503,7 +520,6 @@ function include (val, msg) {
503
520
  break;
504
521
 
505
522
  case 'map':
506
- var isEql = isDeep ? _.eql : SameValueZero;
507
523
  obj.forEach(function (item) {
508
524
  included = included || isEql(item, val);
509
525
  });
@@ -512,7 +528,7 @@ function include (val, msg) {
512
528
  case 'set':
513
529
  if (isDeep) {
514
530
  obj.forEach(function (item) {
515
- included = included || _.eql(item, val);
531
+ included = included || isEql(item, val);
516
532
  });
517
533
  } else {
518
534
  included = obj.has(val);
@@ -522,7 +538,7 @@ function include (val, msg) {
522
538
  case 'array':
523
539
  if (isDeep) {
524
540
  included = obj.some(function (item) {
525
- return _.eql(item, val);
541
+ return isEql(item, val);
526
542
  })
527
543
  } else {
528
544
  included = obj.indexOf(val) !== -1;
@@ -672,6 +688,43 @@ Assertion.addProperty('true', function () {
672
688
  );
673
689
  });
674
690
 
691
+ /**
692
+ * ### .callable
693
+ *
694
+ * Asserts that the target a callable function.
695
+ *
696
+ * expect(console.log).to.be.callable;
697
+ *
698
+ * A custom error message can be given as the second argument to `expect`.
699
+ *
700
+ * expect('not a function', 'nooo why fail??').to.be.callable;
701
+ *
702
+ * @name callable
703
+ * @namespace BDD
704
+ * @api public
705
+ */
706
+ Assertion.addProperty('callable', function () {
707
+ const val = flag(this, 'object')
708
+ const ssfi = flag(this, 'ssfi')
709
+ const message = flag(this, 'message')
710
+ const msg = message ? `${message}: ` : ''
711
+ const negate = flag(this, 'negate');
712
+
713
+ const assertionMessage = negate ?
714
+ `${msg}expected ${_.inspect(val)} not to be a callable function` :
715
+ `${msg}expected ${_.inspect(val)} to be a callable function`;
716
+
717
+ const isCallable = ['Function', 'AsyncFunction', 'GeneratorFunction', 'AsyncGeneratorFunction'].includes(_.type(val));
718
+
719
+ if ((isCallable && negate) || (!isCallable && !negate)) {
720
+ throw new AssertionError(
721
+ assertionMessage,
722
+ undefined,
723
+ ssfi
724
+ );
725
+ }
726
+ });
727
+
675
728
  /**
676
729
  * ### .false
677
730
  *
@@ -1094,8 +1147,9 @@ Assertion.addMethod('eq', assertEqual);
1094
1147
 
1095
1148
  function assertEql(obj, msg) {
1096
1149
  if (msg) flag(this, 'message', msg);
1150
+ var eql = flag(this, 'eql');
1097
1151
  this.assert(
1098
- _.eql(obj, flag(this, 'object'))
1152
+ eql(obj, flag(this, 'object'))
1099
1153
  , 'expected #{this} to deeply equal #{exp}'
1100
1154
  , 'expected #{this} to not deeply equal #{exp}'
1101
1155
  , obj
@@ -1863,7 +1917,8 @@ function assertProperty (name, val, msg) {
1863
1917
  var isDeep = flag(this, 'deep')
1864
1918
  , negate = flag(this, 'negate')
1865
1919
  , pathInfo = isNested ? _.getPathInfo(obj, name) : null
1866
- , value = isNested ? pathInfo.value : obj[name];
1920
+ , value = isNested ? pathInfo.value : obj[name]
1921
+ , isEql = isDeep ? flag(this, 'eql') : (val1, val2) => val1 === val2;
1867
1922
 
1868
1923
  var descriptor = '';
1869
1924
  if (isDeep) descriptor += 'deep ';
@@ -1890,7 +1945,7 @@ function assertProperty (name, val, msg) {
1890
1945
 
1891
1946
  if (arguments.length > 1) {
1892
1947
  this.assert(
1893
- hasProperty && (isDeep ? _.eql(val, value) : val === value)
1948
+ hasProperty && isEql(val, value)
1894
1949
  , 'expected #{this} to have ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
1895
1950
  , 'expected #{this} to not have ' + descriptor + _.inspect(name) + ' of #{act}'
1896
1951
  , val
@@ -2038,9 +2093,10 @@ function assertOwnPropertyDescriptor (name, descriptor, msg) {
2038
2093
  if (msg) flag(this, 'message', msg);
2039
2094
  var obj = flag(this, 'object');
2040
2095
  var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
2096
+ var eql = flag(this, 'eql');
2041
2097
  if (actualDescriptor && descriptor) {
2042
2098
  this.assert(
2043
- _.eql(descriptor, actualDescriptor)
2099
+ eql(descriptor, actualDescriptor)
2044
2100
  , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
2045
2101
  , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
2046
2102
  , descriptor
@@ -2394,7 +2450,8 @@ function assertKeys (keys) {
2394
2450
  var len = keys.length
2395
2451
  , any = flag(this, 'any')
2396
2452
  , all = flag(this, 'all')
2397
- , expected = keys;
2453
+ , expected = keys
2454
+ , isEql = isDeep ? flag(this, 'eql') : (val1, val2) => val1 === val2;
2398
2455
 
2399
2456
  if (!any && !all) {
2400
2457
  all = true;
@@ -2404,11 +2461,7 @@ function assertKeys (keys) {
2404
2461
  if (any) {
2405
2462
  ok = expected.some(function(expectedKey) {
2406
2463
  return actual.some(function(actualKey) {
2407
- if (isDeep) {
2408
- return _.eql(expectedKey, actualKey);
2409
- } else {
2410
- return expectedKey === actualKey;
2411
- }
2464
+ return isEql(expectedKey, actualKey);
2412
2465
  });
2413
2466
  });
2414
2467
  }
@@ -2417,11 +2470,7 @@ function assertKeys (keys) {
2417
2470
  if (all) {
2418
2471
  ok = expected.every(function(expectedKey) {
2419
2472
  return actual.some(function(actualKey) {
2420
- if (isDeep) {
2421
- return _.eql(expectedKey, actualKey);
2422
- } else {
2423
- return expectedKey === actualKey;
2424
- }
2473
+ return isEql(expectedKey, actualKey);
2425
2474
  });
2426
2475
  });
2427
2476
 
@@ -3109,7 +3158,7 @@ Assertion.addMethod('members', function (subset, msg) {
3109
3158
  failNegateMsg = 'expected #{this} to not have the same ' + subject + ' as #{exp}';
3110
3159
  }
3111
3160
 
3112
- var cmp = flag(this, 'deep') ? _.eql : undefined;
3161
+ var cmp = flag(this, 'deep') ? flag(this, 'eql') : undefined;
3113
3162
 
3114
3163
  this.assert(
3115
3164
  isSubsetOf(subset, obj, cmp, contains, ordered)
@@ -3165,7 +3214,8 @@ function oneOf (list, msg) {
3165
3214
  , flagMsg = flag(this, 'message')
3166
3215
  , ssfi = flag(this, 'ssfi')
3167
3216
  , contains = flag(this, 'contains')
3168
- , isDeep = flag(this, 'deep');
3217
+ , isDeep = flag(this, 'deep')
3218
+ , eql = flag(this, 'eql');
3169
3219
  new Assertion(list, flagMsg, ssfi, true).to.be.an('array');
3170
3220
 
3171
3221
  if (contains) {
@@ -3179,7 +3229,7 @@ function oneOf (list, msg) {
3179
3229
  } else {
3180
3230
  if (isDeep) {
3181
3231
  this.assert(
3182
- list.some(function(possibility) { return _.eql(expected, possibility) })
3232
+ list.some(function(possibility) { return eql(expected, possibility) })
3183
3233
  , 'expected #{this} to deeply equal one of #{exp}'
3184
3234
  , 'expected #{this} to deeply equal one of #{exp}'
3185
3235
  , list
@@ -8,6 +8,7 @@ import * as chai from '../../../index.js';
8
8
  import {Assertion} from '../assertion.js';
9
9
  import {flag, inspect} from '../utils/index.js';
10
10
  import {AssertionError} from 'assertion-error';
11
+ import {type} from '../utils/type-detect.js';
11
12
 
12
13
  /**
13
14
  * ### assert(expression, message)
@@ -553,41 +554,39 @@ assert.isDefined = function (val, msg) {
553
554
  };
554
555
 
555
556
  /**
556
- * ### .isFunction(value, [message])
557
+ * ### .isCallable(value, [message])
557
558
  *
558
- * Asserts that `value` is a function.
559
+ * Asserts that `value` is a callable function.
559
560
  *
560
561
  * function serveTea() { return 'cup of tea'; };
561
- * assert.isFunction(serveTea, 'great, we can have tea now');
562
+ * assert.isCallable(serveTea, 'great, we can have tea now');
562
563
  *
563
- * @name isFunction
564
+ * @name isCallable
564
565
  * @param {Mixed} value
565
566
  * @param {String} message
566
567
  * @namespace Assert
567
568
  * @api public
568
569
  */
569
-
570
- assert.isFunction = function (val, msg) {
571
- new Assertion(val, msg, assert.isFunction, true).to.be.a('function');
572
- };
570
+ assert.isCallable = function (val, msg) {
571
+ new Assertion(val, msg, assert.isCallable, true).is.callable;
572
+ }
573
573
 
574
574
  /**
575
- * ### .isNotFunction(value, [message])
575
+ * ### .isNotCallable(value, [message])
576
576
  *
577
- * Asserts that `value` is _not_ a function.
577
+ * Asserts that `value` is _not_ a callable function.
578
578
  *
579
579
  * var serveTea = [ 'heat', 'pour', 'sip' ];
580
- * assert.isNotFunction(serveTea, 'great, we have listed the steps');
580
+ * assert.isNotCallable(serveTea, 'great, we have listed the steps');
581
581
  *
582
- * @name isNotFunction
582
+ * @name isNotCallable
583
583
  * @param {Mixed} value
584
584
  * @param {String} message
585
585
  * @namespace Assert
586
586
  * @api public
587
587
  */
588
-
589
- assert.isNotFunction = function (val, msg) {
590
- new Assertion(val, msg, assert.isNotFunction, true).to.not.be.a('function');
588
+ assert.isNotCallable = function (val, msg) {
589
+ new Assertion(val, msg, assert.isNotCallable, true).is.not.callable;
591
590
  };
592
591
 
593
592
  /**
@@ -3104,4 +3103,6 @@ assert.isNotEmpty = function(val, msg) {
3104
3103
  ('isFrozen', 'frozen')
3105
3104
  ('isNotFrozen', 'notFrozen')
3106
3105
  ('isEmpty', 'empty')
3107
- ('isNotEmpty', 'notEmpty');
3106
+ ('isNotEmpty', 'notEmpty')
3107
+ ('isCallable', 'isFunction')
3108
+ ('isNotCallable', 'isNotFunction')
package/package.json CHANGED
@@ -18,7 +18,7 @@
18
18
  "Veselin Todorov <hi@vesln.com>",
19
19
  "John Firebaugh <john.firebaugh@gmail.com>"
20
20
  ],
21
- "version": "5.0.0-rc.0",
21
+ "version": "5.0.2",
22
22
  "repository": {
23
23
  "type": "git",
24
24
  "url": "https://github.com/chaijs/chai"
@@ -44,16 +44,15 @@
44
44
  "assertion-error": "^2.0.1",
45
45
  "check-error": "^2.0.0",
46
46
  "deep-eql": "^5.0.1",
47
- "loupe": "^3.0.0",
47
+ "loupe": "^3.1.0",
48
48
  "pathval": "^2.0.0"
49
49
  },
50
50
  "devDependencies": {
51
51
  "@rollup/plugin-commonjs": "^25.0.7",
52
- "@web/dev-server-rollup": "^0.5.4",
53
- "@web/test-runner": "^0.17.2",
54
- "@web/test-runner-playwright": "^0.10.2",
55
- "bump-cli": "^1.1.3",
56
- "esbuild": "^0.17.3",
57
- "mocha": "^8.3.0"
52
+ "@web/dev-server-rollup": "^0.6.1",
53
+ "@web/test-runner": "^0.18.0",
54
+ "@web/test-runner-playwright": "^0.11.0",
55
+ "esbuild": "^0.19.10",
56
+ "mocha": "^10.2.0"
58
57
  }
59
58
  }
package/bower.json DELETED
@@ -1,26 +0,0 @@
1
- {
2
- "name": "chai",
3
- "description": "BDD/TDD assertion library for node.js and the browser. Test framework agnostic.",
4
- "license": "MIT",
5
- "keywords": [
6
- "test",
7
- "assertion",
8
- "assert",
9
- "testing",
10
- "chai"
11
- ],
12
- "main": "chai.js",
13
- "ignore": [
14
- "build",
15
- "components",
16
- "lib",
17
- "node_modules",
18
- "support",
19
- "test",
20
- "index.js",
21
- "Makefile",
22
- ".*"
23
- ],
24
- "dependencies": {},
25
- "devDependencies": {}
26
- }