assert: improve default error messages

This improves the error messages for:
- assert.notDeepStrictEqual
- assert.deepStrictEqual
- assert.notStrictEqual
- assert.strictEqual

Those will now always use the same error message as used in the
strict mode.

PR-URL: https://github.com/nodejs/node/pull/19467
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Ruben Bridgewater 2018-03-12 22:14:24 +01:00 committed by James M Snell
parent f2d112c6b7
commit bfe54df812
8 changed files with 320 additions and 120 deletions

View File

@ -54,7 +54,6 @@ const meta = [
const escapeFn = (str) => meta[str.charCodeAt(0)];
const ERR_DIFF_DEACTIVATED = 0;
const ERR_DIFF_NOT_EQUAL = 1;
const ERR_DIFF_EQUAL = 2;
@ -323,7 +322,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
message,
operator: 'deepStrictEqual',
stackStartFn: deepStrictEqual,
errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED
errorDiff: ERR_DIFF_EQUAL
});
}
};
@ -337,7 +336,7 @@ function notDeepStrictEqual(actual, expected, message) {
message,
operator: 'notDeepStrictEqual',
stackStartFn: notDeepStrictEqual,
errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED
errorDiff: ERR_DIFF_NOT_EQUAL
});
}
}
@ -350,7 +349,7 @@ assert.strictEqual = function strictEqual(actual, expected, message) {
message,
operator: 'strictEqual',
stackStartFn: strictEqual,
errorDiff: this === strict ? ERR_DIFF_EQUAL : ERR_DIFF_DEACTIVATED
errorDiff: ERR_DIFF_EQUAL
});
}
};
@ -363,7 +362,7 @@ assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
message,
operator: 'notStrictEqual',
stackStartFn: notStrictEqual,
errorDiff: this === strict ? ERR_DIFF_NOT_EQUAL : ERR_DIFF_DEACTIVATED
errorDiff: ERR_DIFF_NOT_EQUAL
});
}
};

View File

@ -19,6 +19,13 @@ 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 {
errmap,
UV_EAI_MEMORY,
@ -40,10 +47,34 @@ function lazyInternalUtil() {
return internalUtil;
}
function copyError(source) {
const keys = Object.keys(source);
const target = Object.create(Object.getPrototypeOf(source));
for (const key of keys) {
target[key] = source[key];
}
Object.defineProperty(target, 'message', { value: source.message });
return target;
}
function inspectValue(val) {
// The util.inspect default values could be changed. This makes sure the
// error messages contain the necessary information nevertheless.
return util.inspect(
val,
{ compact: false, customInspect: false }
{
compact: false,
customInspect: false,
depth: 1000,
maxArrayLength: Infinity,
// Assert compares only enumerable properties (with a few exceptions).
showHidden: false,
// Having a long line as error is better than wrapping the line for
// comparison.
breakLength: Infinity,
// Assert does not detect proxies currently.
showProxy: false
}
).split('\n');
}
@ -226,8 +257,8 @@ function createErrDiff(actual, expected, operator) {
if (util === undefined) util = require('util');
const actualLines = inspectValue(actual);
const expectedLines = inspectValue(expected);
const msg = `Input A expected to ${operator} input B:\n` +
`${green}+ expected${white} ${red}- actual${white}`;
const msg = READABLE_OPERATOR[operator] +
`:\n${green}+ expected${white} ${red}- actual${white}`;
const skippedMsg = ' ... Lines skipped';
// Remove all ending lines that match (this optimizes the output for
@ -259,6 +290,7 @@ function createErrDiff(actual, expected, operator) {
const maxLines = Math.max(actualLines.length, expectedLines.length);
var printedLines = 0;
var identical = 0;
for (i = 0; i < maxLines; i++) {
// Only extra expected lines exist
const cur = i - lastPos;
@ -318,12 +350,38 @@ 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) {
return `${msg}${skippedMsg}\n${res}\n...${other}\n...`;
}
}
// Strict equal with identical objects that are not identical by reference.
if (identical === maxLines) {
let base = 'Input object identical but not reference equal:';
if (operator !== 'strictEqual') {
// This code path should not be possible to reach.
// The output is identical but it is not clear why.
base = '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] = '...';
while (actualLines.length > 27) {
actualLines.pop();
}
}
return `${base}\n\n ${actualLines.join('\n ')}\n`;
}
return `${msg}${skipped ? skippedMsg : ''}\n${res}${other}${end}`;
}
@ -358,13 +416,15 @@ class AssertionError extends Error {
}
}
if (util === undefined) util = require('util');
// Prevent the error stack from being visible by duplicating the error
// in a very close way to the original in case both sides are actually
// instances of Error.
if (typeof actual === 'object' && actual !== null &&
'stack' in actual && actual instanceof Error) {
actual = `${actual.name}: ${actual.message}`;
}
if (typeof expected === 'object' && expected !== null &&
'stack' in expected && expected instanceof Error) {
expected = `${expected.name}: ${expected.message}`;
typeof expected === 'object' && expected !== null &&
'stack' in actual && actual instanceof Error &&
'stack' in expected && expected instanceof Error) {
actual = copyError(actual);
expected = copyError(expected);
}
if (errorDiff === 0) {
@ -379,15 +439,23 @@ 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}:`;
if (res.length > 20) {
res[19] = '...';
while (res.length > 20) {
// Only remove lines in case it makes sense to collapse those.
// TODO: Accept env to always show the full error.
if (res.length > 30) {
res[26] = '...';
while (res.length > 27) {
res.pop();
}
}
// Only print a single object.
super(`Identical input passed to ${operator}:\n${res.join('\n')}`);
// Only print a single input.
if (res.length === 1) {
super(`${base} ${res[0]}`);
} else {
super(`${base}\n\n ${res.join('\n ')}\n`);
}
} else {
super(createErrDiff(actual, expected, operator));
}

View File

@ -2,7 +2,7 @@ assert.js:*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: Input A expected to deepStrictEqual input B:
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual
- Comparison {}

View File

@ -3,7 +3,11 @@ assert.js:*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: 1 strictEqual 2
AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B:
+ expected - actual
- 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

@ -1,24 +1,6 @@
'use strict';
const common = require('../common');
require('../common');
const assert = require('assert');
const util = require('util');
// Template tag function turning an error message into a RegExp
// for assert.throws()
function re(literals, ...values) {
let result = literals[0];
const escapeRE = /[\\^$.*+?()[\]{}|=!<>:-]/g;
for (const [i, value] of values.entries()) {
const str = util.inspect(value);
// Need to escape special characters.
result += str.replace(escapeRE, '\\$&');
result += literals[i + 1];
}
return common.expectsError({
code: 'ERR_ASSERTION',
message: new RegExp(`^${result}$`)
});
}
// Turn off no-restricted-properties because we are testing deepEqual!
/* eslint-disable no-restricted-properties */
@ -35,10 +17,20 @@ function re(literals, ...values) {
// For deepStrictEqual we check the runtime type,
// then reveal the fakeness of the fake date
assert.throws(() => assert.deepStrictEqual(date, fake),
re`${date} deepStrictEqual Date {}`);
assert.throws(() => assert.deepStrictEqual(fake, date),
re`Date {} deepStrictEqual ${date}`);
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 {}'
}
);
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'
}
);
}
{ // At the moment global has its own type tag

View File

@ -4,6 +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';
// Template tag function turning an error message into a RegExp
// for assert.throws()
@ -32,24 +34,45 @@ function re(literals, ...values) {
const arr = new Uint8Array([120, 121, 122, 10]);
const buf = Buffer.from(arr);
// They have different [[Prototype]]
assert.throws(() => assert.deepStrictEqual(arr, buf),
re`${arr} deepStrictEqual ${buf}`);
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 ]'
}
);
assert.deepEqual(arr, buf);
{
const buf2 = Buffer.from(arr);
buf2.prop = 1;
assert.throws(() => assert.deepStrictEqual(buf2, buf),
re`${buf2} deepStrictEqual ${buf}`);
assert.throws(
() => assert.deepStrictEqual(buf2, buf),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
' Buffer [Uint8Array] [\n 120,\n 121,\n 122,\n' +
'- 10,\n- prop: 1\n+ 10\n ]'
}
);
assert.deepEqual(buf2, buf);
}
{
const arr2 = new Uint8Array([120, 121, 122, 10]);
arr2.prop = 5;
assert.throws(() => assert.deepStrictEqual(arr, arr2),
re`${arr} deepStrictEqual ${arr2}`);
assert.throws(
() => assert.deepStrictEqual(arr, arr2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
' Uint8Array [\n 120,\n 121,\n 122,\n' +
'- 10\n+ 10,\n+ prop: 5\n ]'
}
);
assert.deepEqual(arr, arr2);
}
@ -68,10 +91,24 @@ const date2 = new MyDate('2016');
// but deepStrictEqual checks own properties
assert.deepEqual(date, date2);
assert.deepEqual(date2, date);
assert.throws(() => assert.deepStrictEqual(date, date2),
re`${date} deepStrictEqual ${date2}`);
assert.throws(() => assert.deepStrictEqual(date2, date),
re`${date2} deepStrictEqual ${date}`);
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+ }"
}
);
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"
}
);
class MyRegExp extends RegExp {
constructor(...args) {
@ -86,8 +123,14 @@ const re2 = new MyRegExp('test');
// deepEqual returns true as long as the regexp-specific properties
// are the same, but deepStrictEqual checks all properties
assert.deepEqual(re1, re2);
assert.throws(() => assert.deepStrictEqual(re1, re2),
re`${re1} deepStrictEqual ${re2}`);
assert.throws(
() => assert.deepStrictEqual(re1, re2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
"- /test/\n+ /test/ {\n+ '0': '1'\n+ }"
}
);
// For these weird cases, deepEqual should pass (at least for now),
// but deepStrictEqual should throw.
@ -115,8 +158,10 @@ assert.throws(() => assert.deepStrictEqual(re1, re2),
for (const b of similar) {
if (a !== b) {
assert.deepEqual(a, b);
assert.throws(() => assert.deepStrictEqual(a, b),
re`${a} deepStrictEqual ${b}`);
assert.throws(
() => assert.deepStrictEqual(a, b),
{ code: 'ERR_ASSERTION' }
);
}
}
}
@ -139,22 +184,30 @@ function assertDeepAndStrictEqual(a, b) {
function assertNotDeepOrStrict(a, b, err) {
assert.throws(() => assert.deepEqual(a, b), err || re`${a} deepEqual ${b}`);
assert.throws(() => assert.deepStrictEqual(a, b), err ||
re`${a} deepStrictEqual ${b}`);
assert.throws(
() => assert.deepStrictEqual(a, b),
err || { code: 'ERR_ASSERTION' }
);
assert.throws(() => assert.deepEqual(b, a), err || re`${b} deepEqual ${a}`);
assert.throws(() => assert.deepStrictEqual(b, a), err ||
re`${b} deepStrictEqual ${a}`);
assert.throws(
() => assert.deepStrictEqual(b, a),
err || { code: 'ERR_ASSERTION' }
);
}
function assertOnlyDeepEqual(a, b, err) {
assert.deepEqual(a, b);
assert.throws(() => assert.deepStrictEqual(a, b), err ||
re`${a} deepStrictEqual ${b}`);
assert.throws(
() => assert.deepStrictEqual(a, b),
err || { code: 'ERR_ASSERTION' }
);
assert.deepEqual(b, a);
assert.throws(() => assert.deepStrictEqual(b, a), err ||
re`${b} deepStrictEqual ${a}`);
assert.throws(
() => assert.deepStrictEqual(b, a),
err || { code: 'ERR_ASSERTION' }
);
}
// es6 Maps and Sets
@ -352,7 +405,8 @@ assertOnlyDeepEqual(
assertDeepAndStrictEqual(b, c);
}
// GH-7178. Ensure reflexivity of deepEqual with `arguments` objects.
// https://github.com/nodejs/node-v0.x-archive/pull/7178
// Ensure reflexivity of deepEqual with `arguments` objects.
{
const args = (function() { return arguments; })();
assertNotDeepOrStrict([], args);
@ -434,8 +488,14 @@ assertOnlyDeepEqual(
const map1 = new Map([[1, 1]]);
const map2 = new Map([[1, '1']]);
assert.deepEqual(map1, map2);
assert.throws(() => assert.deepStrictEqual(map1, map2),
re`${map1} deepStrictEqual ${map2}`);
assert.throws(
() => assert.deepStrictEqual(map1, map2),
{
code: 'ERR_ASSERTION',
message: `${defaultMsgStart}\n\n` +
" Map {\n- 1 => 1\n+ 1 => '1'\n }"
}
);
}
{
@ -682,8 +742,11 @@ assert.throws(
assert.throws(
() => assert.notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14)),
AssertionError,
'notDeepStrictEqual(new Date(2000, 3, 14), new Date(2000, 3, 14))'
{
name: 'AssertionError [ERR_ASSERTION]',
message: 'Identical input passed to notDeepStrictEqual: ' +
util.inspect(new Date(2000, 3, 14))
}
);
assert.notDeepStrictEqual(new Date(), new Date(2000, 3, 14));
@ -698,35 +761,35 @@ assert.throws(
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '/ab/ deepStrictEqual /a/'
message: `${defaultMsgStart}\n\n- /ab/\n+ /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/g, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '/a/g deepStrictEqual /a/'
message: `${defaultMsgStart}\n\n- /a/g\n+ /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/i, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '/a/i deepStrictEqual /a/'
message: `${defaultMsgStart}\n\n- /a/i\n+ /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/m, /a/),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '/a/m deepStrictEqual /a/'
message: `${defaultMsgStart}\n\n- /a/m\n+ /a/`
});
assert.throws(
() => assert.deepStrictEqual(/a/igm, /a/im),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '/a/gim deepStrictEqual /a/im'
message: `${defaultMsgStart}\n\n- /a/gim\n+ /a/im`
});
{
@ -735,17 +798,15 @@ assert.throws(
assert.deepStrictEqual(re1, /a/);
}
assert.throws(() => assert.deepStrictEqual(4, '4'),
AssertionError,
'deepStrictEqual(4, \'4\')');
assert.throws(
() => assert.deepStrictEqual(4, '4'),
{ message: `${defaultMsgStart}\n\n- 4\n+ '4'` }
);
assert.throws(() => assert.deepStrictEqual(true, 1),
AssertionError,
'deepStrictEqual(true, 1)');
assert.throws(() => assert.deepStrictEqual(4, '5'),
AssertionError,
'deepStrictEqual(4, \'5\')');
assert.throws(
() => assert.deepStrictEqual(true, 1),
{ message: `${defaultMsgStart}\n\n- true\n+ 1` }
);
// Having the same number of owned properties && the same set of keys.
assert.deepStrictEqual({ a: 4 }, { a: 4 });
@ -754,20 +815,22 @@ assert.throws(() => assert.deepStrictEqual([4], ['4']),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: "[ 4 ] deepStrictEqual [ '4' ]"
});
assert.throws(() => assert.deepStrictEqual({ a: 4 }, { a: 4, b: true }),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: '{ a: 4 } deepStrictEqual { a: 4, b: true }'
});
assert.throws(() => assert.deepStrictEqual(['a'], { 0: 'a' }),
{
code: 'ERR_ASSERTION',
name: 'AssertionError [ERR_ASSERTION]',
message: "[ 'a' ] deepStrictEqual { '0': 'a' }"
message: `${defaultMsgStart}\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 }`
});
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+ }`
});
/* eslint-enable */
@ -826,3 +889,35 @@ assert.throws(() => assert.deepStrictEqual(new String('a'), { 0: 'a' }),
assert.throws(() => assert.deepStrictEqual(new Number(1), {}), AssertionError);
assert.throws(() => assert.deepStrictEqual(new Boolean(true), {}),
AssertionError);
// Check extra properties on errors.
{
const a = new TypeError('foo');
const b = new TypeError('foo');
a.foo = 'bar';
b.foo = 'baz';
assert.throws(
() => assert.deepStrictEqual(a, b),
{
message: `${defaultMsgStart}\n\n` +
' [TypeError: foo] {\n- foo: \'bar\'\n+ foo: \'baz\'\n }'
}
);
}
// Check proxies.
{
// TODO(BridgeAR): Check if it would not be better to detect proxies instead
// of just using the proxy value.
const arrProxy = new Proxy([1, 2], {});
assert.deepStrictEqual(arrProxy, [1, 2]);
const tmp = util.inspect.defaultOptions;
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 ]' }
);
util.inspect.defaultOptions = tmp;
}

View File

@ -34,7 +34,7 @@ const { writeFileSync, unlinkSync } = require('fs');
const { inspect } = require('util');
const a = assert;
const start = 'Input A expected to deepStrictEqual input B:';
const start = 'Input A expected to strictly deep-equal input B:';
const actExp = '+ expected - actual';
assert.ok(a.AssertionError.prototype instanceof Error,
@ -67,8 +67,21 @@ assert.throws(() => a.strictEqual(2, '2'),
assert.throws(() => a.strictEqual(null, undefined),
a.AssertionError, 'strictEqual(null, undefined)');
assert.throws(() => a.notStrictEqual(2, 2),
a.AssertionError, 'notStrictEqual(2, 2)');
assert.throws(
() => a.notStrictEqual(2, 2),
{
message: 'Identical input passed to notStrictEqual: 2',
name: 'AssertionError [ERR_ASSERTION]'
}
);
assert.throws(
() => a.notStrictEqual('a '.repeat(30), 'a '.repeat(30)),
{
message: `Identical input passed to notStrictEqual: '${'a '.repeat(30)}'`,
name: 'AssertionError [ERR_ASSERTION]'
}
);
a.notStrictEqual(2, '2');
@ -245,8 +258,11 @@ function testAssertionMessage(actual, expected) {
try {
assert.strictEqual(actual, '');
} catch (e) {
assert.strictEqual(e.message,
[expected, 'strictEqual', '\'\''].join(' '));
assert.strictEqual(
e.message,
'Input A expected to strictly equal input B:\n+ expected - actual\n\n' +
`- ${expected}\n+ ''`
);
assert.ok(e.generatedMessage, 'Message not marked as generated');
}
}
@ -263,29 +279,34 @@ testAssertionMessage(-Infinity, '-Infinity');
testAssertionMessage('', '""');
testAssertionMessage('foo', '\'foo\'');
testAssertionMessage([], '[]');
testAssertionMessage([1, 2, 3], '[ 1, 2, 3 ]');
testAssertionMessage([1, 2, 3], '[\n- 1,\n- 2,\n- 3\n- ]');
testAssertionMessage(/a/, '/a/');
testAssertionMessage(/abc/gim, '/abc/gim');
testAssertionMessage(function f() {}, '[Function: f]');
testAssertionMessage(function() {}, '[Function]');
testAssertionMessage({}, '{}');
testAssertionMessage(circular, '{ y: 1, x: [Circular] }');
testAssertionMessage({ a: undefined, b: null }, '{ a: undefined, b: null }');
testAssertionMessage(circular, '{\n- y: 1,\n- x: [Circular]\n- }');
testAssertionMessage({ a: undefined, b: null },
'{\n- a: undefined,\n- b: null\n- }');
testAssertionMessage({ a: NaN, b: Infinity, c: -Infinity },
'{ a: NaN, b: Infinity, c: -Infinity }');
'{\n- a: NaN,\n- b: Infinity,\n- c: -Infinity\n- }');
// https://github.com/nodejs/node-v0.x-archive/issues/5292
try {
assert.strictEqual(1, 2);
} catch (e) {
assert.strictEqual(e.message.split('\n')[0], '1 strictEqual 2');
assert.strictEqual(
e.message,
'Input A expected to strictly equal input B:\n' +
'+ expected - actual\n\n- 1\n+ 2'
);
assert.ok(e.generatedMessage, 'Message not marked as generated');
}
try {
assert.strictEqual(1, 2, 'oh no');
} catch (e) {
assert.strictEqual(e.message.split('\n')[0], 'oh no');
assert.strictEqual(e.message, 'oh no');
assert.strictEqual(e.generatedMessage, false,
'Message incorrectly marked as generated');
}
@ -361,10 +382,11 @@ assert.throws(() => { throw new Error(); }, (err) => err instanceof Error);
// Long values should be truncated for display.
assert.throws(() => {
assert.strictEqual('A'.repeat(1000), '');
}, common.expectsError({
}, {
code: 'ERR_ASSERTION',
message: /^'A{124}\.\.\. strictEqual ''$/
}));
message: 'Input A expected to strictly equal input B:\n' +
`+ expected - actual\n\n- '${'A'.repeat(1000)}'\n+ ''`
});
{
// Bad args to AssertionError constructor should throw TypeError.
@ -381,12 +403,13 @@ assert.throws(() => {
});
}
common.expectsError(
assert.throws(
() => assert.strictEqual(new Error('foo'), new Error('foobar')),
{
code: 'ERR_ASSERTION',
type: assert.AssertionError,
message: /^'Error: foo' strictEqual 'Error: foobar'$/
name: 'AssertionError [ERR_ASSERTION]',
message: 'Input A expected to strictly equal input B:\n' +
'+ expected - actual\n\n- [Error: foo]\n+ [Error: foobar]'
}
);
@ -576,14 +599,15 @@ common.expectsError(
});
// notDeepEqual tests
message = 'Identical input passed to notDeepStrictEqual:\n[\n 1\n]';
message = 'Identical input passed to notDeepStrictEqual:\n\n' +
' [\n 1\n ]\n';
assert.throws(
() => assert.notDeepEqual([1], [1]),
{ message });
message = 'Identical input passed to notDeepStrictEqual:' +
`\n[${'\n 1,'.repeat(18)}\n...`;
const data = Array(21).fill(1);
`\n\n [${'\n 1,'.repeat(25)}\n ...\n`;
const data = Array(31).fill(1);
assert.throws(
() => assert.notDeepEqual(data, data),
{ message });
@ -873,3 +897,21 @@ assert.throws(
// Should not throw.
// eslint-disable-next-line no-restricted-syntax, no-throw-literal
assert.throws(() => { throw null; }, 'foo');
assert.throws(
() => assert.strictEqual([], []),
{
message: 'Input object identical but not reference equal:\n\n []\n'
}
);
{
const args = (function() { return arguments; })('a');
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 }"
}
);
}

View File

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