diff --git a/lib/reporters/base.js b/lib/reporters/base.js index 40b5996461..e96235d60c 100644 --- a/lib/reporters/base.js +++ b/lib/reporters/base.js @@ -221,6 +221,23 @@ var generateDiff = (exports.generateDiff = function (actual, expected) { } }); +/** + * This function dumps long stack traces for exceptions having + * an Error cause() method + * + * @public + * @memberof Mocha.reporters.Base + * @param {Error} ex + * @return {string} + */ +exports.getFullErrorStack = function (err, message) { + var ret = err.stack || message || ''; + if (err.cause) { + ret += '\n' + ' ' + 'Caused by: ' + exports.getFullErrorStack(err.cause); + } + return ret; +}; + /** * Outputs the given `failures` as a list. * @@ -260,7 +277,7 @@ exports.list = function (failures) { } else { message = ''; } - var stack = err.stack || message; + var stack = exports.getFullErrorStack(err, message); var index = message ? stack.indexOf(message) : -1; if (index === -1) { diff --git a/lib/runner.js b/lib/runner.js index 12807725fb..b02ddfd473 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -450,6 +450,22 @@ Runner.prototype.fail = function (test, err, force) { // some environments do not take kindly to monkeying with the stack } + // Support for error causes + try { + let nextErr = err; + + while (nextErr.cause && nextErr.cause.stack) { + nextErr = nextErr.cause; + + err.stack += + '\n' + (this.fullStackTrace || !nextErr.stack) + ? nextErr.stack + : stackFilter(nextErr.stack); + } + } catch (ignore) { + // some environments do not take kindly to monkeying with the stack + } + this.emit(constants.EVENT_TEST_FAIL, test, err); }; diff --git a/test/reporters/base.spec.js b/test/reporters/base.spec.js index 6b30b2ccc7..66c1cca0cb 100644 --- a/test/reporters/base.spec.js +++ b/test/reporters/base.spec.js @@ -477,6 +477,32 @@ describe('Base reporter', function () { expect(errOut, 'to be', '1) test title:'); }); + it('should append any error cause trail to stack traces', function () { + var err = { + message: 'Error', + stack: 'Error\nfoo\nbar', + showDiff: false, + cause: { + message: 'Cause1', + stack: 'Cause1\nbar\nfoo', + showDiff: false, + cause: { + message: 'Cause2', + stack: 'Cause2\nabc\nxyz', + showDiff: false + } + } + }; + var test = makeTest(err); + + Base.list([test]); + + var errOut = stdout.join('\n').trim(); + errOut.should.equal( + '1) test title:\n Error\n foo\n bar\n Caused by: Cause Stack' + ); + }); + it('should not modify stack if it does not contain message', function () { var err = { message: 'Error',