assert: multiple improvements

1) Switched + / - and red / green in diffs. It seems like that style
   is more natural to most people.

2) Short primitives do not use the diff anymore. Especially short
   numbers can be read well like 1 !== 2. Cases that can not be
   displayed like that (e.g., -0 and +0) use the regular diff output.

3) Improved error descriptions. It was not always clear what the
   messages stood for. That should now be resolved.

4) Added a position indicator for single lines in case a tty is used
   and the line is shorter than the visual columns.

5) Color detection is now done by checking stderr instead of stdout.

PR-URL: https://github.com/nodejs/node/pull/21628
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
pull/22120/head
Ruben Bridgewater 2018-07-03 02:06:57 +02:00
parent a2ec80851c
commit 0518b9edf3
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
10 changed files with 281 additions and 218 deletions

View File

@ -108,15 +108,15 @@ Example error diff:
const assert = require('assert').strict;
assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual ... Lines skipped
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected ... Lines skipped
//
// [
// [
// ...
// 2,
// - 3
// + '3'
// + 3
// - '3'
// ],
// ...
// 5
@ -315,11 +315,12 @@ const assert = require('assert').strict;
// This fails because 1 !== '1'.
assert.deepStrictEqual({ a: 1 }, { a: '1' });
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// {
// - a: 1
// + a: '1'
// + a: 1
// - a: '1'
// }
// The following objects don't have own properties
@ -330,27 +331,30 @@ Object.setPrototypeOf(fakeDate, Date.prototype);
// Different [[Prototype]]:
assert.deepStrictEqual(object, fakeDate);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - {}
// + Date {}
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + {}
// - Date {}
// Different type tags:
assert.deepStrictEqual(date, fakeDate);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 2018-04-26T00:49:08.604Z
// + Date {}
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 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));
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - [Number: 1]
// + [Number: 2]
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + [Number: 1]
// - [Number: 2]
assert.deepStrictEqual(new String('foo'), Object('foo'));
// OK because the object and the string are identical when unwrapped.
@ -360,17 +364,20 @@ assert.deepStrictEqual(-0, -0);
// Different zeros using the SameValue Comparison:
assert.deepStrictEqual(0, -0);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// - 0
// + -0
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// + 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 });
// AssertionError [ERR_ASSERTION]: Input objects not identical:
// AssertionError [ERR_ASSERTION]: Inputs identical but not reference equal:
//
// {
// [Symbol()]: 1
// }
@ -385,12 +392,13 @@ assert.deepStrictEqual(weakMap1, weakMap2);
// Fails because weakMap3 has a property that weakMap1 does not contain:
assert.deepStrictEqual(weakMap1, weakMap3);
// AssertionError: Input A expected to strictly deep-equal input B:
// + expected - actual
// AssertionError: Expected inputs to be strictly deep-equal:
// + actual - expected
//
// WeakMap {
// - [items unknown]
// + [items unknown],
// + unequal: true
// + [items unknown]
// - [items unknown],
// - unequal: true
// }
```
@ -875,7 +883,9 @@ assert.notStrictEqual(1, 2);
// OK
assert.notStrictEqual(1, 1);
// AssertionError [ERR_ASSERTION]: Identical input passed to notStrictEqual: 1
// AssertionError [ERR_ASSERTION]: Expected "actual" to be strictly unequal to:
//
// 1
assert.notStrictEqual(1, '1');
// OK
@ -1031,19 +1041,20 @@ determined by the [SameValue Comparison][].
const assert = require('assert').strict;
assert.strictEqual(1, 2);
// AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + 2
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
//
// 1 !== 2
assert.strictEqual(1, 1);
// OK
assert.strictEqual(1, '1');
// AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
// + expected - actual
// - 1
// + '1'
assert.strictEqual('Hello foobar', 'Hello World!');
// AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
// + actual - expected
//
// + 'Hello foobar'
// - 'Hello World!'
// ^
```
If the values are not strictly equal, an `AssertionError` is thrown with a
@ -1211,9 +1222,8 @@ function notThrowing() {}
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.
// against the error message, Node.js throws 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:
@ -1221,10 +1231,12 @@ assert.throws(notThrowing, 'Second');
// AssertionError [ERR_ASSERTION]: Missing expected exception: Second
// If it was intended to match for the error message do this instead:
// It does not throw because the error messages match.
assert.throws(throwingSecond, /Second$/);
// Does not throw because the error messages match.
// If the error message does not match, the error from within the function is
// not caught.
assert.throws(throwingFirst, /Second$/);
// Throws an error:
// Error: First
// at throwingFirst (repl:2:9)
```

View File

@ -10,13 +10,18 @@ let green = '';
let red = '';
let white = '';
const READABLE_OPERATOR = {
deepStrictEqual: 'Input A expected to strictly deep-equal input B',
notDeepStrictEqual: 'Input A expected to strictly not deep-equal input B',
strictEqual: 'Input A expected to strictly equal input B',
notStrictEqual: 'Input A expected to strictly not equal input B'
const kReadableOperator = {
deepStrictEqual: 'Expected inputs to be strictly deep-equal:',
notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:',
strictEqual: 'Expected inputs to be strictly equal:',
notStrictEqual: 'Expected "actual" to be strictly unequal to:',
notIdentical: 'Inputs identical but not reference equal:',
};
// Comparing short primitives should just show === / !== instead of using the
// diff.
const kMaxShortLength = 10;
function copyError(source) {
const keys = Object.keys(source);
const target = Object.create(Object.getPrototypeOf(source));
@ -49,22 +54,59 @@ function inspectValue(val) {
}
function createErrDiff(actual, expected, operator) {
var other = '';
var res = '';
var lastPos = 0;
var end = '';
var skipped = false;
let other = '';
let res = '';
let lastPos = 0;
let end = '';
let skipped = false;
const actualLines = inspectValue(actual);
const expectedLines = inspectValue(expected);
const msg = READABLE_OPERATOR[operator] +
`:\n${green}+ expected${white} ${red}- actual${white}`;
const msg = kReadableOperator[operator] +
`\n${green}+ actual${white} ${red}- expected${white}`;
const skippedMsg = ` ${blue}...${white} Lines skipped`;
let i = 0;
let indicator = '';
// If "actual" and "expected" fit on a single line and they are not strictly
// equal, check further special handling.
if (actualLines.length === 1 && expectedLines.length === 1 &&
actualLines[0] !== expectedLines[0]) {
const inputLength = actualLines[0].length + expectedLines[0].length;
// If the character length of "actual" and "expected" together is less than
// kMaxShortLength and if neither is an object and at least one of them is
// not `zero`, use the strict equal comparison to visualize the output.
if (inputLength <= kMaxShortLength) {
if ((typeof actual !== 'object' || actual === null) &&
(typeof expected !== 'object' || expected === null) &&
(actual !== 0 || expected !== 0)) { // -0 === +0
return `${kReadableOperator[operator]}\n\n` +
`${actualLines[0]} !== ${expectedLines[0]}\n`;
}
} else {
// If the stderr is a tty and the input length is lower than the current
// columns per line, add a mismatch indicator below the output. If it is
// not a tty, use a default value of 80 characters.
const maxLength = process.stderr.isTTY ? process.stderr.columns : 80;
if (inputLength < maxLength) {
while (actualLines[0][i] === expectedLines[0][i]) {
i++;
}
// Ignore the first characters.
if (i > 2) {
// Add position indicator for the first mismatch in case it is a
// single line and the input length is less than the column length.
indicator = `\n ${' '.repeat(i)}^`;
i = 0;
}
}
}
}
// Remove all ending lines that match (this optimizes the output for
// readability by reducing the number of total changed lines).
var a = actualLines[actualLines.length - 1];
var b = expectedLines[expectedLines.length - 1];
var i = 0;
let a = actualLines[actualLines.length - 1];
let b = expectedLines[expectedLines.length - 1];
while (a === b) {
if (i++ < 2) {
end = `\n ${a}${end}`;
@ -78,6 +120,26 @@ function createErrDiff(actual, expected, operator) {
a = actualLines[actualLines.length - 1];
b = expectedLines[expectedLines.length - 1];
}
const maxLines = Math.max(actualLines.length, expectedLines.length);
// Strict equal with identical objects that are not identical by reference.
// E.g., assert.deepStrictEqual({ a: Symbol() }, { a: Symbol() })
if (maxLines === 0) {
// We have to get the result again. The lines were all removed before.
const actualLines = inspectValue(actual);
// Only remove lines in case it makes sense to collapse those.
// TODO: Accept env to always show the full error.
if (actualLines.length > 30) {
actualLines[26] = `${blue}...${white}`;
while (actualLines.length > 27) {
actualLines.pop();
}
}
return `${kReadableOperator.notIdentical}\n\n${actualLines.join('\n')}\n`;
}
if (i > 3) {
end = `\n${blue}...${white}${end}`;
skipped = true;
@ -87,9 +149,7 @@ function createErrDiff(actual, expected, operator) {
other = '';
}
const maxLines = Math.max(actualLines.length, expectedLines.length);
var printedLines = 0;
var identical = 0;
let printedLines = 0;
for (i = 0; i < maxLines; i++) {
// Only extra expected lines exist
const cur = i - lastPos;
@ -106,7 +166,7 @@ function createErrDiff(actual, expected, operator) {
printedLines++;
}
lastPos = i;
other += `\n${green}+${white} ${expectedLines[i]}`;
other += `\n${red}-${white} ${expectedLines[i]}`;
printedLines++;
// Only extra actual lines exist
} else if (expectedLines.length < i + 1) {
@ -122,7 +182,7 @@ function createErrDiff(actual, expected, operator) {
printedLines++;
}
lastPos = i;
res += `\n${red}-${white} ${actualLines[i]}`;
res += `\n${green}+${white} ${actualLines[i]}`;
printedLines++;
// Lines diverge
} else if (actualLines[i] !== expectedLines[i]) {
@ -138,8 +198,8 @@ function createErrDiff(actual, expected, operator) {
printedLines++;
}
lastPos = i;
res += `\n${red}-${white} ${actualLines[i]}`;
other += `\n${green}+${white} ${expectedLines[i]}`;
res += `\n${green}+${white} ${actualLines[i]}`;
other += `\n${red}-${white} ${expectedLines[i]}`;
printedLines += 2;
// Lines are identical
} else {
@ -149,7 +209,6 @@ function createErrDiff(actual, expected, operator) {
res += `\n ${actualLines[i]}`;
printedLines++;
}
identical++;
}
// Inspected object to big (Show ~20 rows max)
if (printedLines > 20 && i < maxLines - 2) {
@ -158,28 +217,7 @@ function createErrDiff(actual, expected, operator) {
}
}
// Strict equal with identical objects that are not identical by reference.
if (identical === maxLines) {
// E.g., assert.deepStrictEqual(Symbol(), Symbol())
const base = operator === 'strictEqual' ?
'Input objects identical but not reference equal:' :
'Input objects not identical:';
// We have to get the result again. The lines were all removed before.
const actualLines = inspectValue(actual);
// Only remove lines in case it makes sense to collapse those.
// TODO: Accept env to always show the full error.
if (actualLines.length > 30) {
actualLines[26] = `${blue}...${white}`;
while (actualLines.length > 27) {
actualLines.pop();
}
}
return `${base}\n\n${actualLines.join('\n')}\n`;
}
return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`;
return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}${indicator}`;
}
class AssertionError extends Error {
@ -198,10 +236,10 @@ class AssertionError extends Error {
if (message != null) {
super(String(message));
} else {
if (process.stdout.isTTY) {
if (process.stderr.isTTY) {
// Reset on each call to make sure we handle dynamically set environment
// variables correct.
if (process.stdout.getColorDepth() !== 1) {
if (process.stderr.getColorDepth() !== 1) {
blue = '\u001b[34m';
green = '\u001b[32m';
white = '\u001b[39m';
@ -231,7 +269,7 @@ class AssertionError extends Error {
// In case the objects are equal but the operator requires unequal, show
// the first object and say A equals B
const res = inspectValue(actual);
const base = `Identical input passed to ${operator}:`;
const base = kReadableOperator[operator];
// Only remove lines in case it makes sense to collapse those.
// TODO: Accept env to always show the full error.

View File

@ -2,13 +2,13 @@ assert.js:*
throw err;
^
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual
AssertionError [ERR_ASSERTION]: Expected inputs to be strictly deep-equal:
+ actual - expected
- Comparison {}
+ Comparison {
+ bar: true
+ }
+ Comparison {}
- Comparison {
- bar: true
- }
at Object.<anonymous> (*assert_throws_stack.js:*:*)
at *
at *

View File

@ -3,7 +3,7 @@ punycode.js:42
^
RangeError: Invalid input
at error (punycode.js:42:*)
at error (punycode.js:42:8)
at Object.decode (punycode.js:*:*)
at Object.<anonymous> (*test*message*core_line_numbers.js:*:*)
at Module._compile (internal/modules/cjs/loader.js:*:*)

View File

@ -3,11 +3,10 @@ assert.js:*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
+ expected - actual
AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal:
1 !== 2
- 1
+ 2
at Object.<anonymous> (*test*message*error_exit.js:*:*)
at Module._compile (internal/modules/cjs/loader.js:*:*)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:*:*)

View File

@ -26,15 +26,15 @@ if (process.stdout.isTTY)
assert.throws(
() => assert.deepStrictEqual(date, fake),
{
message: 'Input A expected to strictly deep-equal input B:\n' +
'+ expected - actual\n\n- 2016-01-01T00:00:00.000Z\n+ Date {}'
message: 'Expected inputs to be strictly deep-equal:\n' +
'+ actual - expected\n\n+ 2016-01-01T00:00:00.000Z\n- Date {}'
}
);
assert.throws(
() => assert.deepStrictEqual(fake, date),
{
message: 'Input A expected to strictly deep-equal input B:\n' +
'+ expected - actual\n\n- Date {}\n+ 2016-01-01T00:00:00.000Z'
message: 'Expected inputs to be strictly deep-equal:\n' +
'+ actual - expected\n\n+ Date {}\n- 2016-01-01T00:00:00.000Z'
}
);
}

View File

@ -4,8 +4,8 @@ const common = require('../common');
const assert = require('assert');
const util = require('util');
const { AssertionError } = assert;
const defaultMsgStart = 'Input A expected to strictly deep-equal input B:\n' +
'+ expected - actual';
const defaultMsgStart = 'Expected inputs to be strictly deep-equal:\n';
const defaultMsgStartFull = `${defaultMsgStart}+ actual - expected`;
// Disable colored output to prevent color codes from breaking assertion
// message comparisons. This should only be an issue when process.stdout
@ -44,9 +44,9 @@ assert.throws(
() => assert.deepStrictEqual(arr, buf),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart} ... Lines skipped\n\n` +
'- Uint8Array [\n' +
'+ Buffer [Uint8Array] [\n 120,\n...\n 10\n ]'
message: `${defaultMsgStartFull} ... Lines skipped\n\n` +
'+ Uint8Array [\n' +
'- Buffer [Uint8Array] [\n 120,\n...\n 10\n ]'
}
);
assert.deepEqual(arr, buf);
@ -59,9 +59,9 @@ assert.deepEqual(arr, buf);
() => assert.deepStrictEqual(buf2, buf),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
message: `${defaultMsgStartFull}\n\n` +
' Buffer [Uint8Array] [\n 120,\n 121,\n 122,\n' +
'- 10,\n- prop: 1\n+ 10\n ]'
'+ 10,\n+ prop: 1\n- 10\n ]'
}
);
assert.deepEqual(buf2, buf);
@ -74,9 +74,9 @@ assert.deepEqual(arr, buf);
() => assert.deepStrictEqual(arr, arr2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
message: `${defaultMsgStartFull}\n\n` +
' Uint8Array [\n 120,\n 121,\n 122,\n' +
'- 10\n+ 10,\n+ prop: 5\n ]'
'+ 10\n- 10,\n- prop: 5\n ]'
}
);
assert.deepEqual(arr, arr2);
@ -101,18 +101,18 @@ assert.throws(
() => assert.deepStrictEqual(date, date2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
'- 2016-01-01T00:00:00.000Z\n+ 2016-01-01T00:00:00.000Z {\n' +
"+ '0': '1'\n+ }"
message: `${defaultMsgStartFull}\n\n` +
'+ 2016-01-01T00:00:00.000Z\n- 2016-01-01T00:00:00.000Z {\n' +
"- '0': '1'\n- }"
}
);
assert.throws(
() => assert.deepStrictEqual(date2, date),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
'- 2016-01-01T00:00:00.000Z {\n' +
"- '0': '1'\n- }\n+ 2016-01-01T00:00:00.000Z"
message: `${defaultMsgStartFull}\n\n` +
'+ 2016-01-01T00:00:00.000Z {\n' +
"+ '0': '1'\n+ }\n- 2016-01-01T00:00:00.000Z"
}
);
@ -133,8 +133,8 @@ assert.throws(
() => assert.deepStrictEqual(re1, re2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
"- /test/\n+ /test/ {\n+ '0': '1'\n+ }"
message: `${defaultMsgStartFull}\n\n` +
"+ /test/\n- /test/ {\n- '0': '1'\n- }"
}
);
@ -498,8 +498,8 @@ assertOnlyDeepEqual(
() => assert.deepStrictEqual(map1, map2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
" Map {\n- 1 => 1\n+ 1 => '1'\n }"
message: `${defaultMsgStartFull}\n\n` +
" Map {\n+ 1 => 1\n- 1 => '1'\n }"
}
);
}
@ -750,7 +750,7 @@ assert.throws(
() => assert.notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)),
{
name: 'AssertionError [ERR_ASSERTION]',
message: 'Identical input passed to notDeepStrictEqual: ' +
message: 'Expected "actual" not to be strictly deep-equal to: ' +
util.inspect(new Date(2000, 3, 14))
}
);
@ -767,35 +767,35 @@ assert.throws(
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- /ab/\n+ /a/`
message: `${defaultMsgStartFull}\n\n+ /ab/\n- /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/g, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- /a/g\n+ /a/`
message: `${defaultMsgStartFull}\n\n+ /a/g\n- /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/i, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- /a/i\n+ /a/`
message: `${defaultMsgStartFull}\n\n+ /a/i\n- /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/m, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- /a/m\n+ /a/`
message: `${defaultMsgStartFull}\n\n+ /a/m\n- /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/igm, /a/im),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- /a/gim\n+ /a/im`
message: `${defaultMsgStartFull}\n\n+ /a/gim\n- /a/im\n ^`
});
{
@ -806,12 +806,12 @@ assert.throws(
assert.throws(
() => assert.deepStrictEqual(4, '4'),
{ message: `${defaultMsgStart}\n\n- 4\n+ '4'` }
{ message: `${defaultMsgStart}\n4 !== '4'\n` }
);
assert.throws(
() => assert.deepStrictEqual(true, 1),
{ message: `${defaultMsgStart}\n\n- true\n+ 1` }
{ message: `${defaultMsgStart}\ntrue !== 1\n` }
);
// Having the same number of owned properties && the same set of keys.
@ -821,21 +821,23 @@ assert.throws(() => assert.deepStrictEqual([4], ['4']),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n [\n- 4\n+ '4'\n ]`
message: `${defaultMsgStartFull}\n\n [\n+ 4\n- '4'\n ]`
});
assert.throws(
() => assert.deepStrictEqual({ a: 4 }, { a: 4, b: true }),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n {\n- a: 4\n+ a: 4,\n+ b: true\n }`
message: `${defaultMsgStartFull}\n\n ` +
'{\n+ a: 4\n- a: 4,\n- b: true\n }'
});
assert.throws(
() => assert.deepStrictEqual(['a'], { 0: 'a' }),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: `${defaultMsgStart}\n\n- [\n- 'a'\n- ]\n+ {\n+ '0': 'a'\n+ }`
message: `${defaultMsgStartFull}\n\n` +
"+ [\n+ 'a'\n+ ]\n- {\n- '0': 'a'\n- }"
});
/* eslint-enable */
@ -906,8 +908,8 @@ assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}),
assert.throws(
() => assert.deepStrictEqual(a, b),
{
message: `${defaultMsgStart}\n\n` +
' [TypeError: foo] {\n- foo: \'bar\'\n+ foo: \'baz\'\n }'
message: `${defaultMsgStartFull}\n\n` +
' [TypeError: foo] {\n+ foo: \'bar\'\n- foo: \'baz\'\n }'
}
);
}
@ -922,8 +924,8 @@ assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}),
util.inspect.defaultOptions = { showProxy: true };
assert.throws(
() => assert.deepStrictEqual(arrProxy, [1, 2, 3]),
{ message: `${defaultMsgStart}\n\n` +
' [\n 1,\n- 2\n+ 2,\n+ 3\n ]' }
{ message: `${defaultMsgStartFull}\n\n` +
' [\n 1,\n+ 2\n- 2,\n- 3\n ]' }
);
util.inspect.defaultOptions = tmp;
}

View File

@ -34,8 +34,9 @@ const a = assert;
if (process.stdout.isTTY)
process.env.NODE_DISABLE_COLORS = '1';
const start = 'Input A expected to strictly deep-equal input B:';
const actExp = '+ expected - actual';
const strictEqualMessageStart = 'Expected inputs to be strictly equal:\n';
const start = 'Expected inputs to be strictly deep-equal:';
const actExp = '+ actual - expected';
assert.ok(a.AssertionError.prototype instanceof Error,
'a.AssertionError instanceof Error');
@ -70,7 +71,7 @@ assert.throws(() => a.strictEqual(null, undefined),
assert.throws(
() => a.notStrictEqual(2, 2),
{
message: 'Identical input passed to notStrictEqual: 2',
message: 'Expected "actual" to be strictly unequal to: 2',
name: 'AssertionError [ERR_ASSERTION]'
}
);
@ -78,7 +79,8 @@ assert.throws(
assert.throws(
() => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)),
{
message: `Identical input passed to notStrictEqual: '${'a '.repeat(30)}'`,
message: 'Expected "actual" to be strictly unequal to: ' +
`'${'a '.repeat(30)}'`,
name: 'AssertionError [ERR_ASSERTION]'
}
);
@ -254,42 +256,48 @@ a.throws(() => thrower(TypeError), (err) => {
const circular = { y: 1 };
circular.x = circular;
function testAssertionMessage(actual, expected) {
function testAssertionMessage(actual, expected, msg) {
try {
assert.strictEqual(actual, '');
} catch (e) {
assert.strictEqual(
e.message,
'Input A expected to strictly equal input B:\n+ expected - actual\n\n' +
`- ${expected}\n+ ''`
msg || strictEqualMessageStart +
`+ actual - expected\n\n+ ${expected}\n- ''`
);
assert.ok(e.generatedMessage, 'Message not marked as generated');
}
}
testAssertionMessage(undefined, 'undefined');
testAssertionMessage(null, 'null');
testAssertionMessage(true, 'true');
testAssertionMessage(false, 'false');
testAssertionMessage(0, '0');
testAssertionMessage(100, '100');
testAssertionMessage(NaN, 'NaN');
testAssertionMessage(Infinity, 'Infinity');
testAssertionMessage(-Infinity, '-Infinity');
testAssertionMessage('', '""');
testAssertionMessage('foo', '\'foo\'');
function testShortAssertionMessage(actual, expected) {
testAssertionMessage(actual, expected, strictEqualMessageStart +
`\n${inspect(actual)} !== ''\n`);
}
testShortAssertionMessage(null, 'null');
testShortAssertionMessage(true, 'true');
testShortAssertionMessage(false, 'false');
testShortAssertionMessage(100, '100');
testShortAssertionMessage(NaN, 'NaN');
testShortAssertionMessage(Infinity, 'Infinity');
testShortAssertionMessage('', '""');
testShortAssertionMessage('foo', '\'foo\'');
testShortAssertionMessage(0, '0');
testShortAssertionMessage(Symbol(), 'Symbol()');
testAssertionMessage([], '[]');
testAssertionMessage([1, 2, 3], '[\n- 1,\n- 2,\n- 3\n- ]');
testAssertionMessage(/a/, '/a/');
testAssertionMessage(/abc/gim, '/abc/gim');
testAssertionMessage({}, '{}');
testAssertionMessage(undefined, 'undefined');
testAssertionMessage(-Infinity, '-Infinity');
testAssertionMessage([1, 2, 3], '[\n+ 1,\n+ 2,\n+ 3\n+ ]');
testAssertionMessage(function f() {}, '[Function: f]');
testAssertionMessage(function() {}, '[Function]');
testAssertionMessage({}, '{}');
testAssertionMessage(circular, '{\n- y: 1,\n- x: [Circular]\n- }');
testAssertionMessage(circular, '{\n+ y: 1,\n+ x: [Circular]\n+ }');
testAssertionMessage({ a: undefined, b: null },
'{\n- a: undefined,\n- b: null\n- }');
'{\n+ a: undefined,\n+ b: null\n+ }');
testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
'{\n- a: NaN,\n- b: Infinity,\n- c: -Infinity\n- }');
'{\n+ a: NaN,\n+ b: Infinity,\n+ c: -Infinity\n+ }');
// https://github.com/nodejs/node-v0.x-archive/issues/5292
try {
@ -297,8 +305,7 @@ try {
} catch (e) {
assert.strictEqual(
e.message,
'Input A expected to strictly equal input B:\n' +
'+ expected - actual\n\n- 1\n+ 2'
`${strictEqualMessageStart}\n1 !== 2\n`
);
assert.ok(e.generatedMessage, 'Message not marked as generated');
}
@ -384,8 +391,8 @@ assert.throws(() => {
assert.strictEqual('A'.repeat(1000), '');
}, {
code: 'ERR_ASSERTION',
message: 'Input A expected to strictly equal input B:\n' +
`+ expected - actual\n\n- '${'A'.repeat(1000)}'\n+ ''`
message: `${strictEqualMessageStart}+ actual - expected\n\n` +
`+ '${'A'.repeat(1000)}'\n- ''`
});
{
@ -408,8 +415,9 @@ assert.throws(
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: 'Input A expected to strictly equal input B:\n' +
'+ expected - actual\n\n- [Error: foo]\n+ [Error: foobar]'
message: strictEqualMessageStart +
'+ actual - expected\n\n' +
'+ [Error: foo]\n- [Error: foobar]\n ^'
}
);
@ -433,7 +441,8 @@ assert.throws(
() => assert(...[]),
{
message: 'No value argument passed to `assert.ok()`',
name: 'AssertionError [ERR_ASSERTION]'
name: 'AssertionError [ERR_ASSERTION]',
generatedMessage: true
}
);
assert.throws(
@ -471,8 +480,8 @@ assert.throws(
' [',
'...',
' 2,',
'- 3',
"+ '3'",
'+ 3',
"- '3'",
' ]',
'...',
' 5',
@ -489,7 +498,7 @@ assert.throws(
' 1,',
'...',
' 0,',
'+ 1,',
'- 1,',
' 1,',
'...',
' 1',
@ -509,7 +518,7 @@ assert.throws(
' 1,',
'...',
' 0,',
'- 1,',
'+ 1,',
' 1,',
'...',
' 1',
@ -527,12 +536,12 @@ assert.throws(
'',
' [',
' 1,',
'- 2,',
'+ 1,',
'+ 2,',
'- 1,',
' 1,',
' 1,',
' 0,',
'- 1,',
'+ 1,',
' 1',
' ]'
].join('\n');
@ -546,12 +555,12 @@ assert.throws(
start,
actExp,
'',
'- [',
'- 1,',
'- 2,',
'- 1',
'- ]',
'+ undefined',
'+ [',
'+ 1,',
'+ 2,',
'+ 1',
'+ ]',
'- undefined',
].join('\n');
assert.throws(
() => assert.deepEqual([1, 2, 1]),
@ -562,7 +571,7 @@ assert.throws(
actExp,
'',
' [',
'- 1,',
'+ 1,',
' 2,',
' 1',
' ]'
@ -575,9 +584,9 @@ assert.throws(
`${actExp} ... Lines skipped\n` +
'\n' +
' [\n' +
'- 1,\n'.repeat(10) +
'+ 1,\n'.repeat(10) +
'...\n' +
'+ 2,\n'.repeat(10) +
'- 2,\n'.repeat(10) +
'...';
assert.throws(
() => assert.deepEqual(Array(12).fill(1), Array(12).fill(2)),
@ -591,21 +600,24 @@ assert.throws(
message: `${start}\n` +
`${actExp}\n` +
'\n' +
'- {}\n' +
'+ {\n' +
"+ loop: 'forever',\n" +
'+ [Symbol(util.inspect.custom)]: [Function]\n' +
'+ }'
'+ {}\n' +
'- {\n' +
"- loop: 'forever',\n" +
'- [Symbol(util.inspect.custom)]: [Function]\n' +
'- }'
});
// notDeepEqual tests
message = 'Identical input passed to notDeepStrictEqual:\n\n[\n 1\n]\n';
assert.throws(
() => assert.notDeepEqual([1], [1]),
{ message });
{
message: 'Expected "actual" not to be strictly deep-equal to:\n\n' +
'[\n 1\n]\n'
}
);
message = 'Identical input passed to notDeepStrictEqual:' +
`\n\n[${'\n 1,'.repeat(25)}\n...\n`;
message = 'Expected "actual" not to be strictly deep-equal to:' +
`\n\n[${'\n 1,'.repeat(25)}\n...\n`;
const data = Array(31).fill(1);
assert.throws(
() => assert.notDeepEqual(data, data),
@ -874,8 +886,8 @@ common.expectsError(
name: 'AssertionError [ERR_ASSERTION]',
message: `${start}\n${actExp}\n\n` +
" Comparison {\n name: 'TypeError',\n" +
" message: 'Wrong value',\n- code: 404\n" +
'+ code: 404,\n+ foo: undefined\n }'
" message: 'Wrong value',\n+ code: 404\n" +
'- code: 404,\n- foo: undefined\n }'
}
);
@ -888,8 +900,8 @@ common.expectsError(
name: 'AssertionError [ERR_ASSERTION]',
message: `${start}\n${actExp}\n\n` +
" Comparison {\n name: 'TypeError',\n" +
" message: 'Wrong value',\n- code: 404\n" +
"+ code: '404',\n+ foo: undefined\n }"
" message: 'Wrong value',\n+ code: 404\n" +
"- code: '404',\n- foo: undefined\n }"
}
);
@ -919,7 +931,7 @@ common.expectsError(
name: 'AssertionError [ERR_ASSERTION]',
code: 'ERR_ASSERTION',
message: `${start}\n${actExp}\n\n` +
" Comparison {\n- name: 'TypeError',\n+ name: 'Error'," +
" Comparison {\n+ name: 'TypeError',\n- name: 'Error'," +
"\n message: 'e'\n }"
}
);
@ -930,8 +942,8 @@ common.expectsError(
code: 'ERR_ASSERTION',
generatedMessage: true,
message: `${start}\n${actExp}\n\n` +
" Comparison {\n name: 'Error',\n- message: 'foo'" +
"\n+ message: ''\n }"
" Comparison {\n name: 'Error',\n+ message: 'foo'" +
"\n- message: ''\n }"
}
);
@ -988,7 +1000,7 @@ assert.throws(() => { throw null; }, 'foo');
assert.throws(
() => assert.strictEqual([], []),
{
message: 'Input objects identical but not reference equal:\n\n[]\n'
message: 'Inputs identical but not reference equal:\n\n[]\n'
}
);
@ -997,8 +1009,8 @@ assert.throws(
assert.throws(
() => assert.strictEqual(args, { 0: 'a' }),
{
message: 'Input A expected to strictly equal input B:\n+ expected' +
" - actual\n\n- [Arguments] {\n+ {\n '0': 'a'\n }"
message: `${strictEqualMessageStart}+ actual - expected\n\n` +
"+ [Arguments] {\n- {\n '0': 'a'\n }"
}
);
}
@ -1022,8 +1034,8 @@ assert.throws(
{
message: `${start}\n${actExp}\n\n` +
' Comparison {\n' +
"- message: 'foobar',\n" +
'+ message: /fooa/,\n' +
"+ message: 'foobar',\n" +
'- message: /fooa/,\n' +
" name: 'TypeError'\n" +
' }'
}
@ -1043,10 +1055,10 @@ assert.throws(
expected,
generatedMessage: true,
message: `${start}\n${actExp}\n\n` +
'- null\n' +
'+ {\n' +
"+ message: 'foo'\n" +
'+ }'
'+ null\n' +
'- {\n' +
"- message: 'foo'\n" +
'- }'
}
);

View File

@ -77,7 +77,7 @@ common.expectsError(() => {
}, { code: 'TEST_ERROR_1', type: RangeError });
}, {
code: 'ERR_ASSERTION',
message: /- type: \[Function: TypeError]\n\+ type: \[Function: RangeError]/
message: /\+ type: \[Function: TypeError]\n- type: \[Function: RangeError]/
});
common.expectsError(() => {
@ -89,7 +89,7 @@ common.expectsError(() => {
}, {
code: 'ERR_ASSERTION',
type: assert.AssertionError,
message: /- message: 'Error for testing purposes: a'\n\+ message: \/\^Error/
message: /\+ message: 'Error for testing purposes: a'\n- message: \/\^Error/
});
// Test ERR_INVALID_FD_TYPE

View File

@ -7,12 +7,12 @@ try {
process.env.COLORTERM = '1';
assert.deepStrictEqual([1, 2, 2, 2], [2, 2, 2, 2]);
} catch (err) {
const expected = 'Input A expected to strictly deep-equal input B:\n' +
'\u001b[32m+ expected\u001b[39m \u001b[31m- actual\u001b[39m' +
const expected = 'Expected inputs to be strictly deep-equal:\n' +
'\u001b[32m+ actual\u001b[39m \u001b[31m- expected\u001b[39m' +
' \u001b[34m...\u001b[39m Lines skipped\n\n' +
' [\n' +
'\u001b[31m-\u001b[39m 1,\n' +
'\u001b[32m+\u001b[39m 2,\n' +
'\u001b[32m+\u001b[39m 1,\n' +
'\u001b[31m-\u001b[39m 2,\n' +
' 2,\n' +
'\u001b[34m...\u001b[39m\n' +
' 2\n' +