assert: fix rejects stack trace and operator

This makes sure the stack trace is not removed due to a wrong stack
start function being used. It also fixes the wrong operator caused
by the same reason. This only applies in case an validation object
was used to validate the rejection passed to `assert.reject()` as
first argument.

PR-URL: https://github.com/nodejs/node/pull/27047
Reviewed-By: Rich Trott <rtrott@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Ruben Bridgewater 2019-04-02 03:12:42 +02:00
parent eb2d4161f5
commit 75463a9004
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762
2 changed files with 35 additions and 10 deletions

View File

@ -502,7 +502,7 @@ class Comparison {
} }
} }
function compareExceptionKey(actual, expected, key, message, keys) { function compareExceptionKey(actual, expected, key, message, keys, fn) {
if (!(key in actual) || !isDeepStrictEqual(actual[key], expected[key])) { if (!(key in actual) || !isDeepStrictEqual(actual[key], expected[key])) {
if (!message) { if (!message) {
// Create placeholder objects to create a nice output. // Create placeholder objects to create a nice output.
@ -513,24 +513,24 @@ function compareExceptionKey(actual, expected, key, message, keys) {
actual: a, actual: a,
expected: b, expected: b,
operator: 'deepStrictEqual', operator: 'deepStrictEqual',
stackStartFn: assert.throws stackStartFn: fn
}); });
err.actual = actual; err.actual = actual;
err.expected = expected; err.expected = expected;
err.operator = 'throws'; err.operator = fn.name;
throw err; throw err;
} }
innerFail({ innerFail({
actual, actual,
expected, expected,
message, message,
operator: 'throws', operator: fn.name,
stackStartFn: assert.throws stackStartFn: fn
}); });
} }
} }
function expectedException(actual, expected, msg) { function expectedException(actual, expected, msg, fn) {
if (typeof expected !== 'function') { if (typeof expected !== 'function') {
if (isRegExp(expected)) if (isRegExp(expected))
return expected.test(actual); return expected.test(actual);
@ -548,9 +548,9 @@ function expectedException(actual, expected, msg) {
expected, expected,
message: msg, message: msg,
operator: 'deepStrictEqual', operator: 'deepStrictEqual',
stackStartFn: assert.throws stackStartFn: fn
}); });
err.operator = 'throws'; err.operator = fn.name;
throw err; throw err;
} }
@ -570,7 +570,7 @@ function expectedException(actual, expected, msg) {
expected[key].test(actual[key])) { expected[key].test(actual[key])) {
continue; continue;
} }
compareExceptionKey(actual, expected, key, msg, keys); compareExceptionKey(actual, expected, key, msg, keys, fn);
} }
return true; return true;
} }
@ -676,7 +676,7 @@ function expectsError(stackStartFn, actual, error, message) {
stackStartFn stackStartFn
}); });
} }
if (error && expectedException(actual, error, message) === false) { if (error && !expectedException(actual, error, message, stackStartFn)) {
throw actual; throw actual;
} }
} }

View File

@ -96,6 +96,7 @@ promises.push(assert.rejects(
assert.strictEqual(err.message, assert.strictEqual(err.message,
'Got unwanted rejection.\nActual message: "Failed"'); 'Got unwanted rejection.\nActual message: "Failed"');
assert.strictEqual(err.operator, 'doesNotReject'); assert.strictEqual(err.operator, 'doesNotReject');
assert.ok(err.stack);
assert.ok(!err.stack.includes('at Function.doesNotReject')); assert.ok(!err.stack.includes('at Function.doesNotReject'));
return true; return true;
}; };
@ -121,5 +122,29 @@ promises.push(assert.rejects(
} }
)); ));
{
const handler = (generated, actual, err) => {
assert.strictEqual(err.generatedMessage, generated);
assert.strictEqual(err.code, 'ERR_ASSERTION');
assert.strictEqual(err.actual, actual);
assert.strictEqual(err.operator, 'rejects');
assert(/rejects/.test(err.stack));
return true;
};
const err = new Error();
promises.push(assert.rejects(
assert.rejects(Promise.reject(null), { code: 'FOO' }),
handler.bind(null, true, null)
));
promises.push(assert.rejects(
assert.rejects(Promise.reject(5), { code: 'FOO' }, 'AAAAA'),
handler.bind(null, false, 5)
));
promises.push(assert.rejects(
assert.rejects(Promise.reject(err), { code: 'FOO' }, 'AAAAA'),
handler.bind(null, false, err)
));
}
// Make sure all async code gets properly executed. // Make sure all async code gets properly executed.
Promise.all(promises).then(common.mustCall()); Promise.all(promises).then(common.mustCall());