Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: improve assert docs #20313

Closed
wants to merge 4 commits into from
Closed
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 100 additions & 53 deletions doc/api/assert.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -319,43 +313,67 @@ 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:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the ERR_ASSERTION part in some cases because the line length would otherwise be above 80 characters.

// + expected - actual
// {
// - a: 1
// + a: '1'
// }

// The following objects don't have own properties
const date = new Date();
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([[{}, {}]]);
Expand All @@ -364,8 +382,16 @@ weakMap3.unequal = true;

assert.deepStrictEqual(weakMap1, weakMap2);
// OK, because it is impossible to compare the entries

// Fail because weakMap3 has a property that weakMap1 does not contain:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fail -> Fails? (Ignore if this is a noun)

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`
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`ifError` -> `ifError()`?

`ifError` itself. See below for an example.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`ifError` -> `ifError()`?


```js
const assert = require('assert').strict;
Expand All @@ -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])
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`assert.ok()` ?

Copy link
Contributor

@vsemozhetbyt vsemozhetbyt Apr 26, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO for another PR: unify parentheses in notStrictEqual above and check other cases?


assert.ok(false, 'it\'s false');
// throws "AssertionError: it's false"
// AssertionError: it's false"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: remove "


// 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)
```
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -1106,9 +1147,10 @@ assert.throws(

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
Expand All @@ -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');
Expand All @@ -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)
```
Expand Down