Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Commit 4e06739

Browse files
atlowChemiaduh95
authored andcommitted
test_runner: do not tag-filter test file wrappers
Under run({ testTagFilters, isolation: 'process' }) the parent process's FileTest wrappers have empty tag sets, so any include filter filtered out the wrappers themselves and no test file was ever spawned. The same applied to the single re-spawned child in watch mode with isolation 'none'. Exempt file wrappers from tag filtering: the filter is re-emitted to the child process and applied there, matching isolation 'none' results. This also removes the testTagFilterExpressions bookkeeping and the isolation-conditional assignment of testTagFilters, both of which existed only to keep the parent process from filtering its own file wrappers. The parent now always holds the canonical filter values and re-emits them to child processes. Refs: #63221 Signed-off-by: atlowChemi <chemi@atlow.co.il> PR-URL: #65170 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
1 parent d6059e8 commit 4e06739

4 files changed

Lines changed: 32 additions & 24 deletions

File tree

‎lib/internal/test_runner/runner.js‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ function getRunArgs(path, { forceExit,
182182
inspectPort,
183183
testNamePatterns,
184184
testSkipPatterns,
185-
testTagFilterExpressions,
185+
testTagFilters,
186186
only,
187187
hasFiles,
188188
testFiles,
@@ -224,8 +224,8 @@ function getRunArgs(path, { forceExit,
224224
if(testSkipPatterns!=null){
225225
ArrayPrototypeForEach(testSkipPatterns,(pattern)=>ArrayPrototypePush(runArgs,`--test-skip-pattern=${pattern}`));
226226
}
227-
if(testTagFilterExpressions!=null){
228-
ArrayPrototypeForEach(testTagFilterExpressions,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
227+
if(testTagFilters!=null){
228+
ArrayPrototypeForEach(testTagFilters,(value)=>ArrayPrototypePush(runArgs,`--experimental-test-tag-filter=${value}`));
229229
}
230230
if(only===true){
231231
ArrayPrototypePush(runArgs,'--test-only');
@@ -284,6 +284,14 @@ class FileTest extends Test {
284284
this.timeout=null;
285285
}
286286

287+
willBeFilteredByTags(){
288+
// File wrappers have no tags of their own. Tag filtering applies to the
289+
// tests inside the file, which run in a child process (or in-process
290+
// import); filtering the wrapper would prevent the file from running at
291+
// all.
292+
returnfalse;
293+
}
294+
287295
#skipReporting(){
288296
returnthis.#reportedChildren >0&&(!this.error||this.error.failureType===kSubtestsFailed);
289297
}
@@ -864,7 +872,6 @@ function run(options = kEmptyObject) {
864872
});
865873
}
866874

867-
lettestTagFilterExpressions=null;
868875
if(testTagFilters!=null){
869876
if(!ArrayIsArray(testTagFilters)){
870877
testTagFilters=[testTagFilters];
@@ -876,10 +883,8 @@ function run(options = kEmptyObject) {
876883
testTagFilters=ArrayPrototypeMap(testTagFilters,(value,i)=>(
877884
validateAndCanonicalizeTagFilter(value,`options.testTagFilters[${i}]`)
878885
));
879-
testTagFilterExpressions=testTagFilters;
880886
}
881887
}
882-
testTagFilterExpressions??=options.testTagFilterExpressions;
883888

884889
validateOneOf(isolation,'options.isolation',['process','none']);
885890
validateBoolean(coverage,'options.coverage');
@@ -982,7 +987,6 @@ function run(options = kEmptyObject) {
982987
testNamePatterns,
983988
testSkipPatterns,
984989
testTagFilters,
985-
testTagFilterExpressions,
986990
hasFiles: files!=null,
987991
globPatterns,
988992
only,

‎lib/internal/test_runner/test.js‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ class Test extends AsyncResource {
656656
}
657657

658658
if(isFilteringByTags){
659-
this.filteredByTag=!evaluateTagFilters(config.testTagFilters,this.tagSet);
659+
this.filteredByTag=this.willBeFilteredByTags();
660660
if(!this.filteredByTag){
661661
for(lett=this.parent;t!==null&&t.filteredByTag;t=t.parent){
662662
t.filteredByTag=false;
@@ -894,6 +894,10 @@ class Test extends AsyncResource {
894894
returnfalse;
895895
}
896896

897+
willBeFilteredByTags(){
898+
return!evaluateTagFilters(this.config.testTagFilters,this.tagSet);
899+
}
900+
897901
/**
898902
* Returns a name of the test prefixed by name of all its ancestors in ascending order, separated by a space
899903
* Ex."grandparent parent test"

‎lib/internal/test_runner/utils.js‎

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,6 @@ function parseCommandLine() {
273273
lettestNamePatterns=mapPatternFlagToRegExArray('--test-name-pattern');
274274
lettestSkipPatterns=mapPatternFlagToRegExArray('--test-skip-pattern');
275275
lettestTagFilters=null;
276-
lettestTagFilterExpressions=null;
277276

278277
if(isChildProcessV8){
279278
kBuiltinReporters.set('v8-serializer','internal/test_runner/reporter/v8-serializer');
@@ -309,19 +308,14 @@ function parseCommandLine() {
309308
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
310309
if(tagFilterFlag?.length>0){
311310
emitExperimentalWarning('Test tags');
312-
testTagFilterExpressions=tagFilterFlag;
313-
// Validate at parent startup so a malformed flag fails fast,
314-
// independent of isolation mode. Under isolation='process' the
315-
// validated strings go unused at the parent (children re-validate
316-
// and apply the filter); the validation here only surfaces input
317-
// errors early.
318-
constvalidated=ArrayPrototypeMap(
311+
// File wrappers are exempt from tag filtering, so holding the filters
312+
// in the parent is safe under any isolation mode; under
313+
// isolation='process' the canonical values are re-emitted to the
314+
// child processes, which apply the filter themselves.
315+
testTagFilters=ArrayPrototypeMap(
319316
tagFilterFlag,
320317
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
321318
);
322-
if(isolation==='none'){
323-
testTagFilters=validated;
324-
}
325319
}
326320

327321
if(isolation==='none'){
@@ -365,7 +359,6 @@ function parseCommandLine() {
365359
consttagFilterFlag=getOptionValue('--experimental-test-tag-filter');
366360
if(tagFilterFlag?.length>0){
367361
emitExperimentalWarning('Test tags');
368-
testTagFilterExpressions=tagFilterFlag;
369362
testTagFilters=ArrayPrototypeMap(
370363
tagFilterFlag,
371364
(value,i)=>validateAndCanonicalizeTagFilter(value,`--experimental-test-tag-filter[${i}]`),
@@ -433,7 +426,6 @@ function parseCommandLine() {
433426
sourceMaps,
434427
testNamePatterns,
435428
testSkipPatterns,
436-
testTagFilterExpressions,
437429
testTagFilters,
438430
timeout,
439431
updateSnapshots,

‎test/parallel/test-runner-tags-events.mjs‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,22 @@ describe('tag-bearing event payloads', { concurrency: false }, () => {
8383
});
8484

8585
it('test:pass fires only for selected tagged tests when filtered',async()=>{
86-
// isolation='none' so the parent applies the filter directly. Under
87-
// 'process', the FileTest wrapper (which has no tags) would itself be
88-
// filtered out by the include filter - same wart as --test-name-pattern.
8986
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'none'});
9087
stream.on('test:fail',common.mustNotCall());
9188
// 3 db-tagged tests pass + the db suite itself.
9289
stream.on('test:pass',common.mustCall(4));
9390
// eslint-disable-next-line no-unused-vars
9491
forawait(const_ofstream);
9592
});
93+
94+
it('filtering under process isolation runs the file and filters inside it',async()=>{
95+
// The FileTest wrapper has no tags and must not be filtered out itself;
96+
// the filter is re-emitted to the child process and applied there.
97+
conststream=run({files: [fixture],testTagFilters: ['db'],isolation: 'process'});
98+
stream.on('test:fail',common.mustNotCall());
99+
// 3 db-tagged tests pass + the db suite itself.
100+
stream.on('test:pass',common.mustCall(4));
101+
// eslint-disable-next-line no-unused-vars
102+
forawait(const_ofstream);
103+
});
96104
});

0 commit comments

Comments
 (0)