diff --git a/lib/internal/assert.js b/lib/internal/assert.js index 36e3bbf57b5613..92c2a1d0af893e 100644 --- a/lib/internal/assert.js +++ b/lib/internal/assert.js @@ -11,15 +11,18 @@ let red = ''; let white = ''; const kReadableOperator = { - deepStrictEqual: 'Expected inputs to be strictly deep-equal:', - strictEqual: 'Expected inputs to be strictly equal:', - deepEqual: 'Expected inputs to be loosely deep-equal:', - equal: 'Expected inputs to be loosely equal:', + deepStrictEqual: 'Expected values to be strictly deep-equal:', + strictEqual: 'Expected values to be strictly equal:', + strictEqualObject: 'Expected "actual" to be reference-equal to "expected":', + deepEqual: 'Expected values to be loosely deep-equal:', + equal: 'Expected values to be loosely equal:', notDeepStrictEqual: 'Expected "actual" not to be strictly deep-equal to:', notStrictEqual: 'Expected "actual" to be strictly unequal to:', + // eslint-disable-next-line max-len + notStrictEqualObject: 'Expected "actual" not to be reference-equal to "expected":', notDeepEqual: 'Expected "actual" not to be loosely deep-equal to:', notEqual: 'Expected "actual" to be loosely unequal to:', - notIdentical: 'Inputs identical but not reference equal:', + notIdentical: 'Values identical but not reference-equal:', }; // Comparing short primitives should just show === / !== instead of using the @@ -67,13 +70,20 @@ function createErrDiff(actual, expected, operator) { const actualInspected = inspectValue(actual); const actualLines = actualInspected.split('\n'); const expectedLines = inspectValue(expected).split('\n'); - const msg = kReadableOperator[operator] + - `\n${green}+ actual${white} ${red}- expected${white}`; - const skippedMsg = ` ${blue}...${white} Lines skipped`; let i = 0; let indicator = ''; + // In case both values are objects explicitly mark them as not reference equal + // for the `strictEqual` operator. + if (operator === 'strictEqual' && + typeof actual === 'object' && + typeof expected === 'object' && + actual !== null && + expected !== null) { + operator = 'strictEqualObject'; + } + // 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 && @@ -89,7 +99,7 @@ function createErrDiff(actual, expected, operator) { return `${kReadableOperator[operator]}\n\n` + `${actualLines[0]} !== ${expectedLines[0]}\n`; } - } else { + } else if (operator !== 'strictEqualObject') { // 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. @@ -156,6 +166,10 @@ function createErrDiff(actual, expected, operator) { } let printedLines = 0; + const msg = kReadableOperator[operator] + + `\n${green}+ actual${white} ${red}- expected${white}`; + const skippedMsg = ` ${blue}...${white} Lines skipped`; + for (i = 0; i < maxLines; i++) { // Only extra expected lines exist const cur = i - lastPos; @@ -274,8 +288,15 @@ class AssertionError extends Error { operator === 'notStrictEqual') { // In case the objects are equal but the operator requires unequal, show // the first object and say A equals B + let base = kReadableOperator[operator]; const res = inspectValue(actual).split('\n'); - const base = kReadableOperator[operator]; + + // In case "actual" is an object, it should not be reference equal. + if (operator === 'notStrictEqual' && + typeof actual === 'object' && + actual !== null) { + base = kReadableOperator.notStrictEqualObject; + } // 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 3013dbc0286bb2..cf96ee42c98cb7 100644 --- a/test/message/assert_throws_stack.out +++ b/test/message/assert_throws_stack.out @@ -2,7 +2,7 @@ assert.js:* throw err; ^ -AssertionError [ERR_ASSERTION]: Expected inputs to be strictly deep-equal: +AssertionError [ERR_ASSERTION]: Expected values to be strictly deep-equal: + actual - expected + Comparison {} diff --git a/test/message/error_exit.out b/test/message/error_exit.out index cc1edf46cb0001..be46bbc1ae9b5a 100644 --- a/test/message/error_exit.out +++ b/test/message/error_exit.out @@ -3,7 +3,7 @@ assert.js:* throw new AssertionError(obj); ^ -AssertionError [ERR_ASSERTION]: Expected inputs to be strictly equal: +AssertionError [ERR_ASSERTION]: Expected values to be strictly equal: 1 !== 2 diff --git a/test/parallel/test-assert-checktag.js b/test/parallel/test-assert-checktag.js index 754e5649145f17..eeb25278ff186f 100644 --- a/test/parallel/test-assert-checktag.js +++ b/test/parallel/test-assert-checktag.js @@ -26,14 +26,14 @@ if (process.stdout.isTTY) assert.throws( () => assert.deepStrictEqual(date, fake), { - message: 'Expected inputs to be strictly deep-equal:\n' + + message: 'Expected values 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: 'Expected inputs to be strictly deep-equal:\n' + + message: 'Expected values 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 fab681a89f6a03..306e8367d45502 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -4,7 +4,7 @@ require('../common'); const assert = require('assert'); const util = require('util'); const { AssertionError } = assert; -const defaultMsgStart = 'Expected inputs to be strictly deep-equal:\n'; +const defaultMsgStart = 'Expected values to be strictly deep-equal:\n'; const defaultMsgStartFull = `${defaultMsgStart}+ actual - expected`; // Disable colored output to prevent color codes from breaking assertion @@ -16,7 +16,7 @@ if (process.stdout.isTTY) // Template tag function turning an error message into a RegExp // for assert.throws() function re(literals, ...values) { - let result = 'Expected inputs to be loosely deep-equal:\n\n'; + let result = 'Expected values to be loosely deep-equal:\n\n'; for (const [i, value] of values.entries()) { const str = util.inspect(value, { compact: false, diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index ed6af5310f9428..8e6c2e52b5be55 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -34,8 +34,8 @@ const a = assert; if (process.stdout.isTTY) process.env.NODE_DISABLE_COLORS = '1'; -const strictEqualMessageStart = 'Expected inputs to be strictly equal:\n'; -const start = 'Expected inputs to be strictly deep-equal:'; +const strictEqualMessageStart = 'Expected values to be strictly equal:\n'; +const start = 'Expected values to be strictly deep-equal:'; const actExp = '+ actual - expected'; assert.ok(a.AssertionError.prototype instanceof Error, @@ -415,9 +415,9 @@ assert.throws( { code: 'ERR_ASSERTION', name: 'AssertionError [ERR_ASSERTION]', - message: strictEqualMessageStart + + message: 'Expected "actual" to be reference-equal to "expected":\n' + '+ actual - expected\n\n' + - '+ [Error: foo]\n- [Error: foobar]\n ^' + '+ [Error: foo]\n- [Error: foobar]' } ); @@ -1013,7 +1013,7 @@ assert.throws(() => { throw null; }, 'foo'); assert.throws( () => assert.strictEqual([], []), { - message: 'Inputs identical but not reference equal:\n\n[]\n' + message: 'Values identical but not reference-equal:\n\n[]\n' } ); @@ -1022,7 +1022,8 @@ assert.throws( assert.throws( () => assert.strictEqual(args, { 0: 'a' }), { - message: `${strictEqualMessageStart}+ actual - expected\n\n` + + message: 'Expected "actual" to be reference-equal to "expected":\n' + + '+ actual - expected\n\n' + "+ [Arguments] {\n- {\n '0': 'a'\n }" } ); @@ -1091,3 +1092,43 @@ assert.throws( } ); } + +// Indicate where the strings diverge. +assert.throws( + () => assert.strictEqual('test test', 'test foobar'), + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: strictEqualMessageStart + + '+ actual - expected\n\n' + + "+ 'test test'\n" + + "- 'test foobar'\n" + + ' ^' + } +); + +// Check for reference-equal objects in `notStrictEqual()` +assert.throws( + () => { + const obj = {}; + assert.notStrictEqual(obj, obj); + }, + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: 'Expected "actual" not to be reference-equal to "expected": {}' + } +); + +assert.throws( + () => { + const obj = { a: true }; + assert.notStrictEqual(obj, obj); + }, + { + code: 'ERR_ASSERTION', + name: 'AssertionError [ERR_ASSERTION]', + message: 'Expected "actual" not to be reference-equal to "expected":\n\n' + + '{\n a: true\n}\n' + } +); diff --git a/test/pseudo-tty/test-assert-colors.js b/test/pseudo-tty/test-assert-colors.js index cd855dc06eac27..e843bcb218a078 100644 --- a/test/pseudo-tty/test-assert-colors.js +++ b/test/pseudo-tty/test-assert-colors.js @@ -7,7 +7,7 @@ try { process.env.COLORTERM = '1'; assert.deepStrictEqual([1, 2, 2, 2], [2, 2, 2, 2]); } catch (err) { - const expected = 'Expected inputs to be strictly deep-equal:\n' + + const expected = 'Expected values 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' +