diff --git a/doc/api/assert.md b/doc/api/assert.md index baa7c2f8aa054a..96800217f68074 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -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) ``` diff --git a/lib/internal/assert.js b/lib/internal/assert.js index 74f7e3f7c053c4..894b36d17fadab 100644 --- a/lib/internal/assert.js +++ b/lib/internal/assert.js @@ -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. diff --git a/test/message/assert_throws_stack.out b/test/message/assert_throws_stack.out index 3d5f4de4cf26a6..3013dbc0286bb2 100644 --- a/test/message/assert_throws_stack.out +++ b/test/message/assert_throws_stack.out @@ -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. (*assert_throws_stack.js:*:*) at * at * diff --git a/test/message/core_line_numbers.out b/test/message/core_line_numbers.out index b50e1678f49fb7..fc647e41b92d6b 100644 --- a/test/message/core_line_numbers.out +++ b/test/message/core_line_numbers.out @@ -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. (*test*message*core_line_numbers.js:*:*) at Module._compile (internal/modules/cjs/loader.js:*:*) diff --git a/test/message/error_exit.out b/test/message/error_exit.out index 1935c18979e45c..cc1edf46cb0001 100644 --- a/test/message/error_exit.out +++ b/test/message/error_exit.out @@ -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. (*test*message*error_exit.js:*:*) at Module._compile (internal/modules/cjs/loader.js:*:*) at Object.Module._extensions..js (internal/modules/cjs/loader.js:*:*) diff --git a/test/parallel/test-assert-checktag.js b/test/parallel/test-assert-checktag.js index 70a67e15d3f5f8..754e5649145f17 100644 --- a/test/parallel/test-assert-checktag.js +++ b/test/parallel/test-assert-checktag.js @@ -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' } ); } diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index 538f4bef49d8c6..4536b6d535f703 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -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; } diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index bc96dc57bcd5c0..6aecfc0fe6bf3f 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -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" + + '- }' } ); diff --git a/test/parallel/test-internal-errors.js b/test/parallel/test-internal-errors.js index b5e08911b8219e..6e648aeae721f0 100644 --- a/test/parallel/test-internal-errors.js +++ b/test/parallel/test-internal-errors.js @@ -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 diff --git a/test/pseudo-tty/test-assert-colors.js b/test/pseudo-tty/test-assert-colors.js index 75d3af55796e1b..cd855dc06eac27 100644 --- a/test/pseudo-tty/test-assert-colors.js +++ b/test/pseudo-tty/test-assert-colors.js @@ -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' +