Skip to content

Commit

Permalink
Merge branch 'master' into repo/default-list-style
Browse files Browse the repository at this point in the history
  • Loading branch information
marjys committed Mar 5, 2024
2 parents 422563d + 3735873 commit c358aae
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 24 deletions.
70 changes: 51 additions & 19 deletions lib/reporters/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,56 @@ var generateDiff = (exports.generateDiff = function (actual, expected) {
}
});

/**
* Traverses err.cause and returns all stack traces
*
* @private
* @param {Error} err
* @param {Set<Error>} [seen]
* @return {{ message: string, msg: string, stack: string }}
*/
var getFullErrorStack = function (err, seen) {
if (seen && seen.has(err)) {
return { message: '', msg: '<circular>', stack: '' };
}

var message;

if (typeof err.inspect === 'function') {
message = err.inspect() + '';
} else if (err.message && typeof err.message.toString === 'function') {
message = err.message + '';
} else {
message = '';
}

var msg;
var stack = err.stack || message;
var index = message ? stack.indexOf(message) : -1;

if (index === -1) {
msg = message;
} else {
index += message.length;
msg = stack.slice(0, index);
// remove msg from stack
stack = stack.slice(index + 1);

if (err.cause) {
seen = seen || new Set();
seen.add(err);
const causeStack = getFullErrorStack(err.cause, seen)
stack += '\n Caused by: ' + causeStack.msg + (causeStack.stack ? '\n' + causeStack.stack : '');
}
}

return {
message,
msg,
stack
};
};

/**
* Outputs the given `failures` as a list.
*
Expand All @@ -241,7 +291,6 @@ exports.list = function (failures) {
color('error stack', '\n%s\n');

// msg
var msg;
var err;
if (test.err && test.err.multiple) {
if (multipleTest !== test) {
Expand All @@ -252,25 +301,8 @@ exports.list = function (failures) {
} else {
err = test.err;
}
var message;
if (typeof err.inspect === 'function') {
message = err.inspect() + '';
} else if (err.message && typeof err.message.toString === 'function') {
message = err.message + '';
} else {
message = '';
}
var stack = err.stack || message;
var index = message ? stack.indexOf(message) : -1;

if (index === -1) {
msg = message;
} else {
index += message.length;
msg = stack.slice(0, index);
// remove msg from stack
stack = stack.slice(index + 1);
}
var { message, msg, stack } = getFullErrorStack(err);

// uncaught
if (err.uncaught) {
Expand Down
21 changes: 16 additions & 5 deletions lib/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -443,11 +443,22 @@ Runner.prototype.fail = function (test, err, force) {
err = thrown2Error(err);
}

try {
err.stack =
this.fullStackTrace || !err.stack ? err.stack : stackFilter(err.stack);
} catch (ignore) {
// some environments do not take kindly to monkeying with the stack
// Filter the stack traces
if (!this.fullStackTrace) {
const alreadyFiltered = new Set();
let currentErr = err;

while (currentErr && currentErr.stack && !alreadyFiltered.has(currentErr)) {
alreadyFiltered.add(currentErr);

try {
currentErr.stack = stackFilter(currentErr.stack);
} catch (ignore) {
// some environments do not take kindly to monkeying with the stack
}

currentErr = currentErr.cause;
}
}

this.emit(constants.EVENT_TEST_FAIL, test, err);
Expand Down
102 changes: 102 additions & 0 deletions test/reporters/base.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,108 @@ describe('Base reporter', function () {
expect(errOut, 'to be', '1) test title:\n Error\n foo\n bar');
});

describe('error causes', function () {
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);

list([test]);

var errOut = stdout.join('\n').trim();
expect(
errOut,
'to be',
'1) test title:\n Error\n foo\n bar\n Caused by: Cause1\n bar\n foo\n Caused by: Cause2\n abc\n xyz'
);
});

it('should not get stuck in a hypothetical circular error cause trail', function () {
var err1 = {
message: 'Error',
stack: 'Error\nfoo\nbar',
showDiff: false,
};
var err2 = {
message: 'Cause1',
stack: 'Cause1\nbar\nfoo',
showDiff: false,
cause: err1
}
err1.cause = err2;

var test = makeTest(err1);

list([test]);

var errOut = stdout.join('\n').trim();
expect(
errOut,
'to be',
'1) test title:\n Error\n foo\n bar\n Caused by: Cause1\n bar\n foo\n Caused by: <circular>'
);
});

it("should set an empty cause if neither 'inspect' nor 'message' is set", function () {
var err = {
message: 'Error',
stack: 'Error\nfoo\nbar',
showDiff: false,
cause: {
showDiff: false,
}
};

var test = makeTest(err);

list([test]);

var errOut = stdout.join('\n').trim();
expect(
errOut,
'to be',
'1) test title:\n Error\n foo\n bar\n Caused by:'
);
});

it('should not add cause trail if error does not contain message', function () {
var err = {
message: 'Error',
stack: 'foo\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);

list([test]);

var errOut = stdout.join('\n').trim();
expect(errOut, 'to be', '1) test title:\n Error\n foo\n bar');
});
});

it('should list multiple Errors per test', function () {
var err = new Error('First Error');
err.multiple = [new Error('Second Error - same test')];
Expand Down
34 changes: 34 additions & 0 deletions test/unit/runner.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,22 @@ describe('Runner', function () {
});
runner.fail(hook, err);
});

it('should prettify stack-traces in error cause trail', function (done) {
var hook = new Hook();
hook.parent = suite;
var causeErr = new Error();
// Fake stack-trace
causeErr.stack = stack.join('\n');
var err = new Error();
err.cause = causeErr;

runner.on(EVENT_TEST_FAIL, function (_hook, _err) {
expect(_err.cause.stack, 'to be', stack.slice(0, 3).join('\n'));
done();
});
runner.fail(hook, err);
});
});

describe('long', function () {
Expand All @@ -647,6 +663,24 @@ describe('Runner', function () {
});
runner.fail(hook, err);
});

it('should display full stack-traces in error cause trail', function (done) {
var hook = new Hook();
hook.parent = suite;
var causeErr = new Error();
// Fake stack-trace
causeErr.stack = stack.join('\n');
var err = new Error();
err.cause = causeErr;
// Add --stack-trace option
runner.fullStackTrace = true;

runner.on(EVENT_TEST_FAIL, function (_hook, _err) {
expect(_err.cause.stack, 'to be', stack.join('\n'));
done();
});
runner.fail(hook, err);
});
});

describe('ginormous', function () {
Expand Down

0 comments on commit c358aae

Please sign in to comment.