Skip to content

Commit 9ad464b

Browse files
split err.stack at the trailing frame block so embedded stacks in err.message render once
1 parent 6695fba commit 9ad464b

2 files changed

Lines changed: 63 additions & 18 deletions

File tree

lib/reporters/base.js

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -404,38 +404,58 @@ var getFullErrorStack = function (err, seen) {
404404
}
405405

406406
var message;
407+
var usedInspect = false;
407408

408409
if (typeof err.inspect === "function") {
409410
message = err.inspect() + "";
411+
usedInspect = true;
410412
} else if (err.message && typeof err.message.toString === "function") {
411413
message = err.message + "";
412414
} else {
413415
message = "";
414416
}
415417

416-
var msg;
417-
var stack = err.stack || message;
418-
var index = message ? stack.indexOf(message) : -1;
418+
var rawStack = err.stack || message;
419+
var lines = rawStack.split("\n");
420+
var frameStart = lines.length;
421+
for (var i = lines.length - 1; i >= 0; i--) {
422+
if (/^\s+at\s/.test(lines[i])) {
423+
frameStart = i;
424+
} else {
425+
break;
426+
}
427+
}
419428

420-
if (index === -1) {
421-
msg = message;
429+
var msg;
430+
var stack;
431+
var splitSucceeded = false;
432+
if (frameStart < lines.length) {
433+
stack = lines.slice(frameStart).join("\n");
434+
msg = usedInspect ? message : lines.slice(0, frameStart).join("\n");
435+
splitSucceeded = true;
422436
} else {
423-
index += message.length;
424-
msg = stack.slice(0, index);
425-
// remove msg from stack
426-
stack = stack.slice(index + 1);
427-
428-
if (err.cause) {
429-
seen = seen || new Set();
430-
seen.add(err);
431-
const causeStack = getFullErrorStack(err.cause, seen);
432-
stack +=
433-
"\n Caused by: " +
434-
causeStack.msg +
435-
(causeStack.stack ? "\n" + causeStack.stack : "");
437+
var index = message ? rawStack.indexOf(message) : -1;
438+
if (index === -1) {
439+
msg = message;
440+
stack = rawStack;
441+
} else {
442+
index += message.length;
443+
msg = rawStack.slice(0, index);
444+
stack = rawStack.slice(index + 1);
445+
splitSucceeded = true;
436446
}
437447
}
438448

449+
if (splitSucceeded && err.cause) {
450+
seen = seen || new Set();
451+
seen.add(err);
452+
const causeStack = getFullErrorStack(err.cause, seen);
453+
stack +=
454+
"\n Caused by: " +
455+
causeStack.msg +
456+
(causeStack.stack ? "\n" + causeStack.stack : "");
457+
}
458+
439459
return {
440460
message,
441461
msg,

test/reporters/base.spec.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,31 @@ describe("Base reporter", function () {
568568
);
569569
});
570570

571+
it("should not duplicate the message when it contains an embedded stack", function () {
572+
var embeddedMessage =
573+
"An error occured with following trace:\n\nError\n at inner (foo.js:1:1)\n at outer (foo.js:2:2)";
574+
var err = {
575+
message: embeddedMessage,
576+
stack:
577+
"Error: " +
578+
embeddedMessage +
579+
"\n at outer (foo.js:2:2)\n at runTest (lib/runner.js:1:1)",
580+
showDiff: false,
581+
};
582+
var test = makeTest(err);
583+
584+
list([test]);
585+
586+
var errOut = stdout.join("\n").trim();
587+
expect(
588+
errOut.match(/Error: An error occured with following trace:/g),
589+
"to have length",
590+
1,
591+
);
592+
expect(errOut, "to contain", "at runTest (lib/runner.js:1:1)");
593+
expect(errOut.match(/at inner \(foo\.js:1:1\)/g), "to have length", 1);
594+
});
595+
571596
it("should not add cause trail if error does not contain message", function () {
572597
var err = {
573598
message: "Error",

0 commit comments

Comments
 (0)