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:
parent
f2d112c6b7
commit
bfe54df812
@ -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
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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 {}
|
||||
|
@ -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:*:*)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -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' +
|
||||
|
Loading…
x
Reference in New Issue
Block a user