Skip to content

Commit

Permalink
Fix stack traces in throw assertions
Browse files Browse the repository at this point in the history
Fixes #1372.
  • Loading branch information
dflupu authored and novemberborn committed Jan 27, 2019
1 parent 8ad5efd commit ad087f2
Show file tree
Hide file tree
Showing 6 changed files with 404 additions and 40 deletions.
14 changes: 13 additions & 1 deletion lib/assert.js
Expand Up @@ -36,6 +36,7 @@ class AssertionError extends Error {
this.assertion = opts.assertion;
this.fixedSource = opts.fixedSource;
this.improperUsage = opts.improperUsage || false;
this.actualStack = opts.actualStack;
this.operator = opts.operator;
this.values = opts.values || [];

Expand Down Expand Up @@ -147,11 +148,14 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
});
}

const actualStack = actual.stack;

if (hasOwnProperty(expectations, 'is') && actual !== expectations.is) {
throw new AssertionError({
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected to be strictly equal to:', expectations.is)
Expand All @@ -164,6 +168,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected instance of:', expectations.instanceOf)
Expand All @@ -176,6 +181,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected name to equal:', expectations.name)
Expand All @@ -188,6 +194,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected message to equal:', expectations.message)
Expand All @@ -200,6 +207,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected message to match:', expectations.message)
Expand All @@ -212,6 +220,7 @@ function assertExpectations({assertion, actual, expectations, message, prefix, s
assertion,
message,
stack,
actualStack,
values: [
formatWithLabel(`${prefix} unexpected exception:`, actual),
formatWithLabel('Expected code to equal:', expectations.code)
Expand Down Expand Up @@ -433,6 +442,7 @@ function wrapAssertions(callbacks) {
fail(this, new AssertionError({
assertion: 'throwsAsync',
message,
actualStack: actual.stack,
values: [formatWithLabel('Function threw synchronously. Use `t.throws()` instead:', actual)]
}));
return Promise.resolve();
Expand Down Expand Up @@ -467,6 +477,7 @@ function wrapAssertions(callbacks) {
fail(this, new AssertionError({
assertion: 'notThrows',
message,
actualStack: error.stack,
values: [formatWithLabel('Function threw:', error)]
}));
return;
Expand All @@ -493,7 +504,7 @@ function wrapAssertions(callbacks) {
throw new AssertionError({
assertion: 'notThrowsAsync',
message,
stack,
actualStack: stack,
values: [formatWithLabel(`${wasReturned ? 'Returned promise' : 'Promise'} rejected with:`, reason)]
});
});
Expand All @@ -513,6 +524,7 @@ function wrapAssertions(callbacks) {
fail(this, new AssertionError({
assertion: 'notThrowsAsync',
message,
actualStack: error.stack,
values: [formatWithLabel('Function threw:', error)]
}));
return Promise.resolve();
Expand Down
4 changes: 4 additions & 0 deletions lib/serialize-error.js
Expand Up @@ -60,6 +60,10 @@ function trySerializeError(err, shouldBeautifyStack) {
stack
};

if (err.actualStack) {
retval.stack = shouldBeautifyStack ? beautifyStack(err.actualStack) : err.actualStack;
}

if (retval.avaAssertionError) {
retval.improperUsage = err.improperUsage;
retval.message = err.message;
Expand Down
29 changes: 29 additions & 0 deletions test/fixture/report/regular/traces-in-t-throws.js
@@ -0,0 +1,29 @@
import test from '../../../..';

function throwError() {
throw new Error('uh-oh');
}

function returnRejectedPromise() {
return Promise.reject(new Error('uh-oh'));
}

test('throws', t => {
t.throws(() => throwError(), TypeError);
});

test('notThrows', t => {
t.notThrows(() => throwError());
});

test('notThrowsAsync', t => {
t.notThrowsAsync(() => throwError());
});

test('throwsAsync', t => {
t.throwsAsync(() => throwError(), TypeError);
});

test('throwsAsync different error', t => {
return t.throwsAsync(returnRejectedPromise, TypeError);
});

0 comments on commit ad087f2

Please sign in to comment.