@@ -395,8 +395,10 @@ class Test extends AsyncResource {
395395 this . parent = parent ;
396396 this . testNumber = 0 ;
397397 this . outputSubtestCount = 0 ;
398- this . filteredSubtestCount = 0 ;
398+ this . diagnostics = [ ] ;
399399 this . filtered = false ;
400+ this . filteredByName = false ;
401+ this . hasOnlyTests = false ;
400402
401403 if ( parent === null ) {
402404 this . root = this ;
@@ -413,26 +415,48 @@ class Test extends AsyncResource {
413415 } else {
414416 const nesting = parent . parent === null ? parent . nesting :
415417 parent . nesting + 1 ;
418+ const { config, isFilteringByName, isFilteringByOnly } = parent . root . harness ;
416419
417420 this . root = parent . root ;
418421 this . harness = null ;
419- this . config = this . root . harness . config ;
422+ this . config = config ;
420423 this . concurrency = parent . concurrency ;
421424 this . nesting = nesting ;
422- this . only = only ?? ( parent . only && ! parent . runOnlySubtests ) ;
425+ this . only = only ;
423426 this . reporter = parent . reporter ;
424427 this . runOnlySubtests = false ;
425428 this . childNumber = parent . subtests . length + 1 ;
426429 this . timeout = parent . timeout ;
427430 this . entryFile = parent . entryFile ;
428431
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+ }
432439 }
433440
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 ) ;
436460 }
437461 }
438462
@@ -491,7 +515,6 @@ class Test extends AsyncResource {
491515 this . endTime = null ;
492516 this . passed = false ;
493517 this . error = null ;
494- this . diagnostics = [ ] ;
495518 this . message = typeof skip === 'string' ? skip :
496519 typeof todo === 'string' ? todo : null ;
497520 this . activeSubtests = 0 ;
@@ -509,12 +532,6 @@ class Test extends AsyncResource {
509532 ownAfterEachCount : 0 ,
510533 } ;
511534
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-
518535 if ( loc === undefined ) {
519536 this . loc = undefined ;
520537 } else {
@@ -542,9 +559,27 @@ class Test extends AsyncResource {
542559 }
543560 }
544561
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+ }
547567
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 ( ) {
548583 const { testNamePatterns, testSkipPatterns } = this . config ;
549584
550585 if ( testNamePatterns && ! testMatchesPattern ( this , testNamePatterns ) ) {
@@ -757,12 +792,10 @@ class Test extends AsyncResource {
757792 ArrayPrototypePush ( this . diagnostics , message ) ;
758793 }
759794
760- get shouldFilter ( ) {
761- return this . filtered && this . parent ?. filteredSubtestCount > 0 ;
762- }
763-
764795 start ( ) {
765- if ( this . shouldFilter ) {
796+ this . applyFilters ( ) ;
797+
798+ if ( this . filtered ) {
766799 noopTestStream ??= new TestsStream ( ) ;
767800 this . reporter = noopTestStream ;
768801 this . run = this . filteredRun ;
@@ -970,7 +1003,7 @@ class Test extends AsyncResource {
9701003 this . mock ?. reset ( ) ;
9711004
9721005 if ( this . parent !== null ) {
973- if ( ! this . shouldFilter ) {
1006+ if ( ! this . filtered ) {
9741007 const report = this . getReportDetails ( ) ;
9751008 report . details . passed = this . passed ;
9761009 this . testNumber ||= ++ this . parent . outputSubtestCount ;
@@ -1159,7 +1192,7 @@ class TestHook extends Test {
11591192 getRunArgs ( ) {
11601193 return this . #args;
11611194 }
1162- willBeFiltered ( ) {
1195+ willBeFilteredByName ( ) {
11631196 return false ;
11641197 }
11651198 postRun ( ) {
@@ -1192,7 +1225,6 @@ class Suite extends Test {
11921225 this . fn = options . fn || this . fn ;
11931226 this . skipped = false ;
11941227 }
1195- this . runOnlySubtests = this . config . only ;
11961228
11971229 try {
11981230 const { ctx, args } = this . getRunArgs ( ) ;
@@ -1216,21 +1248,6 @@ class Suite extends Test {
12161248
12171249 postBuild ( ) {
12181250 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- }
12341251 }
12351252
12361253 getRunArgs ( ) {
0 commit comments