Skip to content

Commit 34ecd1e

Browse files
pulkit-30richardlau
authored andcommitted
test_runner: fixed test object is incorrectly passed to setup()
PR-URL: #50982 Reviewed-By: Raz Luvaton <[email protected]> Reviewed-By: Moshe Atlow <[email protected]>
1 parent 38f4000 commit 34ecd1e

File tree

5 files changed

+56
-7
lines changed

5 files changed

+56
-7
lines changed

lib/internal/test_runner/harness.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ const {
2323
parseCommandLine,
2424
reporterScope,
2525
setupTestReporters,
26+
shouldColorizeTestFiles,
2627
} = require('internal/test_runner/utils');
2728
const { bigint: hrtime } = process.hrtime;
2829

@@ -205,7 +206,8 @@ function getGlobalRoot() {
205206
process.exitCode = kGenericUserError;
206207
}
207208
});
208-
reportersSetup = setupTestReporters(globalRoot);
209+
reportersSetup = setupTestReporters(globalRoot.reporter);
210+
globalRoot.harness.shouldColorizeTestFiles ||= shouldColorizeTestFiles(globalRoot);
209211
}
210212
return globalRoot;
211213
}

lib/internal/test_runner/runner.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ const {
7070
countCompletedTest,
7171
doesPathMatchFilter,
7272
isSupportedFileType,
73+
shouldColorizeTestFiles,
7374
} = require('internal/test_runner/utils');
7475
const { basename, join, resolve } = require('path');
7576
const { once } = require('events');
@@ -531,6 +532,8 @@ function run(options) {
531532
}
532533

533534
const root = createTestTree({ __proto__: null, concurrency, timeout, signal });
535+
root.harness.shouldColorizeTestFiles ||= shouldColorizeTestFiles(root);
536+
534537
if (process.env.NODE_TEST_CONTEXT !== undefined) {
535538
return root.reporter;
536539
}
@@ -556,7 +559,7 @@ function run(options) {
556559
});
557560
};
558561

559-
PromisePrototypeThen(PromisePrototypeThen(PromiseResolve(setup?.(root)), runFiles), postRun);
562+
PromisePrototypeThen(PromisePrototypeThen(PromiseResolve(setup?.(root.reporter)), runFiles), postRun);
560563

561564
return root.reporter;
562565
}

lib/internal/test_runner/utils.js

+15-5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const {
55
ArrayPrototypeFlatMap,
66
ArrayPrototypePush,
77
ArrayPrototypeReduce,
8+
ArrayPrototypeSome,
89
ObjectGetOwnPropertyDescriptor,
910
MathFloor,
1011
MathMax,
@@ -134,10 +135,18 @@ function tryBuiltinReporter(name) {
134135
return require(builtinPath);
135136
}
136137

137-
async function getReportersMap(reporters, destinations, rootTest) {
138+
function shouldColorizeTestFiles(rootTest) {
139+
// This function assumes only built-in destinations (stdout/stderr) supports coloring
140+
const { reporters, destinations } = parseCommandLine();
141+
return ArrayPrototypeSome(reporters, (_, index) => {
142+
const destination = kBuiltinDestinations.get(destinations[index]);
143+
return destination && shouldColorize(destination);
144+
});
145+
}
146+
147+
async function getReportersMap(reporters, destinations) {
138148
return SafePromiseAllReturnArrayLike(reporters, async (name, i) => {
139149
const destination = kBuiltinDestinations.get(destinations[i]) ?? createWriteStream(destinations[i]);
140-
rootTest.harness.shouldColorizeTestFiles ||= shouldColorize(destination);
141150

142151
// Load the test reporter passed to --test-reporter
143152
let reporter = tryBuiltinReporter(name);
@@ -172,12 +181,12 @@ async function getReportersMap(reporters, destinations, rootTest) {
172181
}
173182

174183
const reporterScope = new AsyncResource('TestReporterScope');
175-
const setupTestReporters = reporterScope.bind(async (rootTest) => {
184+
const setupTestReporters = reporterScope.bind(async (rootReporter) => {
176185
const { reporters, destinations } = parseCommandLine();
177-
const reportersMap = await getReportersMap(reporters, destinations, rootTest);
186+
const reportersMap = await getReportersMap(reporters, destinations);
178187
for (let i = 0; i < reportersMap.length; i++) {
179188
const { reporter, destination } = reportersMap[i];
180-
compose(rootTest.reporter, reporter).pipe(destination);
189+
compose(rootReporter, reporter).pipe(destination);
181190
}
182191
});
183192

@@ -428,5 +437,6 @@ module.exports = {
428437
parseCommandLine,
429438
reporterScope,
430439
setupTestReporters,
440+
shouldColorizeTestFiles,
431441
getCoverageReport,
432442
};

test/parallel/test-runner-reporters.js

+19
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,23 @@ describe('node:test reporters', { concurrency: true }, () => {
155155
assert.strictEqual(child.stdout.toString(), 'Going to throw an error\n');
156156
assert.match(child.stderr.toString(), /Emitted 'error' event on Duplex instance/);
157157
});
158+
159+
it('should support stdout as a destination with spec reporter', async () => {
160+
process.env.FORCE_COLOR = '1';
161+
const file = tmpdir.resolve(`${tmpFiles++}.txt`);
162+
const child = spawnSync(process.execPath,
163+
['--test', '--test-reporter', 'spec', '--test-reporter-destination', file, testFile]);
164+
assert.strictEqual(child.stderr.toString(), '');
165+
assert.strictEqual(child.stdout.toString(), '');
166+
const fileConent = fs.readFileSync(file, 'utf8');
167+
assert.match(fileConent, / nested/);
168+
assert.match(fileConent, / ok/);
169+
assert.match(fileConent, / failing/);
170+
assert.match(fileConent, / tests 4/);
171+
assert.match(fileConent, / pass 2/);
172+
assert.match(fileConent, / fail 2/);
173+
assert.match(fileConent, / cancelled 0/);
174+
assert.match(fileConent, / skipped 0/);
175+
assert.match(fileConent, / todo 0/);
176+
});
158177
});

test/parallel/test-runner-run.mjs

+15
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,21 @@ describe('require(\'node:test\').run', { concurrency: true }, () => {
459459
});
460460
});
461461

462+
describe('validation', () => {
463+
it('should pass instance of stream to setup', async () => {
464+
const stream = run({
465+
files: [join(testFixtures, 'default-behavior/test/random.cjs')],
466+
setup: common.mustCall((root) => {
467+
assert.strictEqual(root.constructor.name, 'TestsStream');
468+
}),
469+
});
470+
stream.on('test:fail', common.mustNotCall());
471+
stream.on('test:pass', common.mustCall());
472+
// eslint-disable-next-line no-unused-vars
473+
for await (const _ of stream);
474+
});
475+
});
476+
462477
it('should run with no files', async () => {
463478
const stream = run({
464479
files: undefined

0 commit comments

Comments
 (0)