Skip to content

Commit 28a1317

Browse files
MoLowjuanarbol
authored andcommitted
test_runner: bootstrap reporters before running tests
PR-URL: #46737 Backport-PR-URL: #46839Fixes: #46747 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent cd3aaa8 commit 28a1317

4 files changed

Lines changed: 29 additions & 12 deletions

File tree

‎doc/api/test.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,9 @@ added: v18.9.0
681681
**Default:**`true`.
682682
*`files`: {Array} An array containing the list of files to run.
683683
**Default** matching files from [test runner execution model][].
684+
*`setup` {Function} A function that accepts the `TestsStream` instance
685+
and can be used to setup listeners before any tests are run.
686+
**Default:**`undefined`.
684687
*`signal` {AbortSignal} Allows aborting an in-progress test execution.
685688
*`timeout` {number} A number of milliseconds the test execution will
686689
fail after.

‎lib/internal/main/test_runner.js‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ if (isUsingInspector()) {
2121
inspectPort=process.debugPort;
2222
}
2323

24-
consttestsStream=run({ concurrency, inspectPort,watch: getOptionValue('--watch')});
25-
testsStream.once('test:fail',()=>{
24+
run({ concurrency, inspectPort,watch: getOptionValue('--watch'),setup: setupTestReporters})
25+
.once('test:fail',()=>{
2626
process.exitCode=1;
2727
});
28-
setupTestReporters(testsStream);

‎lib/internal/test_runner/harness.js‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,29 +159,35 @@ function setup(root) {
159159
}
160160

161161
letglobalRoot;
162+
letreportersSetup;
162163
functiongetGlobalRoot(){
163164
if(!globalRoot){
164165
globalRoot=createTestTree();
165166
globalRoot.reporter.once('test:fail',()=>{
166167
process.exitCode=1;
167168
});
168-
setupTestReporters(globalRoot.reporter);
169+
reportersSetup=setupTestReporters(globalRoot.reporter);
169170
}
170171
returnglobalRoot;
171172
}
172173

174+
asyncfunctionstartSubtest(subtest){
175+
awaitreportersSetup;
176+
awaitsubtest.start();
177+
}
178+
173179
functiontest(name,options,fn){
174180
constparent=testResources.get(executionAsyncId())||getGlobalRoot();
175181
constsubtest=parent.createSubtest(Test,name,options,fn);
176-
returnsubtest.start();
182+
returnstartSubtest(subtest);
177183
}
178184

179185
functionrunInParentContext(Factory){
180186
functionrun(name,options,fn,overrides){
181187
constparent=testResources.get(executionAsyncId())||getGlobalRoot();
182188
constsubtest=parent.createSubtest(Factory,name,options,fn,overrides);
183189
if(parent===getGlobalRoot()){
184-
subtest.start();
190+
startSubtest(subtest);
185191
}
186192
}
187193

‎lib/internal/test_runner/runner.js‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ const {
1313
ObjectAssign,
1414
ObjectKeys,
1515
PromisePrototypeThen,
16+
SafePromiseAll,
1617
SafePromiseAllReturnVoid,
1718
SafePromiseAllSettledReturnVoid,
19+
PromiseResolve,
1820
SafeMap,
1921
SafeSet,
2022
StringPrototypeIndexOf,
@@ -24,6 +26,7 @@ const {
2426

2527
const{ spawn }=require('child_process');
2628
const{ readdirSync, statSync }=require('fs');
29+
const{ finished }=require('internal/streams/end-of-stream');
2730
// TODO(aduh95): switch to internal/readline/interface when backporting to Node.js 16.x is no longer a concern.
2831
const{ createInterface }=require('readline');
2932
const{ FilesWatcher }=require('internal/watch_mode/files_watcher');
@@ -33,7 +36,7 @@ const {
3336
ERR_TEST_FAILURE,
3437
},
3538
}=require('internal/errors');
36-
const{ validateArray, validateBoolean }=require('internal/validators');
39+
const{ validateArray, validateBoolean, validateFunction}=require('internal/validators');
3740
const{ getInspectPort, isUsingInspector, isInspectorMessage }=require('internal/util/inspector');
3841
const{ kEmptyObject }=require('internal/util');
3942
const{ createTestTree }=require('internal/test_runner/harness');
@@ -298,7 +301,10 @@ function runTestFile(path, root, inspectPort, filesWatcher) {
298301
subtest.addToReport(ast);
299302
});
300303

301-
const{0: code,1: signal}=awaitonce(child,'exit',{signal: t.signal});
304+
const{0: {0: code,1: signal}}=awaitSafePromiseAll([
305+
once(child,'exit',{signal: t.signal}),
306+
finished(parser,{signal: t.signal}),
307+
]);
302308

303309
runningProcesses.delete(path);
304310
runningSubtests.delete(path);
@@ -347,14 +353,17 @@ function run(options) {
347353
if(options===null||typeofoptions!=='object'){
348354
options=kEmptyObject;
349355
}
350-
const{ concurrency, timeout, signal, files, inspectPort, watch }=options;
356+
const{ concurrency, timeout, signal, files, inspectPort, watch, setup}=options;
351357

352358
if(files!=null){
353359
validateArray(files,'options.files');
354360
}
355361
if(watch!=null){
356362
validateBoolean(watch,'options.watch');
357363
}
364+
if(setup!=null){
365+
validateFunction(setup,'options.setup');
366+
}
358367

359368
constroot=createTestTree({ concurrency, timeout, signal });
360369
consttestFiles=files??createTestFileList();
@@ -365,13 +374,13 @@ function run(options) {
365374
filesWatcher=watchFiles(testFiles,root,inspectPort);
366375
postRun=undefined;
367376
}
368-
369-
PromisePrototypeThen(SafePromiseAllSettledReturnVoid(testFiles,(path)=>{
377+
construnFiles=()=>SafePromiseAllSettledReturnVoid(testFiles,(path)=>{
370378
constsubtest=runTestFile(path,root,inspectPort,filesWatcher);
371379
runningSubtests.set(path,subtest);
372380
returnsubtest;
373-
}),postRun);
381+
});
374382

383+
PromisePrototypeThen(PromisePrototypeThen(PromiseResolve(setup?.(root.reporter)),runFiles),postRun);
375384

376385
returnroot.reporter;
377386
}

0 commit comments

Comments
 (0)