Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,28 @@ export function createEsmAndCjsTests(
const createdRunners = new Set<ReturnType<typeof createRunner>>();

callback(
() => trackRunner(createdRunners, createRunner(paths.esm.scenario).withFlags('--import', paths.esm.instrument)),
() => {
const runner = createRunner(paths.esm.scenario).withFlags('--import', paths.esm.instrument);
// Expected failure — don't dump the child's captured output for these.
if (options?.failsOnEsm) {
runner.suppressErrorLogs();
}
return trackRunner(createdRunners, runner);
},
esmTestFn,
'esm',
tmpDirPath,
);

callback(
() => trackRunner(createdRunners, createRunner(paths.cjs.scenario).withFlags('--require', paths.cjs.instrument)),
() => {
const runner = createRunner(paths.cjs.scenario).withFlags('--require', paths.cjs.instrument);
// Expected failure — don't dump the child's captured output for these.
if (options?.failsOnCjs) {
runner.suppressErrorLogs();
}
return trackRunner(createdRunners, runner);
},
cjsTestFn,
'cjs',
tmpDirPath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ export function createRunner(...paths: string[]) {
let withSentryServer = false;
let dockerOptions: DockerOptions | undefined;
let ensureNoErrorOutput = false;
// When set, the test using this runner expects `completed()` to reject (e.g. `test.fails` variants
// created via `createEsmAndCjsTests` with `failsOnEsm`/`failsOnCjs`). We suppress the captured-log
// dump in that case, since the failure is expected and the output would just be noise.
let suppressErrorLogs = false;
const logs: string[] = [];

if (testPath.endsWith('.ts')) {
Expand Down Expand Up @@ -227,6 +231,14 @@ export function createRunner(...paths: string[]) {
ensureNoErrorOutput = true;
return this;
},
/**
* Mark this runner's test as expected to fail (i.e. `completed()` is expected to reject).
* Suppresses the captured-log dump so expected failures don't emit noisy output.
*/
suppressErrorLogs: function () {
suppressErrorLogs = true;
return this;
},
start: function (): StartResult {
let isComplete = false;
let completeError: Error | undefined;
Expand All @@ -248,6 +260,33 @@ export function createRunner(...paths: string[]) {
child?.kill();
}

/**
* Print everything the child process wrote to stdout/stderr. Called when a test fails or
* times out so the captured output is visible in CI logs. Skipped when `DEBUG` is set, since
* that already streams the same lines live as they arrive.
*/
function dumpCapturedLogs(): void {
// Skip when the failure is expected (`test.fails` variants) — the output would just be noise.
// In debug mode the same lines are already streamed live, so skip then too.
if (process.env.DEBUG || suppressErrorLogs) {
return;
}

// eslint-disable-next-line no-console
console.log(`\n--- Captured child process output for ${testPath} ---`);
if (logs.length === 0) {
// eslint-disable-next-line no-console
console.log('(no output captured)');
} else {
for (const line of logs) {
// eslint-disable-next-line no-console
console.log(line);
}
}
// eslint-disable-next-line no-console
console.log('--- End of captured child process output ---\n');
}

/** Called after each expect callback to check if we're complete */
function expectCallbackCalled(): void {
envelopeCount++;
Expand Down Expand Up @@ -472,9 +511,18 @@ export function createRunner(...paths: string[]) {

return {
completed: async function (): Promise<void> {
await waitFor(() => isComplete, 120_000, 'Timed out waiting for test to complete');
try {
await waitFor(() => isComplete, 120_000, 'Timed out waiting for test to complete');
} catch (e) {
// On timeout, dump the captured child output (same info `DEBUG=1` would have streamed live)
// so CI failures are diagnosable without re-running locally with DEBUG enabled.
dumpCapturedLogs();
throw e;
}

if (completeError) {
// Same rationale as the timeout branch: surface what the child actually logged before failing.
dumpCapturedLogs();
throw completeError;
}
},
Expand Down
Loading