Skip to content
Permalink
Browse files

Preserve the stack of the actual error.

  • Loading branch information...
papandreou committed Jul 23, 2016
1 parent 6ee3731 commit 8f3638f4d7b19209717997c8bfd983f6e44da445
@@ -488,6 +488,8 @@ Unexpected.prototype.fail = function (arg) {
var value = arg[key];
if (key === 'diff') {
error.createDiff = value;
} else if (key === 'stack') {
error._stack = value;
} else if (key !== 'message') {
error[key] = value;
}
@@ -223,6 +223,9 @@ UnexpectedError.prototype.serializeMessage = function (outputFormat) {
format: htmlFormat ? 'text' : outputFormat
}).toString() + '\n';

if (this._stack) {
this.stack = this._stack;
}
if (this.stack && !this.useFullStackTrace) {
var newStack = [];
var removedFrames = false;
@@ -595,11 +595,16 @@ module.exports = function (expect) {
expect.addAssertion('<function> to error [with] <any>', function (expect, subject, arg) {
return expect(subject, 'to error').then(function (error) {
expect.errorMode = 'nested';
if (error.isUnexpected && (typeof arg === 'string' || isRegExp(arg))) {
return expect(error, 'to have message', arg);
} else {
return expect(error, 'to satisfy', arg);
}
return expect.withError(function () {
if (error.isUnexpected && (typeof arg === 'string' || isRegExp(arg))) {
return expect(error, 'to have message', arg);
} else {
return expect(error, 'to satisfy', arg);
}
}, function (e) {
e._stack = error && error.stack;
throw e;
});
});
});

@@ -614,9 +619,12 @@ module.exports = function (expect) {
}
}).caught(function (error) {
expect.errorMode = 'nested';
expect.fail(function (output) {
output.error(threw ? 'threw' : 'returned promise rejected with').error(': ')
.appendErrorMessage(error);
expect.fail({
output: function (output) {
output.error(threw ? 'threw' : 'returned promise rejected with').error(': ')
.appendErrorMessage(error);
},
stack: error && error.stack
});
});
});
@@ -634,8 +642,11 @@ module.exports = function (expect) {

if (threw) {
expect.errorMode = 'nested';
expect.fail(function (output) {
output.error('threw: ').appendErrorMessage(error);
expect.fail({
output: function (output) {
output.error('threw: ').appendErrorMessage(error);
},
stack: error && error.stack
});
}
});
@@ -655,11 +666,16 @@ module.exports = function (expect) {
// in the presence of a matcher an error must have been thrown.

expect.errorMode = 'nested';
if (isUnexpected && (typeof arg === 'string' || isRegExp(arg))) {
return expect(error.getErrorMessage('text').toString(), 'to satisfy', arg);
} else {
return expect(error, 'to satisfy', arg);
}
return expect.withError(function () {
if (isUnexpected && (typeof arg === 'string' || isRegExp(arg))) {
return expect(error.getErrorMessage('text').toString(), 'to satisfy', arg);
} else {
return expect(error, 'to satisfy', arg);
}
}, function (err) {
err._stack = error && error.stack;
throw err;
});
});
});

@@ -1404,15 +1420,20 @@ module.exports = function (expect) {
expect.addAssertion('<Promise> to be rejected with <any>', function (expect, subject, value) {
expect.errorMode = 'nested';
return expect(subject, 'to be rejected').then(function (err) {
if (err && err._isUnexpected && (typeof value === 'string' || isRegExp(value))) {
return expect(err, 'to have message', value).then(function () {
return err;
});
} else {
return expect(err, 'to satisfy', value).then(function () {
return err;
});
}
return expect.withError(function () {
if (err && err._isUnexpected && (typeof value === 'string' || isRegExp(value))) {
return expect(err, 'to have message', value).then(function () {
return err;
});
} else {
return expect(err, 'to satisfy', value).then(function () {
return err;
});
}
}, function (e) {
e._stack = err && err.stack;
throw e;
});
});
});

@@ -1430,11 +1451,14 @@ module.exports = function (expect) {
}).then(function (fulfillmentValue) {
return fulfillmentValue;
}, function (err) {
expect.fail(function (output) {
output.appendInspected(subject).sp().text('unexpectedly rejected');
if (typeof err !== 'undefined') {
output.sp().text('with').sp().appendInspected(err);
}
expect.fail({
output: function (output) {
output.appendInspected(subject).sp().text('unexpectedly rejected');
if (typeof err !== 'undefined') {
output.sp().text('with').sp().appendInspected(err);
}
},
stack: err && err.stack
});
});
});
@@ -1483,7 +1507,12 @@ module.exports = function (expect) {
}
});
}, function (err) {
return expect.shift(err);
return expect.withError(function () {
return expect.shift(err);
}, function (e) {
e._stack = err && err.stack;
throw e;
});
});
});

@@ -1509,11 +1538,14 @@ module.exports = function (expect) {
output.sp().appendItems(rest, ', ');
}
};
expect.fail(function (output) {
output.appendInspected(subject).sp().text('unexpectedly rejected');
if (typeof err !== 'undefined') {
output.sp().text('with').sp().appendInspected(err);
}
expect.fail({
output: function (output) {
output.appendInspected(subject).sp().text('unexpectedly rejected');
if (typeof err !== 'undefined') {
output.sp().text('with').sp().appendInspected(err);
}
},
stack: err && err.stack
});
});
});
@@ -75,7 +75,9 @@ module.exports = function createWrappedExpectProto(unexpected) {
if (isPendingPromise(result)) {
result = result.then(undefined, function (e) {
if (e && e._isUnexpected) {
throw new UnexpectedError(that, e);
var wrappedError = new UnexpectedError(that, e);
wrappedError._stack = e._stack;
throw wrappedError;
}
throw e;
});
@@ -86,6 +88,7 @@ module.exports = function createWrappedExpectProto(unexpected) {
} catch (e) {
if (e && e._isUnexpected) {
var wrappedError = new UnexpectedError(that, e);
wrappedError._stack = e._stack;
if (that._context.serializeErrorsFromWrappedExpect) {
expect.setErrorMessage(wrappedError);
}
@@ -691,7 +691,7 @@ module.exports = function (expect) {
}
});

var unexpectedErrorMethodBlacklist = ['output', '_isUnexpected', 'htmlMessage', '_hasSerializedErrorMessage', 'expect', 'assertion'].reduce(function (result, prop) {
var unexpectedErrorMethodBlacklist = ['output', '_isUnexpected', 'htmlMessage', '_hasSerializedErrorMessage', 'expect', 'assertion', '_stack'].reduce(function (result, prop) {
result[prop] = true;
return result;
}, {});
@@ -139,4 +139,38 @@ describe('to be fulfilled assertion', function () {
);
});
});

it('should use the stack of the thrown error when failing', function () {
return expect(function () {
return expect(function () {
return expect.promise(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to be fulfilled');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});

describe('with another promise library', function () {
var Promise = typeof weknowhow === 'undefined' ?
require('rsvp').Promise :
window.RSVP.Promise;

it('should use the stack of the thrown error when failing', function () {
return expect(function () {
return expect(function () {
return new Promise(function (resolve, reject) {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to be fulfilled');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});
});
@@ -175,4 +175,38 @@ describe('to be rejected assertion', function () {
}, 'to be rejected');
});
});

it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return expect.promise(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to be rejected with', 'foobar');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});

describe('with another promise library', function () {
var Promise = typeof weknowhow === 'undefined' ?
require('rsvp').Promise :
window.RSVP.Promise;

it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return new Promise(function (resolve, reject) {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to be rejected with', 'foobar');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});
});
@@ -69,4 +69,76 @@ describe('to error assertion', function () {
expect(123, 'to equal', 456);
}, 'to error', /expected 123 to equal 456/);
});

describe('without the not flag', function () {
it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return expect.promise(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to error with', 'foobar');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});

describe('with another promise library', function () {
var Promise = typeof weknowhow === 'undefined' ?
require('rsvp').Promise :
window.RSVP.Promise;

it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return new Promise(function (resolve, reject) {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'to error with', 'foobar');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});
});

describe('with the not flag', function () {
it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return expect.promise(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'not to error');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});

describe('with another promise library', function () {
var Promise = typeof weknowhow === 'undefined' ?
require('rsvp').Promise :
window.RSVP.Promise;

it('should use the stack of the rejection reason when failing', function () {
return expect(function () {
return expect(function () {
return new Promise(function (resolve, reject) {
(function thisIsImportant() {
throw new Error('argh');
}());
});
}, 'not to error');
}, 'to error', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});
});
});
@@ -145,4 +145,32 @@ describe('to throw assertion', function () {
'expected function () { throw null; } not to throw\n' +
' threw: null');
});

describe('with the not flag', function () {
it('should use the stack of the thrown error when failing', function () {
expect(function () {
expect(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
}, 'not to throw');
}, 'to throw', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});

describe('without the not flag', function () {
it('should use the stack of the thrown (but wrong) error when failing', function () {
expect(function () {
expect(function () {
(function thisIsImportant() {
throw new Error('argh');
}());
}, 'to throw', 'foo');
}, 'to throw', function (err) {
expect(err.stack, 'to match', /at thisIsImportant/);
});
});
});
});

0 comments on commit 8f3638f

Please sign in to comment.
You can’t perform that action at this time.