From 1bc9f4612df4066e29e55ec5471fc0f37dac34e4 Mon Sep 17 00:00:00 2001 From: Aston Monteiro <152646326+Aston8@users.noreply.github.com> Date: Tue, 4 Aug 2026 10:40:12 +0000 Subject: [PATCH 1/2] test_runner: create reporter destination directories --- lib/internal/test_runner/utils.js | 11 +++++++---- test/parallel/test-runner-reporters.js | 13 +++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 3590d3ef79b4..43a331e34297 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -35,8 +35,8 @@ const { const { AsyncResource } = require('async_hooks'); const { tracingChannel } = require('diagnostics_channel'); -const { relative, sep, resolve } = require('path'); -const { createWriteStream, readFileSync } = require('fs'); +const { dirname, relative, sep, resolve } = require('path'); +const { createWriteStream, mkdirSync, readFileSync } = require('fs'); const { pathToFileURL } = require('internal/url'); const { getOptionValue } = require('internal/options'); const { green, yellow, red, white, shouldColorize } = require('internal/util/colors'); @@ -199,8 +199,11 @@ function parsePreviousRuns(rerunFailuresFilePath) { async function getReportersMap(reporters, destinations) { return SafePromiseAllReturnArrayLike(reporters, async (name, i) => { - const destination = kBuiltinDestinations.get(destinations[i]) ?? - createWriteStream(destinations[i], { __proto__: null, flush: true }); + const destinationPath = destinations[i]; + const destination = kBuiltinDestinations.get(destinationPath) ?? ( + mkdirSync(dirname(destinationPath), { recursive: true }), + createWriteStream(destinationPath, { __proto__: null, flush: true }) + ); // Load the test reporter passed to --test-reporter let reporter = tryBuiltinReporter(name); diff --git a/test/parallel/test-runner-reporters.js b/test/parallel/test-runner-reporters.js index 7fed79d45b48..f050e2cf7342 100644 --- a/test/parallel/test-runner-reporters.js +++ b/test/parallel/test-runner-reporters.js @@ -76,6 +76,19 @@ describe('node:test reporters', { concurrency: true }, () => { assert.match(fileContents, /✖ nested/); }); + it('should create parent directories for a file destination', async () => { + const file = tmpdir.resolve(`${tmpFiles++}/nested/report.out`); + const child = spawnSync(process.execPath, + ['--test', '--test-reporter', 'dot', '--test-reporter-destination', file, testFile]); + assert.strictEqual(child.stderr.toString(), ''); + assert.strictEqual(child.stdout.toString(), ''); + const fileContents = fs.readFileSync(file, 'utf8'); + assert.match(fileContents, /\.XX\.\n/); + assert.match(fileContents, /Failed tests:/); + assert.match(fileContents, /✖ failing/); + assert.match(fileContents, /✖ nested/); + }); + it('should disallow using v8-serializer as reporter', async () => { const child = spawnSync(process.execPath, ['--test', '--test-reporter', 'v8-serializer', testFile]); assert.strictEqual(child.stdout.toString(), ''); From e7c01bb89fa054f0ea3084b8a7fad8ce1c9147a2 Mon Sep 17 00:00:00 2001 From: Aston Monteiro <152646326+Aston8@users.noreply.github.com> Date: Tue, 4 Aug 2026 18:42:59 +0530 Subject: [PATCH 2/2] Update lib/internal/test_runner/utils.js Co-authored-by: Aviv Keller --- lib/internal/test_runner/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index 43a331e34297..68d23799e06d 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -201,7 +201,7 @@ async function getReportersMap(reporters, destinations) { return SafePromiseAllReturnArrayLike(reporters, async (name, i) => { const destinationPath = destinations[i]; const destination = kBuiltinDestinations.get(destinationPath) ?? ( - mkdirSync(dirname(destinationPath), { recursive: true }), + mkdirSync(dirname(destinationPath), { __proto__: null, recursive: true }), createWriteStream(destinationPath, { __proto__: null, flush: true }) );