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

assert: improve the strict equal messages #23056

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
41 changes: 31 additions & 10 deletions lib/internal/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 &&
Expand All @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion test/message/assert_throws_stack.out
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand Down
2 changes: 1 addition & 1 deletion test/message/error_exit.out
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-assert-checktag.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
);
Expand Down
4 changes: 2 additions & 2 deletions test/parallel/test-assert-deep.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down
53 changes: 47 additions & 6 deletions test/parallel/test-assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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]'
}
);

Expand Down Expand Up @@ -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'
}
);

Expand All @@ -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 }"
}
);
Expand Down Expand Up @@ -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'
}
);
2 changes: 1 addition & 1 deletion test/pseudo-tty/test-assert-colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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' +
Expand Down