doc: improve assert docs

This improves the error example output by reflecting the current
state. It also makes sure the examples are up to date in general.
`assert.throws` clarified the `ERR_AMBIGUOUS_ARGUMENT` error.

PR-URL: https://github.com/nodejs/node/pull/20313
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
This commit is contained in:
Ruben Bridgewater 2018-04-26 03:06:10 +02:00
parent 8a0fb137d8
commit 655430179f
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762

View File

@ -102,31 +102,25 @@ It can be accessed using:
const assert = require('assert').strict;
```
Example error diff (the `expected`, `actual`, and `Lines skipped` will be on a
single row):
Example error diff:
```js
const assert = require('assert').strict;
assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
```
```diff
AssertionError [ERR_ASSERTION]: Input A expected to deepStrictEqual input B:
+ expected
- actual
... Lines skipped
[
[
...
2,
- 3
+ '3'
],
...
5
]
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual ... Lines skipped
//
// [
// [
// ...
// 2,
// - 3
// + '3'
// ],
// ...
// 5
// ]
```
To deactivate the colors, use the `NODE_DISABLE_COLORS` environment variable.
@ -319,9 +313,14 @@ are recursively evaluated also by the following rules.
```js
const assert = require('assert').strict;
// This fails because 1 !== '1'.
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// AssertionError: { a: 1 } deepStrictEqual { a: '1' }
// because 1 !== '1' using SameValue comparison
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// {
// - a: 1
// + a: '1'
// }
// The following objects don't have own properties
const date = new Date();
@ -329,33 +328,52 @@ const object = {};
const fakeDate = {};
Object.setPrototypeOf(fakeDate, Date.prototype);
// Different [[Prototype]]:
assert.deepStrictEqual(object, fakeDate);
// AssertionError: {} deepStrictEqual Date {}
// Different [[Prototype]]
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - {}
// + Date {}
// Different type tags:
assert.deepStrictEqual(date, fakeDate);
// AssertionError: 2017-03-11T14:25:31.849Z deepStrictEqual Date {}
// Different type tags
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 2018-04-26T00:49:08.604Z
// + Date {}
assert.deepStrictEqual(NaN, NaN);
// OK, because of the SameValue comparison
// Different unwrapped numbers:
assert.deepStrictEqual(new Number(1), new Number(2));
// Fails because the wrapped number is unwrapped and compared as well.
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - [Number: 1]
// + [Number: 2]
assert.deepStrictEqual(new String('foo'), Object('foo'));
// OK because the object and the string are identical when unwrapped.
assert.deepStrictEqual(-0, -0);
// OK
// Different zeros using the SameValue Comparison:
assert.deepStrictEqual(0, -0);
// AssertionError: 0 deepStrictEqual -0
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 0
// + -0
const symbol1 = Symbol();
const symbol2 = Symbol();
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol1]: 1 });
// OK, because it is the same symbol on both objects.
assert.deepStrictEqual({ [symbol1]: 1 }, { [symbol2]: 1 });
// Fails because symbol1 !== symbol2!
// AssertionError [ERR_ASSERTION]: Input objects not identical:
// {
// [Symbol()]: 1
// }
const weakMap1 = new WeakMap();
const weakMap2 = new WeakMap([[{}, {}]]);
@ -364,8 +382,16 @@ weakMap3.unequal = true;
assert.deepStrictEqual(weakMap1, weakMap2);
// OK, because it is impossible to compare the entries
// Fails because weakMap3 has a property that weakMap1 does not contain:
assert.deepStrictEqual(weakMap1, weakMap3);
// Fails because weakMap3 has a property that weakMap1 does not contain!
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// WeakMap {
// - [items unknown]
// + [items unknown],
// + unequal: true
// }
```
If the values are not equal, an `AssertionError` is thrown with a `message`
@ -639,7 +665,9 @@ changes:
* `value` {any}
Throws `value` if `value` is not `undefined` or `null`. This is useful when
testing the `error` argument in callbacks.
testing the `error` argument in callbacks. The stack trace contains all frames
from the error passed to `ifError()` including the potential new frames for
`ifError()` itself. See below for an example.
```js
const assert = require('assert').strict;
@ -652,6 +680,19 @@ assert.ifError('error');
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 'error'
assert.ifError(new Error());
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error
// Create some random error frames.
let err;
(function errorFrame() {
err = new Error('test error');
})();
(function ifErrorFrame() {
assert.ifError(err);
})();
// AssertionError [ERR_ASSERTION]: ifError got unwanted exception: test error
// at ifErrorFrame
// at errorFrame
```
## assert.notDeepEqual(actual, expected[, message])
@ -834,7 +875,7 @@ assert.notStrictEqual(1, 2);
// OK
assert.notStrictEqual(1, 1);
// AssertionError: 1 notStrictEqual 1
// AssertionError [ERR_ASSERTION]: Identical input passed to notStrictEqual: 1
assert.notStrictEqual(1, '1');
// OK
@ -880,40 +921,34 @@ assert.ok(1);
// OK
assert.ok();
// throws:
// "AssertionError: No value argument passed to `assert.ok`.
// AssertionError: No value argument passed to `assert.ok()`
assert.ok(false, 'it\'s false');
// throws "AssertionError: it's false"
// AssertionError: it's false
// In the repl:
assert.ok(typeof 123 === 'string');
// throws:
// "AssertionError: false == true
// AssertionError: false == true
// In a file (e.g. test.js):
assert.ok(typeof 123 === 'string');
// throws:
// "AssertionError: The expression evaluated to a falsy value:
// AssertionError: The expression evaluated to a falsy value:
//
// assert.ok(typeof 123 === 'string')
assert.ok(false);
// throws:
// "AssertionError: The expression evaluated to a falsy value:
// AssertionError: The expression evaluated to a falsy value:
//
// assert.ok(false)
assert.ok(0);
// throws:
// "AssertionError: The expression evaluated to a falsy value:
// AssertionError: The expression evaluated to a falsy value:
//
// assert.ok(0)
// Using `assert()` works the same:
assert(0);
// throws:
// "AssertionError: The expression evaluated to a falsy value:
// AssertionError: The expression evaluated to a falsy value:
//
// assert(0)
```
@ -995,13 +1030,19 @@ determined by the [SameValue Comparison][].
const assert = require('assert').strict;
assert.strictEqual(1, 2);
// AssertionError: 1 strictEqual 2
// AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + 2
assert.strictEqual(1, 1);
// OK
assert.strictEqual(1, '1');
// AssertionError: 1 strictEqual '1'
// AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + '1'
```
If the values are not strictly equal, an `AssertionError` is thrown with a
@ -1035,6 +1076,34 @@ each property will be tested for including the non-enumerable `message` and
If specified, `message` will be the message provided by the `AssertionError` if
the block fails to throw.
Custom error object / error instance:
```js
const err = new TypeError('Wrong value');
err.code = 404;
assert.throws(
() => {
throw err;
},
{
name: 'TypeError',
message: 'Wrong value'
// Note that only properties on the error object will be tested!
}
);
// Fails due to the different `message` and `name` properties:
assert.throws(
() => {
const otherErr = new Error('Not found');
otherErr.code = 404;
throw otherErr;
},
err // This tests for `message`, `name` and `code`.
);
```
Validate instanceof using constructor:
```js
@ -1076,39 +1145,12 @@ assert.throws(
);
```
Custom error object / error instance:
```js
const err = new TypeError('Wrong value');
err.code = 404;
assert.throws(
() => {
throw err;
},
{
name: 'TypeError',
message: 'Wrong value'
// Note that only properties on the error object will be tested!
}
);
// Fails due to the different `message` and `name` properties:
assert.throws(
() => {
const otherErr = new Error('Not found');
otherErr.code = 404;
throw otherErr;
},
err // This tests for `message`, `name` and `code`.
);
```
Note that `error` cannot be a string. If a string is provided as the second
argument, then `error` is assumed to be omitted and the string will be used for
`message` instead. This can lead to easy-to-miss mistakes. Please read the
example below carefully if using a string as the second argument gets
considered:
`message` instead. This can lead to easy-to-miss mistakes. Using the same
message as the thrown error message is going to result in an
`ERR_AMBIGUOUS_ARGUMENT` error. Please read the example below carefully if using
a string as the second argument gets considered:
<!-- eslint-disable no-restricted-syntax -->
```js
@ -1121,10 +1163,15 @@ function throwingSecond() {
function notThrowing() {}
// The second argument is a string and the input function threw an Error.
// In that case both cases do not throw as neither is going to try to
// match for the error message thrown by the input function!
// The first case will not throw as it does not match for the error message
// thrown by the input function!
assert.throws(throwingFirst, 'Second');
// In the next example the message has no benefit over the message from the
// error and since it is not clear if the user intended to actually match
// against the error message, Node.js thrown an `ERR_AMBIGUOUS_ARGUMENT` error.
assert.throws(throwingSecond, 'Second');
// Throws an error:
// TypeError [ERR_AMBIGUOUS_ARGUMENT]
// The string is only used (as message) in case the function does not throw:
assert.throws(notThrowing, 'Second');
@ -1134,7 +1181,7 @@ assert.throws(notThrowing, 'Second');
assert.throws(throwingSecond, /Second$/);
// Does not throw because the error messages match.
assert.throws(throwingFirst, /Second$/);
// Throws a error:
// Throws an error:
// Error: First
// at throwingFirst (repl:2:9)
```