Skip to content

Commit f6a42ba

Browse files
committed
Record stack for async throws assertions
If the assertion fails, the AssertionError no longer has access to the stack of when the assertion was called. Record it before entering the promise chain.
1 parent 880e87e commit f6a42ba

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

lib/assert.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ class AssertionError extends Error {
2929
}
3030
exports.AssertionError = AssertionError;
3131

32+
function getStack() {
33+
const obj = {};
34+
Error.captureStackTrace(obj, getStack);
35+
return obj.stack;
36+
}
37+
3238
function wrapAssertions(callbacks) {
3339
const pass = callbacks.pass;
3440
const pending = callbacks.pending;
@@ -138,7 +144,7 @@ function wrapAssertions(callbacks) {
138144
coreAssertThrowsErrorArg = err;
139145
}
140146

141-
const test = fn => {
147+
const test = (fn, stack) => {
142148
let actual;
143149
let threw = false;
144150
try {
@@ -160,13 +166,16 @@ function wrapAssertions(callbacks) {
160166
throw new AssertionError({
161167
assertion: 'throws',
162168
message,
169+
stack,
163170
values
164171
});
165172
}
166173
};
167174

168175
if (promise) {
169-
const intermediate = promise.then(makeNoop, makeRethrow).then(test);
176+
// Record stack before it gets lost in the promise chain.
177+
const stack = getStack();
178+
const intermediate = promise.then(makeNoop, makeRethrow).then(fn => test(fn, stack));
170179
pending(this, intermediate);
171180
// Don't reject the returned promise, even if the assertion fails.
172181
return intermediate.catch(noop);
@@ -196,20 +205,23 @@ function wrapAssertions(callbacks) {
196205
return;
197206
}
198207

199-
const test = fn => {
208+
const test = (fn, stack) => {
200209
try {
201210
coreAssert.doesNotThrow(fn);
202211
} catch (err) {
203212
throw new AssertionError({
204213
assertion: 'notThrows',
205214
message,
215+
stack,
206216
values: [formatAssertError.formatWithLabel('Threw:', err.actual)]
207217
});
208218
}
209219
};
210220

211221
if (promise) {
212-
const intermediate = promise.then(noop, reason => test(makeRethrow(reason)));
222+
// Record stack before it gets lost in the promise chain.
223+
const stack = getStack();
224+
const intermediate = promise.then(noop, reason => test(makeRethrow(reason), stack));
213225
pending(this, intermediate);
214226
// Don't reject the returned promise, even if the assertion fails.
215227
return intermediate.catch(noop);

0 commit comments

Comments
 (0)