From ea43fd7dc69ab9c05d2f3f4df9a4bbbcbecc8d92 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Tue, 2 Apr 2019 03:12:42 +0200 Subject: [PATCH 1/2] 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. --- lib/assert.js | 20 ++++++++++---------- test/parallel/test-assert-async.js | 27 +++++++++++++++++++++++++++ 2 files changed, 37 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..9a65039fa1c0d5 100644 --- a/test/parallel/test-assert-async.js +++ b/test/parallel/test-assert-async.js @@ -93,9 +93,11 @@ promises.push(assert.rejects( assert(err instanceof assert.AssertionError, `${err.name} is not instance of AssertionError`); assert.strictEqual(err.code, 'ERR_ASSERTION'); + assert.strictEqual(err.operator, 'doesNotReject'); 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 +123,30 @@ promises.push(assert.rejects( } )); +{ + const handler = (generated, actual, err) => { + assert.strictEqual(err.operator, 'rejects'); + 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()); From 789b01cfece95b9166813c596655b689c71f7ead Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 7 Apr 2019 17:06:36 +0200 Subject: [PATCH 2/2] fixup! assert: fix rejects stack trace and operator --- test/parallel/test-assert-async.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/parallel/test-assert-async.js b/test/parallel/test-assert-async.js index 9a65039fa1c0d5..d461e403300b34 100644 --- a/test/parallel/test-assert-async.js +++ b/test/parallel/test-assert-async.js @@ -93,7 +93,6 @@ promises.push(assert.rejects( assert(err instanceof assert.AssertionError, `${err.name} is not instance of AssertionError`); assert.strictEqual(err.code, 'ERR_ASSERTION'); - assert.strictEqual(err.operator, 'doesNotReject'); assert.strictEqual(err.message, 'Got unwanted rejection.\nActual message: "Failed"'); assert.strictEqual(err.operator, 'doesNotReject'); @@ -125,7 +124,6 @@ promises.push(assert.rejects( { const handler = (generated, actual, err) => { - assert.strictEqual(err.operator, 'rejects'); assert.strictEqual(err.generatedMessage, generated); assert.strictEqual(err.code, 'ERR_ASSERTION'); assert.strictEqual(err.actual, actual);