@@ -76,6 +76,7 @@ const {
76
76
kSubtestsFailed,
77
77
kTestCodeFailure,
78
78
kTestTimeoutFailure,
79
+ kTestBailedOut,
79
80
Test,
80
81
} = require ( 'internal/test_runner/test' ) ;
81
82
@@ -101,7 +102,10 @@ const kFilterArgValues = ['--test-reporter', '--test-reporter-destination'];
101
102
const kDiagnosticsFilterArgs = [ 'tests' , 'suites' , 'pass' , 'fail' , 'cancelled' , 'skipped' , 'todo' , 'duration_ms' ] ;
102
103
103
104
const kCanceledTests = new SafeSet ( )
104
- . add ( kCancelledByParent ) . add ( kAborted ) . add ( kTestTimeoutFailure ) ;
105
+ . add ( kCancelledByParent )
106
+ . add ( kAborted )
107
+ . add ( kTestTimeoutFailure )
108
+ . add ( kTestBailedOut ) ;
105
109
106
110
let kResistStopPropagation ;
107
111
@@ -137,7 +141,8 @@ function getRunArgs(path, { forceExit,
137
141
only,
138
142
argv : suppliedArgs ,
139
143
execArgv,
140
- cwd } ) {
144
+ cwd,
145
+ bail } ) {
141
146
const argv = ArrayPrototypeFilter ( process . execArgv , filterExecArgv ) ;
142
147
if ( forceExit === true ) {
143
148
ArrayPrototypePush ( argv , '--test-force-exit' ) ;
@@ -154,6 +159,9 @@ function getRunArgs(path, { forceExit,
154
159
if ( only === true ) {
155
160
ArrayPrototypePush ( argv , '--test-only' ) ;
156
161
}
162
+ if ( bail === true ) {
163
+ ArrayPrototypePush ( argv , '--test-bail' ) ;
164
+ }
157
165
158
166
ArrayPrototypePushApply ( argv , execArgv ) ;
159
167
@@ -216,6 +224,14 @@ class FileTest extends Test {
216
224
if ( item . data . details ?. error ) {
217
225
item . data . details . error = deserializeError ( item . data . details . error ) ;
218
226
}
227
+ if ( item . type === 'test:bail' ) {
228
+ // <-- here we need to stop all the pending test files (aka subprocesses)
229
+ // To be replaced, just for poc
230
+ this . root . harness . testsProcesses . forEach ( ( child ) => {
231
+ child . kill ( ) ;
232
+ } ) ;
233
+ return ;
234
+ }
219
235
if ( item . type === 'test:pass' || item . type === 'test:fail' ) {
220
236
item . data . testNumber = isTopLevel ? ( this . root . harness . counters . topLevel + 1 ) : item . data . testNumber ;
221
237
countCompletedTest ( {
@@ -362,7 +378,12 @@ function runTestFile(path, filesWatcher, opts) {
362
378
const watchMode = filesWatcher != null ;
363
379
const testPath = path === kIsolatedProcessName ? '' : path ;
364
380
const testOpts = { __proto__ : null , signal : opts . signal } ;
381
+ const subtestProcesses = opts . root . harness . testsProcesses ;
365
382
const subtest = opts . root . createSubtest ( FileTest , testPath , testOpts , async ( t ) => {
383
+ if ( opts . root . bailed ) {
384
+ // TODO(pmarchini): this is a temporary solution to avoid running tests after bailing
385
+ return ; // No-op in order to avoid running tests after bailing
386
+ }
366
387
const args = getRunArgs ( path , opts ) ;
367
388
const stdio = [ 'pipe' , 'pipe' , 'pipe' ] ;
368
389
const env = { __proto__ : null , ...process . env , NODE_TEST_CONTEXT : 'child-v8' } ;
@@ -389,6 +410,7 @@ function runTestFile(path, filesWatcher, opts) {
389
410
filesWatcher . runningProcesses . set ( path , child ) ;
390
411
filesWatcher . watcher . watchChildProcessModules ( child , path ) ;
391
412
}
413
+ subtestProcesses . set ( path , child ) ;
392
414
393
415
let err ;
394
416
@@ -422,6 +444,7 @@ function runTestFile(path, filesWatcher, opts) {
422
444
finished ( child . stdout , { __proto__ : null , signal : t . signal } ) ,
423
445
] ) ;
424
446
447
+ subtestProcesses . delete ( path ) ;
425
448
if ( watchMode ) {
426
449
filesWatcher . runningProcesses . delete ( path ) ;
427
450
filesWatcher . runningSubtests . delete ( path ) ;
@@ -478,6 +501,8 @@ function watchFiles(testFiles, opts) {
478
501
// Reset the topLevel counter
479
502
opts . root . harness . counters . topLevel = 0 ;
480
503
}
504
+ // TODO(pmarchini): Reset the bailed flag to rerun the tests.
505
+ // This must be added only when we add support for bail in watch mode.
481
506
await runningSubtests . get ( file ) ;
482
507
runningSubtests . set ( file , runTestFile ( file , filesWatcher , opts ) ) ;
483
508
}
@@ -564,6 +589,7 @@ function run(options = kEmptyObject) {
564
589
execArgv = [ ] ,
565
590
argv = [ ] ,
566
591
cwd = process . cwd ( ) ,
592
+ bail = false ,
567
593
} = options ;
568
594
569
595
if ( files != null ) {
@@ -663,6 +689,15 @@ function run(options = kEmptyObject) {
663
689
664
690
validateStringArray ( argv , 'options.argv' ) ;
665
691
validateStringArray ( execArgv , 'options.execArgv' ) ;
692
+ validateBoolean ( bail , 'options.bail' ) ;
693
+ // TODO(pmarchini): watch mode with bail needs to be implemented
694
+ if ( bail && watch ) {
695
+ throw new ERR_INVALID_ARG_VALUE (
696
+ 'options.bail' ,
697
+ watch ,
698
+ 'bail not supported while watch mode is enabled' ,
699
+ ) ;
700
+ }
666
701
667
702
const rootTestOptions = { __proto__ : null , concurrency, timeout, signal } ;
668
703
const globalOptions = {
@@ -678,6 +713,7 @@ function run(options = kEmptyObject) {
678
713
branchCoverage : branchCoverage ,
679
714
functionCoverage : functionCoverage ,
680
715
cwd,
716
+ bail,
681
717
} ;
682
718
const root = createTestTree ( rootTestOptions , globalOptions ) ;
683
719
let testFiles = files ?? createTestFileList ( globPatterns , cwd ) ;
@@ -705,6 +741,7 @@ function run(options = kEmptyObject) {
705
741
isolation,
706
742
argv,
707
743
execArgv,
744
+ bail,
708
745
} ;
709
746
710
747
if ( isolation === 'process' ) {
0 commit comments