From 75463a9004a62d120e0590f86adb923f28c9cd13 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Apr 2019 03:12:42 +0200 Subject: [PATCH] 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 Reviewed-By: James M Snell --- lib/assert.js | 20 ++++++++++---------- test/parallel/test-assert-async.js | 25 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 10 deletions(-) diff --git a/lib/assert.js b/lib/assert.js index 51ee781b59b472..db0a2283e63db9 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -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 (!message) { // Create placeholder objects to create a nice output. @@ -513,24 +513,24 @@ function compareExceptionKey(actual, expected, key, message, keys) { actual: a, expected: b, operator: 'deepStrictEqual', - stackStartFn: assert.throws + stackStartFn: fn }); err.actual = actual; err.expected = expected; - err.operator = 'throws'; + err.operator = fn.name; throw err; } innerFail({ actual, expected, message, - operator: 'throws', - stackStartFn: assert.throws + operator: fn.name, + stackStartFn: fn }); } } -function expectedException(actual, expected, msg) { +function expectedException(actual, expected, msg, fn) { if (typeof expected !== 'function') { if (isRegExp(expected)) return expected.test(actual); @@ -548,9 +548,9 @@ function expectedException(actual, expected, msg) { expected, message: msg, operator: 'deepStrictEqual', - stackStartFn: assert.throws + stackStartFn: fn }); - err.operator = 'throws'; + err.operator = fn.name; throw err; } @@ -570,7 +570,7 @@ function expectedException(actual, expected, msg) { expected[key].test(actual[key])) { continue; } - compareExceptionKey(actual, expected, key, msg, keys); + compareExceptionKey(actual, expected, key, msg, keys, fn); } return true; } @@ -676,7 +676,7 @@ function expectsError(stackStartFn, actual, error, message) { stackStartFn }); } - if (error && expectedException(actual, error, message) === false) { + if (error && !expectedException(actual, error, message, stackStartFn)) { throw actual; } } diff --git a/test/parallel/test-assert-async.js b/test/parallel/test-assert-async.js index c2b422061721a1..d461e403300b34 100644 --- a/test/parallel/test-assert-async.js +++ b/test/parallel/test-assert-async.js @@ -96,6 +96,7 @@ promises.push(assert.rejects( assert.strictEqual(err.message, 'Got unwanted rejection.\nActual message: "Failed"'); assert.strictEqual(err.operator, 'doesNotReject'); + assert.ok(err.stack); assert.ok(!err.stack.includes('at Function.doesNotReject')); 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. Promise.all(promises).then(common.mustCall());