Skip to content

Commit b4e52fc

Browse files
committed
Add test for async stack traces
Fixes #78
1 parent 3bdb53a commit b4e52fc

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

test.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import process from 'node:process';
2+
import fs from 'node:fs/promises';
3+
import path from 'node:path';
4+
import {execa} from 'execa';
15
import test from 'ava';
26
import delay from 'delay';
37
import pRetry, {AbortError} from './index.js';
@@ -626,3 +630,70 @@ test.serial('unref option prevents timeout from keeping process alive', async t
626630

627631
t.true(timeoutUnrefCalled, 'timeout.unref() should be called when unref option is true');
628632
});
633+
634+
test('preserves user stack trace through async retries', async t => {
635+
const script = `
636+
import pRetry from './index.js';
637+
638+
async function foo1() {
639+
return await foo2();
640+
}
641+
642+
async function foo2() {
643+
return await pRetry(
644+
async () => {
645+
throw new Error('foo2 failed');
646+
},
647+
{
648+
retries: 1,
649+
}
650+
);
651+
}
652+
653+
async function main() {
654+
try {
655+
await foo1();
656+
} catch (error) {
657+
console.error('STACKTRACE_START');
658+
console.error(error.stack);
659+
console.error('STACKTRACE_END');
660+
}
661+
}
662+
663+
main();
664+
`.trim();
665+
666+
const temporaryFile = path.join(process.cwd(), 'p-retry-stack-test.js');
667+
await fs.writeFile(temporaryFile, script);
668+
669+
try {
670+
const {stderr, stdout} = await execa('node', [temporaryFile], {reject: false});
671+
const output = stderr + stdout;
672+
const stack = output.split('STACKTRACE_START')[1]?.split('STACKTRACE_END')[0]?.trim();
673+
674+
t.truthy(stack, 'Should capture stack trace output');
675+
676+
t.regex(stack, /Error: foo2 failed/);
677+
678+
// Print the stack for debugging if needed
679+
if (!/foo2/.test(stack) || !/foo1/.test(stack) || !/main/.test(stack)) {
680+
console.log('\n==== Full stack trace for debugging ====\n' + stack + '\n==== End stack trace ====\n');
681+
}
682+
683+
t.regex(stack, /foo2/);
684+
t.regex(stack, /foo1/);
685+
t.regex(stack, /main/);
686+
687+
// Check order
688+
const lines = stack.split('\n');
689+
const foo2Index = lines.findIndex(line => /foo2/.test(line));
690+
const foo1Index = lines.findIndex(line => /foo1/.test(line));
691+
const mainIndex = lines.findIndex(line => /main/.test(line));
692+
693+
t.true(foo2Index !== -1, 'foo2 should appear in the stack trace');
694+
t.true(foo1Index > foo2Index, 'foo1 should appear after foo2');
695+
t.true(mainIndex > foo1Index, 'main should appear after foo1');
696+
} finally {
697+
await fs.unlink(temporaryFile);
698+
}
699+
});

0 commit comments

Comments
 (0)