@@ -395,8 +395,10 @@ class Test extends AsyncResource {
395
395
this . parent = parent ;
396
396
this . testNumber = 0 ;
397
397
this . outputSubtestCount = 0 ;
398
- this . filteredSubtestCount = 0 ;
398
+ this . diagnostics = [ ] ;
399
399
this . filtered = false ;
400
+ this . filteredByName = false ;
401
+ this . hasOnlyTests = false ;
400
402
401
403
if ( parent === null ) {
402
404
this . root = this ;
@@ -413,26 +415,48 @@ class Test extends AsyncResource {
413
415
} else {
414
416
const nesting = parent . parent === null ? parent . nesting :
415
417
parent . nesting + 1 ;
418
+ const { config, isFilteringByName, isFilteringByOnly } = parent . root . harness ;
416
419
417
420
this . root = parent . root ;
418
421
this . harness = null ;
419
- this . config = this . root . harness . config ;
422
+ this . config = config ;
420
423
this . concurrency = parent . concurrency ;
421
424
this . nesting = nesting ;
422
- this . only = only ?? ( parent . only && ! parent . runOnlySubtests ) ;
425
+ this . only = only ;
423
426
this . reporter = parent . reporter ;
424
427
this . runOnlySubtests = false ;
425
428
this . childNumber = parent . subtests . length + 1 ;
426
429
this . timeout = parent . timeout ;
427
430
this . entryFile = parent . entryFile ;
428
431
429
- if ( this . willBeFiltered ( ) ) {
430
- this . filtered = true ;
431
- this . parent . filteredSubtestCount ++ ;
432
+ if ( isFilteringByName ) {
433
+ this . filteredByName = this . willBeFilteredByName ( ) ;
434
+ if ( ! this . filteredByName ) {
435
+ for ( let t = this . parent ; t !== null && t . filteredByName ; t = t . parent ) {
436
+ t . filteredByName = false ;
437
+ }
438
+ }
432
439
}
433
440
434
- if ( this . config . only && only === false ) {
435
- fn = noop ;
441
+ if ( isFilteringByOnly ) {
442
+ if ( this . only ) {
443
+ // If filtering impacts the tests within a suite, then the suite only
444
+ // runs those tests. If filtering does not impact the tests within a
445
+ // suite, then all tests are run.
446
+ this . parent . runOnlySubtests = true ;
447
+
448
+ if ( this . parent === this . root || this . parent . startTime === null ) {
449
+ for ( let t = this . parent ; t !== null && ! t . hasOnlyTests ; t = t . parent ) {
450
+ t . hasOnlyTests = true ;
451
+ }
452
+ }
453
+ } else if ( this . only === false ) {
454
+ fn = noop ;
455
+ }
456
+ } else if ( only || this . parent . runOnlySubtests ) {
457
+ const warning =
458
+ "'only' and 'runOnly' require the --test-only command-line option." ;
459
+ this . diagnostic ( warning ) ;
436
460
}
437
461
}
438
462
@@ -491,7 +515,6 @@ class Test extends AsyncResource {
491
515
this . endTime = null ;
492
516
this . passed = false ;
493
517
this . error = null ;
494
- this . diagnostics = [ ] ;
495
518
this . message = typeof skip === 'string' ? skip :
496
519
typeof todo === 'string' ? todo : null ;
497
520
this . activeSubtests = 0 ;
@@ -509,12 +532,6 @@ class Test extends AsyncResource {
509
532
ownAfterEachCount : 0 ,
510
533
} ;
511
534
512
- if ( ! this . config . only && ( only || this . parent ?. runOnlySubtests ) ) {
513
- const warning =
514
- "'only' and 'runOnly' require the --test-only command-line option." ;
515
- this . diagnostic ( warning ) ;
516
- }
517
-
518
535
if ( loc === undefined ) {
519
536
this . loc = undefined ;
520
537
} else {
@@ -542,9 +559,27 @@ class Test extends AsyncResource {
542
559
}
543
560
}
544
561
545
- willBeFiltered ( ) {
546
- if ( this . config . only && ! this . only ) return true ;
562
+ applyFilters ( ) {
563
+ if ( this . error ) {
564
+ // Never filter out errors.
565
+ return ;
566
+ }
547
567
568
+ if ( this . filteredByName ) {
569
+ this . filtered = true ;
570
+ return ;
571
+ }
572
+
573
+ if ( this . root . harness . isFilteringByOnly && ! this . only && ! this . hasOnlyTests ) {
574
+ if ( this . parent . runOnlySubtests ||
575
+ this . parent . hasOnlyTests ||
576
+ this . only === false ) {
577
+ this . filtered = true ;
578
+ }
579
+ }
580
+ }
581
+
582
+ willBeFilteredByName ( ) {
548
583
const { testNamePatterns, testSkipPatterns } = this . config ;
549
584
550
585
if ( testNamePatterns && ! testMatchesPattern ( this , testNamePatterns ) ) {
@@ -757,12 +792,10 @@ class Test extends AsyncResource {
757
792
ArrayPrototypePush ( this . diagnostics , message ) ;
758
793
}
759
794
760
- get shouldFilter ( ) {
761
- return this . filtered && this . parent ?. filteredSubtestCount > 0 ;
762
- }
763
-
764
795
start ( ) {
765
- if ( this . shouldFilter ) {
796
+ this . applyFilters ( ) ;
797
+
798
+ if ( this . filtered ) {
766
799
noopTestStream ??= new TestsStream ( ) ;
767
800
this . reporter = noopTestStream ;
768
801
this . run = this . filteredRun ;
@@ -970,7 +1003,7 @@ class Test extends AsyncResource {
970
1003
this . mock ?. reset ( ) ;
971
1004
972
1005
if ( this . parent !== null ) {
973
- if ( ! this . shouldFilter ) {
1006
+ if ( ! this . filtered ) {
974
1007
const report = this . getReportDetails ( ) ;
975
1008
report . details . passed = this . passed ;
976
1009
this . testNumber ||= ++ this . parent . outputSubtestCount ;
@@ -1159,7 +1192,7 @@ class TestHook extends Test {
1159
1192
getRunArgs ( ) {
1160
1193
return this . #args;
1161
1194
}
1162
- willBeFiltered ( ) {
1195
+ willBeFilteredByName ( ) {
1163
1196
return false ;
1164
1197
}
1165
1198
postRun ( ) {
@@ -1192,7 +1225,6 @@ class Suite extends Test {
1192
1225
this . fn = options . fn || this . fn ;
1193
1226
this . skipped = false ;
1194
1227
}
1195
- this . runOnlySubtests = this . config . only ;
1196
1228
1197
1229
try {
1198
1230
const { ctx, args } = this . getRunArgs ( ) ;
@@ -1216,21 +1248,6 @@ class Suite extends Test {
1216
1248
1217
1249
postBuild ( ) {
1218
1250
this . buildPhaseFinished = true ;
1219
- if ( this . filtered &&
1220
- ( this . filteredSubtestCount !== this . subtests . length || this . error ) ) {
1221
- // A suite can transition from filtered to unfiltered based on the
1222
- // tests that it contains - in case of children matching patterns.
1223
- this . filtered = false ;
1224
- this . parent . filteredSubtestCount -- ;
1225
- } else if (
1226
- this . config . only &&
1227
- this . config . testNamePatterns == null &&
1228
- this . config . testSkipPatterns == null &&
1229
- this . filteredSubtestCount === this . subtests . length
1230
- ) {
1231
- // If no subtests are marked as "only", run them all
1232
- this . filteredSubtestCount = 0 ;
1233
- }
1234
1251
}
1235
1252
1236
1253
getRunArgs ( ) {
0 commit comments