Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Append the cause() stacks to the main stack trace #2381

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion lib/reporters/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,28 @@ exports.cursor = {
}
};

/**
* This function dumps long stack traces for exceptions having a cause()
* method. The error classes from
* [verror](https://github.com/davepacheco/node-verror) and
* [restify v2.0](https://github.com/mcavage/node-restify) are examples.
*
* @param {Error} ex
* @return {string}
* @api public
*/

exports.getFullErrorStack = function(err, message) {
var ret = err.stack || message || '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we cannot expect err to be defined, nor can we expect it to be non-null

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@boneskull Generally I would agree, but since the lines above and below where getFullErrorStack() gets called already accesses err.message, err.inspect, err.actual etc. I think we can safely assume that at this stage the err is defined and is a non-null value, else that code would be broken as well

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, must be that we won't add a non-object error to the list. looking into that.

I hadn't noticed err.inspect here, which sets a precedent for this PR anyway.

if (err.cause && typeof (err.cause) === 'function') {
var causeErr = err.cause();
if (causeErr) {
ret += '\n' + ' ' + 'Caused by: ' + exports.getFullErrorStack(causeErr);
}
}
return ret;
};

/**
* Outut the given `failures` as a list.
*
Expand All @@ -177,7 +199,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;
var actual = err.actual;
var expected = err.expected;
Expand Down
12 changes: 9 additions & 3 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,15 @@ Runner.prototype.fail = function(test, err) {
err = new Error('the ' + type(err) + ' ' + stringify(err) + ' was thrown, throw an Error :)');
}

err.stack = (this.fullStackTrace || !err.stack)
? err.stack
: stackFilter(err.stack);
var causeErr = err;

while (causeErr) {
causeErr.stack = (this.fullStackTrace || !causeErr.stack)
? causeErr.stack
: stackFilter(causeErr.stack);

causeErr = causeErr.cause && typeof (causeErr.cause) === 'function' ? causeErr.cause() : false;
}

this.emit('fail', test, err);
};
Expand Down
15 changes: 15 additions & 0 deletions test/reporters/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,21 @@ describe('Base reporter', function () {
errOut.should.equal('1) test title:\n an error happened');
});

it('should append the cause() property to stack trace when set', function () {
var err = {
message: 'Error',
stack: 'Error\nfoo\nbar',
showDiff: false,
cause: function() { return { stack: 'Cause Stack' }; }
};
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',
Expand Down