mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
assert: allow printf-style messages as assertion error
Also add functions as allowed message input. This allows to have leavy message computation to become cheaper. PR-URL: https://github.com/nodejs/node/pull/58849 Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
This commit is contained in:
parent
8096aeab81
commit
d3f79aa65d
|
|
@ -39,6 +39,27 @@ strict methods. For example, [`assert.deepEqual()`][] will behave like
|
||||||
In strict assertion mode, error messages for objects display a diff. In legacy
|
In strict assertion mode, error messages for objects display a diff. In legacy
|
||||||
assertion mode, error messages for objects display the objects, often truncated.
|
assertion mode, error messages for objects display the objects, often truncated.
|
||||||
|
|
||||||
|
### Message parameter semantics
|
||||||
|
|
||||||
|
For assertion methods that accept an optional `message` parameter, the message
|
||||||
|
may be provided in one of the following forms:
|
||||||
|
|
||||||
|
* **string**: Used as-is. If additional arguments are supplied after the
|
||||||
|
`message` string, they are treated as printf-like substitutions (see
|
||||||
|
[`util.format()`][]).
|
||||||
|
* **Error**: If an `Error` instance is provided as `message`, that error is
|
||||||
|
thrown directly instead of an `AssertionError`.
|
||||||
|
* **function**: A function of the form `(actual, expected) => string`. It is
|
||||||
|
called only when the assertion fails and should return a string to be used as
|
||||||
|
the error message. Non-string return values are ignored and the default
|
||||||
|
message is used instead.
|
||||||
|
|
||||||
|
If additional arguments are passed along with an `Error` or a function as
|
||||||
|
`message`, the call is rejected with `ERR_AMBIGUOUS_ARGUMENT`.
|
||||||
|
|
||||||
|
If the first item is neither a string, `Error`, nor function, `ERR_INVALID_ARG_TYPE`
|
||||||
|
is thrown.
|
||||||
|
|
||||||
To use strict assertion mode:
|
To use strict assertion mode:
|
||||||
|
|
||||||
```mjs
|
```mjs
|
||||||
|
|
@ -305,10 +326,14 @@ destructuring and call methods directly on the instance.
|
||||||
|
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.5.9
|
added: v0.5.9
|
||||||
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
* `value` {any} The input that is checked for being truthy.
|
* `value` {any} The input that is checked for being truthy.
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
An alias of [`assert.ok()`][].
|
An alias of [`assert.ok()`][].
|
||||||
|
|
||||||
|
|
@ -324,6 +349,9 @@ changes:
|
||||||
- version: v25.0.0
|
- version: v25.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/57627
|
pr-url: https://github.com/nodejs/node/pull/57627
|
||||||
description: Invalid dates are now considered equal.
|
description: Invalid dates are now considered equal.
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v24.0.0
|
- version: v24.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/57622
|
pr-url: https://github.com/nodejs/node/pull/57622
|
||||||
description: Recursion now stops when either side encounters a circular
|
description: Recursion now stops when either side encounters a circular
|
||||||
|
|
@ -375,7 +403,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
**Strict assertion mode**
|
**Strict assertion mode**
|
||||||
|
|
||||||
|
|
@ -524,6 +552,9 @@ changes:
|
||||||
- version: v25.0.0
|
- version: v25.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/57627
|
pr-url: https://github.com/nodejs/node/pull/57627
|
||||||
description: Invalid dates are now considered equal.
|
description: Invalid dates are now considered equal.
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v24.0.0
|
- version: v24.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/57622
|
pr-url: https://github.com/nodejs/node/pull/57622
|
||||||
description: Recursion now stops when either side encounters a circular
|
description: Recursion now stops when either side encounters a circular
|
||||||
|
|
@ -567,7 +598,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Tests for deep equality between the `actual` and `expected` parameters.
|
Tests for deep equality between the `actual` and `expected` parameters.
|
||||||
"Deep" equality means that the enumerable "own" properties of child objects
|
"Deep" equality means that the enumerable "own" properties of child objects
|
||||||
|
|
@ -829,6 +860,9 @@ added:
|
||||||
- v13.6.0
|
- v13.6.0
|
||||||
- v12.16.0
|
- v12.16.0
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v16.0.0
|
- version: v16.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/38111
|
pr-url: https://github.com/nodejs/node/pull/38111
|
||||||
description: This API is no longer experimental.
|
description: This API is no longer experimental.
|
||||||
|
|
@ -836,7 +870,7 @@ changes:
|
||||||
|
|
||||||
* `string` {string}
|
* `string` {string}
|
||||||
* `regexp` {RegExp}
|
* `regexp` {RegExp}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Expects the `string` input not to match the regular expression.
|
Expects the `string` input not to match the regular expression.
|
||||||
|
|
||||||
|
|
@ -1069,6 +1103,9 @@ assert.doesNotThrow(
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version:
|
- version:
|
||||||
- v16.0.0
|
- v16.0.0
|
||||||
- v14.18.0
|
- v14.18.0
|
||||||
|
|
@ -1083,7 +1120,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
**Strict assertion mode**
|
**Strict assertion mode**
|
||||||
|
|
||||||
|
|
@ -1254,6 +1291,9 @@ added:
|
||||||
- v13.6.0
|
- v13.6.0
|
||||||
- v12.16.0
|
- v12.16.0
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v16.0.0
|
- version: v16.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/38111
|
pr-url: https://github.com/nodejs/node/pull/38111
|
||||||
description: This API is no longer experimental.
|
description: This API is no longer experimental.
|
||||||
|
|
@ -1261,7 +1301,7 @@ changes:
|
||||||
|
|
||||||
* `string` {string}
|
* `string` {string}
|
||||||
* `regexp` {RegExp}
|
* `regexp` {RegExp}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Expects the `string` input to match the regular expression.
|
Expects the `string` input to match the regular expression.
|
||||||
|
|
||||||
|
|
@ -1303,6 +1343,9 @@ instance of {Error} then it will be thrown instead of the
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version:
|
- version:
|
||||||
- v16.0.0
|
- v16.0.0
|
||||||
- v14.18.0
|
- v14.18.0
|
||||||
|
|
@ -1338,7 +1381,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
**Strict assertion mode**
|
**Strict assertion mode**
|
||||||
|
|
||||||
|
|
@ -1427,6 +1470,9 @@ instead of the `AssertionError`.
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v1.2.0
|
added: v1.2.0
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v9.0.0
|
- version: v9.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/15398
|
pr-url: https://github.com/nodejs/node/pull/15398
|
||||||
description: The `-0` and `+0` are not considered equal anymore.
|
description: The `-0` and `+0` are not considered equal anymore.
|
||||||
|
|
@ -1458,7 +1504,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual()`][].
|
Tests for deep strict inequality. Opposite of [`assert.deepStrictEqual()`][].
|
||||||
|
|
||||||
|
|
@ -1487,6 +1533,9 @@ instead of the [`AssertionError`][].
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version:
|
- version:
|
||||||
- v16.0.0
|
- v16.0.0
|
||||||
- v14.18.0
|
- v14.18.0
|
||||||
|
|
@ -1501,7 +1550,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
**Strict assertion mode**
|
**Strict assertion mode**
|
||||||
|
|
||||||
|
|
@ -1551,6 +1600,9 @@ parameter is an instance of {Error} then it will be thrown instead of the
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v10.0.0
|
- version: v10.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/17003
|
pr-url: https://github.com/nodejs/node/pull/17003
|
||||||
description: Used comparison changed from Strict Equality to `Object.is()`.
|
description: Used comparison changed from Strict Equality to `Object.is()`.
|
||||||
|
|
@ -1558,7 +1610,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Tests strict inequality between the `actual` and `expected` parameters as
|
Tests strict inequality between the `actual` and `expected` parameters as
|
||||||
determined by [`Object.is()`][].
|
determined by [`Object.is()`][].
|
||||||
|
|
@ -1604,6 +1656,9 @@ instead of the `AssertionError`.
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v10.0.0
|
- version: v10.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/18319
|
pr-url: https://github.com/nodejs/node/pull/18319
|
||||||
description: The `assert.ok()` (no arguments) will now use a predefined
|
description: The `assert.ok()` (no arguments) will now use a predefined
|
||||||
|
|
@ -1611,7 +1666,7 @@ changes:
|
||||||
-->
|
-->
|
||||||
|
|
||||||
* `value` {any}
|
* `value` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Tests if `value` is truthy. It is equivalent to
|
Tests if `value` is truthy. It is equivalent to
|
||||||
`assert.equal(!!value, true, message)`.
|
`assert.equal(!!value, true, message)`.
|
||||||
|
|
@ -1844,6 +1899,9 @@ argument gets considered.
|
||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v0.1.21
|
added: v0.1.21
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/58849
|
||||||
|
description: Message may now be a `printf`-like format string or function.
|
||||||
- version: v10.0.0
|
- version: v10.0.0
|
||||||
pr-url: https://github.com/nodejs/node/pull/17003
|
pr-url: https://github.com/nodejs/node/pull/17003
|
||||||
description: Used comparison changed from Strict Equality to `Object.is()`.
|
description: Used comparison changed from Strict Equality to `Object.is()`.
|
||||||
|
|
@ -1851,7 +1909,14 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function} Postfix `printf`-like arguments in case
|
||||||
|
it's used as format string.
|
||||||
|
If message is a function, it is called in case of a comparison failure. The
|
||||||
|
function receives the `actual` and `expected` arguments and has to return a
|
||||||
|
string that is going to be used as error message.
|
||||||
|
`printf`-like format strings and functions are beneficial for performance
|
||||||
|
reasons in case arguments are passed through. In addition, it allows nice
|
||||||
|
formatting with ease.
|
||||||
|
|
||||||
Tests strict equality between the `actual` and `expected` parameters as
|
Tests strict equality between the `actual` and `expected` parameters as
|
||||||
determined by [`Object.is()`][].
|
determined by [`Object.is()`][].
|
||||||
|
|
@ -1880,8 +1945,17 @@ const oranges = 2;
|
||||||
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
|
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
|
||||||
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
||||||
|
|
||||||
|
assert.strictEqual(apples, oranges, 'apples %s !== oranges %s', apples, oranges);
|
||||||
|
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
||||||
|
|
||||||
assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
|
assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
|
||||||
// TypeError: Inputs are not identical
|
// TypeError: Inputs are not identical
|
||||||
|
|
||||||
|
assert.strictEqual(apples, oranges, (actual, expected) => {
|
||||||
|
// Do 'heavy' computations
|
||||||
|
return `I expected ${expected} but I got ${actual}`;
|
||||||
|
});
|
||||||
|
// AssertionError [ERR_ASSERTION]: I expected oranges but I got apples
|
||||||
```
|
```
|
||||||
|
|
||||||
```cjs
|
```cjs
|
||||||
|
|
@ -1908,8 +1982,17 @@ const oranges = 2;
|
||||||
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
|
assert.strictEqual(apples, oranges, `apples ${apples} !== oranges ${oranges}`);
|
||||||
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
||||||
|
|
||||||
|
assert.strictEqual(apples, oranges, 'apples %s !== oranges %s', apples, oranges);
|
||||||
|
// AssertionError [ERR_ASSERTION]: apples 1 !== oranges 2
|
||||||
|
|
||||||
assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
|
assert.strictEqual(1, '1', new TypeError('Inputs are not identical'));
|
||||||
// TypeError: Inputs are not identical
|
// TypeError: Inputs are not identical
|
||||||
|
|
||||||
|
assert.strictEqual(apples, oranges, (actual, expected) => {
|
||||||
|
// Do 'heavy' computations
|
||||||
|
return `I expected ${expected} but I got ${actual}`;
|
||||||
|
});
|
||||||
|
// AssertionError [ERR_ASSERTION]: I expected oranges but I got apples
|
||||||
```
|
```
|
||||||
|
|
||||||
If the values are not strictly equal, an [`AssertionError`][] is thrown with a
|
If the values are not strictly equal, an [`AssertionError`][] is thrown with a
|
||||||
|
|
@ -2295,7 +2378,7 @@ changes:
|
||||||
|
|
||||||
* `actual` {any}
|
* `actual` {any}
|
||||||
* `expected` {any}
|
* `expected` {any}
|
||||||
* `message` {string|Error}
|
* `message` {string|Error|Function}
|
||||||
|
|
||||||
Tests for partial deep equality between the `actual` and `expected` parameters.
|
Tests for partial deep equality between the `actual` and `expected` parameters.
|
||||||
"Deep" equality means that the enumerable "own" properties of child objects
|
"Deep" equality means that the enumerable "own" properties of child objects
|
||||||
|
|
@ -2460,5 +2543,6 @@ assert.partialDeepStrictEqual(
|
||||||
[`assert.strictEqual()`]: #assertstrictequalactual-expected-message
|
[`assert.strictEqual()`]: #assertstrictequalactual-expected-message
|
||||||
[`assert.throws()`]: #assertthrowsfn-error-message
|
[`assert.throws()`]: #assertthrowsfn-error-message
|
||||||
[`getColorDepth()`]: tty.md#writestreamgetcolordepthenv
|
[`getColorDepth()`]: tty.md#writestreamgetcolordepthenv
|
||||||
|
[`util.format()`]: util.md#utilformatformat-args
|
||||||
[enumerable "own" properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
|
[enumerable "own" properties]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
|
||||||
[prototype-spec]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
|
[prototype-spec]: https://tc39.github.io/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ const {
|
||||||
isRegExp,
|
isRegExp,
|
||||||
} = require('internal/util/types');
|
} = require('internal/util/types');
|
||||||
const { isError, setOwnProperty } = require('internal/util');
|
const { isError, setOwnProperty } = require('internal/util');
|
||||||
const { innerOk } = require('internal/assert/utils');
|
const { innerOk, innerFail } = require('internal/assert/utils');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
validateFunction,
|
validateFunction,
|
||||||
|
|
@ -143,12 +143,6 @@ function Assert(options) {
|
||||||
// they lose their `this` context and will use default behavior instead of the
|
// they lose their `this` context and will use default behavior instead of the
|
||||||
// instance's custom options.
|
// instance's custom options.
|
||||||
|
|
||||||
function innerFail(obj) {
|
|
||||||
if (obj.message instanceof Error) throw obj.message;
|
|
||||||
|
|
||||||
throw new AssertionError(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throws an AssertionError with the given message.
|
* Throws an AssertionError with the given message.
|
||||||
* @param {any | Error} [message]
|
* @param {any | Error} [message]
|
||||||
|
|
@ -189,7 +183,7 @@ assert.AssertionError = AssertionError;
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function assert(...args) {
|
function assert(...args) {
|
||||||
innerOk(assert, args.length, ...args);
|
innerOk(assert, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -200,17 +194,17 @@ function assert(...args) {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.ok = function ok(...args) {
|
Assert.prototype.ok = function ok(...args) {
|
||||||
innerOk(ok, args.length, ...args);
|
innerOk(ok, ...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The equality assertion tests shallow, coercive equality with ==.
|
* The equality assertion tests shallow, coercive equality with ==.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.equal = function equal(actual, expected, message) {
|
Assert.prototype.equal = function equal(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -232,10 +226,10 @@ Assert.prototype.equal = function equal(actual, expected, message) {
|
||||||
* equal with !=.
|
* equal with !=.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.notEqual = function notEqual(actual, expected, message) {
|
Assert.prototype.notEqual = function notEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -256,10 +250,10 @@ Assert.prototype.notEqual = function notEqual(actual, expected, message) {
|
||||||
* The deep equivalence assertion tests a deep equality relation.
|
* The deep equivalence assertion tests a deep equality relation.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.deepEqual = function deepEqual(actual, expected, message) {
|
Assert.prototype.deepEqual = function deepEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -280,10 +274,10 @@ Assert.prototype.deepEqual = function deepEqual(actual, expected, message) {
|
||||||
* The deep non-equivalence assertion tests for any deep inequality.
|
* The deep non-equivalence assertion tests for any deep inequality.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.notDeepEqual = function notDeepEqual(actual, expected, message) {
|
Assert.prototype.notDeepEqual = function notDeepEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -305,10 +299,10 @@ Assert.prototype.notDeepEqual = function notDeepEqual(actual, expected, message)
|
||||||
* relation.
|
* relation.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
Assert.prototype.deepStrictEqual = function deepStrictEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -330,11 +324,11 @@ Assert.prototype.deepStrictEqual = function deepStrictEqual(actual, expected, me
|
||||||
* inequality.
|
* inequality.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.notDeepStrictEqual = notDeepStrictEqual;
|
Assert.prototype.notDeepStrictEqual = notDeepStrictEqual;
|
||||||
function notDeepStrictEqual(actual, expected, message) {
|
function notDeepStrictEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -355,10 +349,10 @@ function notDeepStrictEqual(actual, expected, message) {
|
||||||
* The strict equivalence assertion tests a strict equality relation.
|
* The strict equivalence assertion tests a strict equality relation.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.strictEqual = function strictEqual(actual, expected, message) {
|
Assert.prototype.strictEqual = function strictEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -378,10 +372,10 @@ Assert.prototype.strictEqual = function strictEqual(actual, expected, message) {
|
||||||
* The strict non-equivalence assertion tests for any strict inequality.
|
* The strict non-equivalence assertion tests for any strict inequality.
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.notStrictEqual = function notStrictEqual(actual, expected, message) {
|
Assert.prototype.notStrictEqual = function notStrictEqual(actual, expected, ...message) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
}
|
}
|
||||||
|
|
@ -401,13 +395,13 @@ Assert.prototype.notStrictEqual = function notStrictEqual(actual, expected, mess
|
||||||
* The strict equivalence assertion test between two objects
|
* The strict equivalence assertion test between two objects
|
||||||
* @param {any} actual
|
* @param {any} actual
|
||||||
* @param {any} expected
|
* @param {any} expected
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.partialDeepStrictEqual = function partialDeepStrictEqual(
|
Assert.prototype.partialDeepStrictEqual = function partialDeepStrictEqual(
|
||||||
actual,
|
actual,
|
||||||
expected,
|
expected,
|
||||||
message,
|
...message
|
||||||
) {
|
) {
|
||||||
if (arguments.length < 2) {
|
if (arguments.length < 2) {
|
||||||
throw new ERR_MISSING_ARGS('actual', 'expected');
|
throw new ERR_MISSING_ARGS('actual', 'expected');
|
||||||
|
|
@ -464,7 +458,7 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
|
||||||
innerFail({
|
innerFail({
|
||||||
actual,
|
actual,
|
||||||
expected,
|
expected,
|
||||||
message,
|
message: [message],
|
||||||
operator: fn.name,
|
operator: fn.name,
|
||||||
stackStartFn: fn,
|
stackStartFn: fn,
|
||||||
diff: this?.[kOptions]?.diff,
|
diff: this?.[kOptions]?.diff,
|
||||||
|
|
@ -666,7 +660,7 @@ function expectsError(stackStartFn, actual, error, message) {
|
||||||
actual: undefined,
|
actual: undefined,
|
||||||
expected: error,
|
expected: error,
|
||||||
operator: stackStartFn.name,
|
operator: stackStartFn.name,
|
||||||
message: `Missing expected ${fnType}${details}`,
|
message: [`Missing expected ${fnType}${details}`],
|
||||||
stackStartFn,
|
stackStartFn,
|
||||||
diff: this?.[kOptions]?.diff,
|
diff: this?.[kOptions]?.diff,
|
||||||
});
|
});
|
||||||
|
|
@ -715,8 +709,8 @@ function expectsNoError(stackStartFn, actual, error, message) {
|
||||||
actual,
|
actual,
|
||||||
expected: error,
|
expected: error,
|
||||||
operator: stackStartFn.name,
|
operator: stackStartFn.name,
|
||||||
message: `Got unwanted ${fnType}${details}\n` +
|
message: [`Got unwanted ${fnType}${details}\n` +
|
||||||
`Actual message: "${actual?.message}"`,
|
`Actual message: "${actual?.message}"`],
|
||||||
stackStartFn,
|
stackStartFn,
|
||||||
diff: this?.[kOptions]?.diff,
|
diff: this?.[kOptions]?.diff,
|
||||||
});
|
});
|
||||||
|
|
@ -834,30 +828,26 @@ function internalMatch(string, regexp, message, fn) {
|
||||||
const match = fn === Assert.prototype.match;
|
const match = fn === Assert.prototype.match;
|
||||||
if (typeof string !== 'string' ||
|
if (typeof string !== 'string' ||
|
||||||
RegExpPrototypeExec(regexp, string) !== null !== match) {
|
RegExpPrototypeExec(regexp, string) !== null !== match) {
|
||||||
if (message instanceof Error) {
|
|
||||||
throw message;
|
|
||||||
}
|
|
||||||
|
|
||||||
const generatedMessage = !message;
|
const generatedMessage = message.length === 0;
|
||||||
|
|
||||||
// 'The input was expected to not match the regular expression ' +
|
// 'The input was expected to not match the regular expression ' +
|
||||||
message ||= (typeof string !== 'string' ?
|
message[0] ||= (typeof string !== 'string' ?
|
||||||
'The "string" argument must be of type string. Received type ' +
|
'The "string" argument must be of type string. Received type ' +
|
||||||
`${typeof string} (${inspect(string)})` :
|
`${typeof string} (${inspect(string)})` :
|
||||||
(match ?
|
(match ?
|
||||||
'The input did not match the regular expression ' :
|
'The input did not match the regular expression ' :
|
||||||
'The input was expected to not match the regular expression ') +
|
'The input was expected to not match the regular expression ') +
|
||||||
`${inspect(regexp)}. Input:\n\n${inspect(string)}\n`);
|
`${inspect(regexp)}. Input:\n\n${inspect(string)}\n`);
|
||||||
const err = new AssertionError({
|
innerFail({
|
||||||
actual: string,
|
actual: string,
|
||||||
expected: regexp,
|
expected: regexp,
|
||||||
message,
|
message,
|
||||||
operator: fn.name,
|
operator: fn.name,
|
||||||
stackStartFn: fn,
|
stackStartFn: fn,
|
||||||
diff: this?.[kOptions]?.diff,
|
diff: this?.[kOptions]?.diff,
|
||||||
|
generatedMessage: generatedMessage,
|
||||||
});
|
});
|
||||||
err.generatedMessage = generatedMessage;
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -865,10 +855,10 @@ function internalMatch(string, regexp, message, fn) {
|
||||||
* Expects the `string` input to match the regular expression.
|
* Expects the `string` input to match the regular expression.
|
||||||
* @param {string} string
|
* @param {string} string
|
||||||
* @param {RegExp} regexp
|
* @param {RegExp} regexp
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.match = function match(string, regexp, message) {
|
Assert.prototype.match = function match(string, regexp, ...message) {
|
||||||
internalMatch(string, regexp, message, match);
|
internalMatch(string, regexp, message, match);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -876,10 +866,10 @@ Assert.prototype.match = function match(string, regexp, message) {
|
||||||
* Expects the `string` input not to match the regular expression.
|
* Expects the `string` input not to match the regular expression.
|
||||||
* @param {string} string
|
* @param {string} string
|
||||||
* @param {RegExp} regexp
|
* @param {RegExp} regexp
|
||||||
* @param {string | Error} [message]
|
* @param {string | Error | MessageFactory} [message]
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
Assert.prototype.doesNotMatch = function doesNotMatch(string, regexp, message) {
|
Assert.prototype.doesNotMatch = function doesNotMatch(string, regexp, ...message) {
|
||||||
internalMatch(string, regexp, message, doesNotMatch);
|
internalMatch(string, regexp, message, doesNotMatch);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -889,7 +879,7 @@ Assert.prototype.doesNotMatch = function doesNotMatch(string, regexp, message) {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function strict(...args) {
|
function strict(...args) {
|
||||||
innerOk(strict, args.length, ...args);
|
innerOk(strict, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayPrototypeForEach([
|
ArrayPrototypeForEach([
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,21 @@
|
||||||
const {
|
const {
|
||||||
Error,
|
Error,
|
||||||
ErrorCaptureStackTrace,
|
ErrorCaptureStackTrace,
|
||||||
|
ErrorPrototypeToString,
|
||||||
StringPrototypeCharCodeAt,
|
StringPrototypeCharCodeAt,
|
||||||
StringPrototypeReplace,
|
StringPrototypeReplace,
|
||||||
} = primordials;
|
} = primordials;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
codes: {
|
||||||
|
ERR_AMBIGUOUS_ARGUMENT,
|
||||||
|
ERR_INVALID_ARG_TYPE,
|
||||||
|
},
|
||||||
isErrorStackTraceLimitWritable,
|
isErrorStackTraceLimitWritable,
|
||||||
} = require('internal/errors');
|
} = require('internal/errors');
|
||||||
const AssertionError = require('internal/assert/assertion_error');
|
const AssertionError = require('internal/assert/assertion_error');
|
||||||
const { isError } = require('internal/util');
|
const { isError } = require('internal/util');
|
||||||
|
const { format } = require('internal/util/inspect');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
getErrorSourceExpression,
|
getErrorSourceExpression,
|
||||||
|
|
@ -33,6 +39,43 @@ const meta = [
|
||||||
|
|
||||||
const escapeFn = (str) => meta[StringPrototypeCharCodeAt(str, 0)];
|
const escapeFn = (str) => meta[StringPrototypeCharCodeAt(str, 0)];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function that derives the failure message from the actual and expected values.
|
||||||
|
* It is invoked only when the assertion fails.
|
||||||
|
*
|
||||||
|
* Other return values than a string are ignored.
|
||||||
|
* @callback MessageFactory
|
||||||
|
* @param {any} actual
|
||||||
|
* @param {any} expected
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw message input is always passed internally as a tuple array.
|
||||||
|
* Accepted shapes:
|
||||||
|
* - []
|
||||||
|
* - [string]
|
||||||
|
* - [string, ...any[]] (printf-like substitutions)
|
||||||
|
* - [Error]
|
||||||
|
* - [MessageFactory]
|
||||||
|
*
|
||||||
|
* Additional elements after [Error] or [MessageFactory] are rejected with ERR_AMBIGUOUS_ARGUMENT.
|
||||||
|
* A first element that is neither string, Error nor function is rejected with ERR_INVALID_ARG_TYPE.
|
||||||
|
* @typedef {[] | [string] | [string, ...any[]] | [Error] | [MessageFactory]} MessageTuple
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options consumed by innerFail to construct and throw the AssertionError.
|
||||||
|
* @typedef {object} InnerFailOptions
|
||||||
|
* @property {any} actual Actual value
|
||||||
|
* @property {any} expected Expected value
|
||||||
|
* @property {MessageTuple} message Message
|
||||||
|
* @property {string} operator Operator
|
||||||
|
* @property {Function} stackStartFn Stack start function
|
||||||
|
* @property {'simple' | 'full'} [diff] Diff mode
|
||||||
|
* @property {boolean} [generatedMessage] Generated message
|
||||||
|
*/
|
||||||
|
|
||||||
function getErrMessage(fn) {
|
function getErrMessage(fn) {
|
||||||
const tmpLimit = Error.stackTraceLimit;
|
const tmpLimit = Error.stackTraceLimit;
|
||||||
const errorStackTraceLimitIsWritable = isErrorStackTraceLimitWritable();
|
const errorStackTraceLimitIsWritable = isErrorStackTraceLimitWritable();
|
||||||
|
|
@ -52,32 +95,89 @@ function getErrMessage(fn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function innerOk(fn, argLen, value, message) {
|
/**
|
||||||
if (!value) {
|
* @param {InnerFailOptions} obj
|
||||||
let generatedMessage = false;
|
*/
|
||||||
|
function innerFail(obj) {
|
||||||
if (argLen === 0) {
|
if (obj.message.length === 0) {
|
||||||
generatedMessage = true;
|
obj.message = undefined;
|
||||||
message = 'No value argument passed to `assert.ok()`';
|
} else if (typeof obj.message[0] === 'string') {
|
||||||
} else if (message == null) {
|
if (obj.message.length > 1) {
|
||||||
generatedMessage = true;
|
obj.message = format(...obj.message);
|
||||||
message = getErrMessage(fn);
|
} else {
|
||||||
} else if (isError(message)) {
|
obj.message = obj.message[0];
|
||||||
throw message;
|
}
|
||||||
|
} else if (isError(obj.message[0])) {
|
||||||
|
if (obj.message.length > 1) {
|
||||||
|
throw new ERR_AMBIGUOUS_ARGUMENT(
|
||||||
|
'message',
|
||||||
|
`The error message was passed as error object "${ErrorPrototypeToString(obj.message[0])}" has trailing arguments that would be ignored.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
throw obj.message[0];
|
||||||
|
} else if (typeof obj.message[0] === 'function') {
|
||||||
|
if (obj.message.length > 1) {
|
||||||
|
throw new ERR_AMBIGUOUS_ARGUMENT(
|
||||||
|
'message',
|
||||||
|
`The error message with function "${obj.message[0].name || 'anonymous'}" has trailing arguments that would be ignored.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
obj.message = obj.message[0](obj.actual, obj.expected);
|
||||||
|
if (typeof obj.message !== 'string') {
|
||||||
|
obj.message = undefined;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Ignore and use default message instead
|
||||||
|
obj.message = undefined;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new ERR_INVALID_ARG_TYPE(
|
||||||
|
'message',
|
||||||
|
['string', 'function'],
|
||||||
|
obj.message[0],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const err = new AssertionError({
|
const error = new AssertionError(obj);
|
||||||
actual: value,
|
if (obj.generatedMessage !== undefined) {
|
||||||
|
error.generatedMessage = obj.generatedMessage;
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal ok handler delegating to innerFail for message handling.
|
||||||
|
* @param {Function} fn
|
||||||
|
* @param {...any} args
|
||||||
|
*/
|
||||||
|
function innerOk(fn, ...args) {
|
||||||
|
if (!args[0]) {
|
||||||
|
let generatedMessage = false;
|
||||||
|
let messageArgs;
|
||||||
|
|
||||||
|
if (args.length === 0) {
|
||||||
|
generatedMessage = true;
|
||||||
|
messageArgs = ['No value argument passed to `assert.ok()`'];
|
||||||
|
} else if (args.length === 1 || args[1] == null) {
|
||||||
|
generatedMessage = true;
|
||||||
|
messageArgs = [getErrMessage(fn)];
|
||||||
|
} else {
|
||||||
|
messageArgs = args.slice(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
innerFail({
|
||||||
|
actual: args[0],
|
||||||
expected: true,
|
expected: true,
|
||||||
message,
|
message: messageArgs,
|
||||||
operator: '==',
|
operator: '==',
|
||||||
stackStartFn: fn,
|
stackStartFn: fn,
|
||||||
|
generatedMessage,
|
||||||
});
|
});
|
||||||
err.generatedMessage = generatedMessage;
|
|
||||||
throw err;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
innerOk,
|
innerOk,
|
||||||
|
innerFail,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -333,7 +333,7 @@ class TestContext {
|
||||||
if (plan !== null) {
|
if (plan !== null) {
|
||||||
plan.count();
|
plan.count();
|
||||||
}
|
}
|
||||||
innerOk(ok, args.length, ...args);
|
innerOk(ok, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.ok = ok;
|
assert.ok = ok;
|
||||||
|
|
|
||||||
4
test/fixtures/errors/error_exit.snapshot
vendored
4
test/fixtures/errors/error_exit.snapshot
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
Exiting with code=1
|
Exiting with code=1
|
||||||
node:assert:*
|
node:internal*assert*utils:*
|
||||||
throw new AssertionError(obj);
|
throw error;
|
||||||
^
|
^
|
||||||
|
|
||||||
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
|
||||||
|
|
|
||||||
|
|
@ -904,10 +904,9 @@ test('Additional asserts', () => {
|
||||||
assert.throws(
|
assert.throws(
|
||||||
() => assert(false, Symbol('foo')),
|
() => assert(false, Symbol('foo')),
|
||||||
{
|
{
|
||||||
code: 'ERR_ASSERTION',
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
constructor: assert.AssertionError,
|
constructor: TypeError,
|
||||||
generatedMessage: false,
|
message: /"message" argument.+Symbol\(foo\)/
|
||||||
message: 'Symbol(foo)'
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -1595,5 +1594,188 @@ test('assert/strict exists', () => {
|
||||||
assert.strictEqual(require('assert/strict'), assert.strict);
|
assert.strictEqual(require('assert/strict'), assert.strict);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Printf-like format strings as error message', () => {
|
||||||
|
assert.throws(
|
||||||
|
() => assert.equal(1, 2, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.strictEqual(1, 2, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notEqual(1, 1, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notStrictEqual(1, 1, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.deepEqual(1, 2, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notDeepEqual(1, 1, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.deepStrictEqual(1, 2, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notDeepStrictEqual(1, 1, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.partialDeepStrictEqual(1, 2, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.match('foo', /bar/, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, 'The answer to all questions is %i', 42),
|
||||||
|
/The answer to all questions is 42/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Functions as error message', () => {
|
||||||
|
function errorMessage(actual, expected) {
|
||||||
|
return `Nice message including ${actual} and ${expected}`;
|
||||||
|
}
|
||||||
|
assert.throws(
|
||||||
|
() => assert.equal(1, 2, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 2' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.strictEqual(1, 2, errorMessage),
|
||||||
|
// TODO(BridgeAR): Align input arguments with generated message for all
|
||||||
|
// methods.
|
||||||
|
// TODO(BridgeAR): Check how to handle this for custom messages. Do
|
||||||
|
// we need this? Should it be skipped for methods like these?
|
||||||
|
{ message: 'Nice message including 1 and 2\n\n1 !== 2\n' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notEqual(1, 1, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 1' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notStrictEqual(1, 1, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 1' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.deepEqual(1, 2, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 2' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notDeepEqual(1, 1, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 1' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.deepStrictEqual(1, 2, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 2\n\n1 !== 2\n' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.notDeepStrictEqual(1, 1, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 1' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.partialDeepStrictEqual(1, 2, errorMessage),
|
||||||
|
{ message: 'Nice message including 1 and 2\n\n1 !== 2\n' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.match('foo', /bar/, errorMessage),
|
||||||
|
{ message: 'Nice message including foo and /bar/' }
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, errorMessage),
|
||||||
|
{ message: 'Nice message including foo and /foo/' }
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Ambiguous error messages fail', () => {
|
||||||
|
function errorMessage(actual, expected) {
|
||||||
|
return `Nice message including ${actual} and ${expected}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, errorMessage, 'foobar'),
|
||||||
|
{
|
||||||
|
code: 'ERR_AMBIGUOUS_ARGUMENT',
|
||||||
|
message: /errorMessage/
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, new Error('baz'), 'foobar'),
|
||||||
|
{
|
||||||
|
code: 'ERR_AMBIGUOUS_ARGUMENT',
|
||||||
|
message: /baz/
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Faulty message functions', () => {
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, (a, b) => 123),
|
||||||
|
{
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
message: "'foo' doesNotMatch /foo/"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.match('foo', /123/, (a, b) => { new Error('baz'); }),
|
||||||
|
{
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
message: "'foo' match /123/"
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Functions as error message', () => {
|
||||||
|
function errorMessage(actual, expected) {
|
||||||
|
return `Nice message including ${actual} and ${expected}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.equal('foo', 'bar', errorMessage),
|
||||||
|
{
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
message: /Nice message including foo and bar/
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.throws(
|
||||||
|
() => assert.doesNotMatch('foo', /foo/, errorMessage),
|
||||||
|
{
|
||||||
|
code: 'ERR_ASSERTION',
|
||||||
|
message: /Nice message including foo and \/foo\//
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
/* eslint-enable no-restricted-syntax */
|
/* eslint-enable no-restricted-syntax */
|
||||||
/* eslint-enable no-restricted-properties */
|
/* eslint-enable no-restricted-properties */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user