From 73e0f817b99f8499c7ff6234d0dcc5668fdbabed Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 7 Aug 2024 18:23:57 -0400 Subject: [PATCH 1/6] test_runner: use run() argument names in parseCommandLine() This commit updates parseCommandLine() to use the names supported by run(). This removes some unnecessary renaming code, and allows node:test and run() to more easily share code. --- lib/internal/main/test_runner.js | 26 ++++++----------------- lib/internal/test_runner/test.js | 2 +- lib/internal/test_runner/utils.js | 34 +++++++++++++++---------------- 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/lib/internal/main/test_runner.js b/lib/internal/main/test_runner.js index a42c1e5dff64cc..9785a74cd1a665 100644 --- a/lib/internal/main/test_runner.js +++ b/lib/internal/main/test_runner.js @@ -22,32 +22,18 @@ let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => { prepareMainThreadExecution(false); markBootstrapComplete(); -const { - perFileTimeout, - runnerConcurrency, - shard, - watchMode, -} = parseCommandLine(); - -let concurrency = runnerConcurrency; -let inspectPort; +const options = parseCommandLine(); if (isUsingInspector()) { process.emitWarning('Using the inspector with --test forces running at a concurrency of 1. ' + 'Use the inspectPort option to run with concurrency'); - concurrency = 1; - inspectPort = process.debugPort; + options.concurrency = 1; + options.inspectPort = process.debugPort; } -const options = { - concurrency, - inspectPort, - watch: watchMode, - setup: setupTestReporters, - timeout: perFileTimeout, - shard, - globPatterns: ArrayPrototypeSlice(process.argv, 1), -}; +options.setup = setupTestReporters; +options.globPatterns = ArrayPrototypeSlice(process.argv, 1); + debug('test runner configuration:', options); run(options).on('test:fail', (data) => { if (data.todo === undefined || data.todo === false) { diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 00922c7b529272..ab41a93fc081f9 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -84,7 +84,7 @@ const { sourceMaps, testNamePatterns, testSkipPatterns, - testOnlyFlag, + only: testOnlyFlag, updateSnapshots, } = parseCommandLine(); let kResistStopPropagation; diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index aae2a756800a0f..bbd69aa4211415 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -197,19 +197,19 @@ function parseCommandLine() { const forceExit = getOptionValue('--test-force-exit'); const sourceMaps = getOptionValue('--enable-source-maps'); const updateSnapshots = getOptionValue('--test-update-snapshots'); - const watchMode = getOptionValue('--watch'); + const watch = getOptionValue('--watch'); const isChildProcess = process.env.NODE_TEST_CONTEXT === 'child'; const isChildProcessV8 = process.env.NODE_TEST_CONTEXT === 'child-v8'; + let concurrency; let coverageExcludeGlobs; let coverageIncludeGlobs; let destinations; - let perFileTimeout; + let only; let reporters; - let runnerConcurrency; + let shard; let testNamePatterns; let testSkipPatterns; - let testOnlyFlag; - let shard; + let timeout; if (isChildProcessV8) { kBuiltinReporters.set('v8-serializer', 'internal/test_runner/reporter/v8-serializer'); @@ -239,9 +239,9 @@ function parseCommandLine() { } if (isTestRunner) { - perFileTimeout = getOptionValue('--test-timeout') || Infinity; - runnerConcurrency = getOptionValue('--test-concurrency') || true; - testOnlyFlag = false; + timeout = getOptionValue('--test-timeout') || Infinity; + concurrency = getOptionValue('--test-concurrency') || true; + only = false; testNamePatterns = null; const shardOption = getOptionValue('--test-shard'); @@ -262,10 +262,10 @@ function parseCommandLine() { }; } } else { - perFileTimeout = Infinity; - runnerConcurrency = 1; + timeout = Infinity; + concurrency = 1; const testNamePatternFlag = getOptionValue('--test-name-pattern'); - testOnlyFlag = getOptionValue('--test-only'); + only = getOptionValue('--test-only'); testNamePatterns = testNamePatternFlag?.length > 0 ? ArrayPrototypeMap( testNamePatternFlag, @@ -284,21 +284,21 @@ function parseCommandLine() { globalTestOptions = { __proto__: null, isTestRunner, + concurrency, coverage, coverageExcludeGlobs, coverageIncludeGlobs, + destinations, forceExit, - perFileTimeout, - runnerConcurrency, + only, + reporters, shard, sourceMaps, - testOnlyFlag, testNamePatterns, testSkipPatterns, + timeout, updateSnapshots, - reporters, - destinations, - watchMode, + watch, }; return globalTestOptions; From 488e5bcf3cf9fcbaab783e5076c2a0b8a9f9172d Mon Sep 17 00:00:00 2001 From: cjihrig Date: Thu, 8 Aug 2024 17:06:12 -0400 Subject: [PATCH 2/6] test_runner: pass harness object as option to root test This commit initializes the root harness object before the root test and passes the harness as an option to the root test constructor. This commit also attaches the global configuration to the harness. This will allow the parseCommandLine() call in test.js to be removed, as those values are now available via the root test. --- lib/internal/test_runner/harness.js | 76 +++++++++++++++-------------- lib/internal/test_runner/test.js | 3 +- 2 files changed, 41 insertions(+), 38 deletions(-) diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index ac52307cc38be5..de0cf82682af31 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -35,7 +35,42 @@ let globalRoot; testResources.set(reporterScope.asyncId(), reporterScope); function createTestTree(options = kEmptyObject) { - globalRoot = setup(new Test({ __proto__: null, ...options, name: '' })); + const globalOptions = parseCommandLine(); + const harness = { + __proto__: null, + allowTestsToRun: false, + bootstrapPromise: resolvedPromise, + watching: false, + config: globalOptions, + coverage: null, + resetCounters() { + harness.counters = { + __proto__: null, + all: 0, + failed: 0, + passed: 0, + cancelled: 0, + skipped: 0, + todo: 0, + topLevel: 0, + suites: 0, + }; + }, + counters: null, + shouldColorizeTestFiles: shouldColorizeTestFiles(globalOptions.destinations), + teardown: null, + snapshotManager: null, + }; + + harness.resetCounters(); + globalRoot = new Test({ + __proto__: null, + ...options, + harness, + name: '', + }); + setupProcessState(globalRoot, globalOptions, harness); + globalRoot.startTime = hrtime(); return globalRoot; } @@ -127,15 +162,7 @@ function collectCoverage(rootTest, coverage) { return summary; } -function setup(root) { - if (root.startTime !== null) { - return root; - } - - // Parse the command line options before the hook is enabled. We don't want - // global input validation errors to end up in the uncaughtException handler. - const globalOptions = parseCommandLine(); - +function setupProcessState(root, globalOptions) { const hook = createHook({ __proto__: null, init(asyncId, type, triggerAsyncId, resource) { @@ -195,33 +222,8 @@ function setup(root) { process.on('SIGTERM', terminationHandler); } - root.harness = { - __proto__: null, - allowTestsToRun: false, - bootstrapPromise: resolvedPromise, - watching: false, - coverage: FunctionPrototypeBind(collectCoverage, null, root, coverage), - resetCounters() { - root.harness.counters = { - __proto__: null, - all: 0, - failed: 0, - passed: 0, - cancelled: 0, - skipped: 0, - todo: 0, - topLevel: 0, - suites: 0, - }; - }, - counters: null, - shouldColorizeTestFiles: shouldColorizeTestFiles(globalOptions.destinations), - teardown: exitHandler, - snapshotManager: null, - }; - root.harness.resetCounters(); - root.startTime = hrtime(); - return root; + root.harness.coverage = FunctionPrototypeBind(collectCoverage, null, root, coverage); + root.harness.teardown = exitHandler; } function lazyBootstrapRoot() { diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index ab41a93fc081f9..9fe5cf9ccd0e9c 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -395,6 +395,7 @@ class Test extends AsyncResource { this.timeout = kDefaultTimeout; this.entryFile = entryFile; this.root = this; + this.harness = options.harness; this.hooks = { __proto__: null, before: [], @@ -416,6 +417,7 @@ class Test extends AsyncResource { this.timeout = parent.timeout; this.entryFile = parent.entryFile; this.root = parent.root; + this.harness = null; this.hooks = { __proto__: null, before: [], @@ -480,7 +482,6 @@ class Test extends AsyncResource { ); this.fn = fn; - this.harness = null; // Configured on the root test by the test harness. this.mock = null; this.plan = null; this.expectedAssertions = plan; From cc2ba8ce6416a07873f9f4551ccf2e719ea1bfa5 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 12 Aug 2024 18:23:49 -0400 Subject: [PATCH 3/6] test_runner: pass global options to createTestTree() The global configuration should already be known when createTestTree() is called. This commit updates that function to take the global configuration as an input. --- lib/internal/test_runner/harness.js | 13 +++++++------ lib/internal/test_runner/runner.js | 10 +++++++++- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index de0cf82682af31..9f78319bef5727 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -17,8 +17,6 @@ const { }, } = require('internal/errors'); const { exitCodes: { kGenericUserError } } = internalBinding('errors'); - -const { kEmptyObject } = require('internal/util'); const { kCancelledByParent, Test, Suite } = require('internal/test_runner/test'); const { parseCommandLine, @@ -34,8 +32,7 @@ let globalRoot; testResources.set(reporterScope.asyncId(), reporterScope); -function createTestTree(options = kEmptyObject) { - const globalOptions = parseCommandLine(); +function createTestTree(rootTestOptions, globalOptions) { const harness = { __proto__: null, allowTestsToRun: false, @@ -65,7 +62,7 @@ function createTestTree(options = kEmptyObject) { harness.resetCounters(); globalRoot = new Test({ __proto__: null, - ...options, + ...rootTestOptions, harness, name: '', }); @@ -230,7 +227,11 @@ function lazyBootstrapRoot() { if (!globalRoot) { // This is where the test runner is bootstrapped when node:test is used // without the --test flag or the run() API. - createTestTree({ __proto__: null, entryFile: process.argv?.[1] }); + const rootTestOptions = { + __proto__: null, + entryFile: process.argv?.[1], + }; + createTestTree(rootTestOptions, parseCommandLine()); globalRoot.reporter.on('test:fail', (data) => { if (data.todo === undefined || data.todo === false) { process.exitCode = kGenericUserError; diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index a14cc97ce8690c..301f5a0e28eba3 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -69,6 +69,7 @@ const { convertStringToRegExp, countCompletedTest, kDefaultPattern, + parseCommandLine, } = require('internal/test_runner/utils'); const { Glob } = require('internal/fs/glob'); const { once } = require('events'); @@ -561,7 +562,14 @@ function run(options = kEmptyObject) { }); } - const root = createTestTree({ __proto__: null, concurrency, timeout, signal }); + const rootTestOptions = { __proto__: null, concurrency, timeout, signal }; + const globalOptions = { + __proto__: null, + // parseCommandLine() should not be used here. However, The existing run() + // behavior has relied on it, so removing it must be done in a semver major. + ...parseCommandLine(), + }; + const root = createTestTree(rootTestOptions, globalOptions); if (process.env.NODE_TEST_CONTEXT !== undefined) { process.emitWarning('node:test run() is being called recursively within a test file. skipping running files.'); From 2d41819a61db91746d2dcc1a9db77a56258aa59b Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 12 Aug 2024 20:18:27 -0400 Subject: [PATCH 4/6] test_runner: return setup() from parseCommandLine() Now that parseCommandLine() returns run() compatible arguments, it makes sense to return setupTestReporters() as the setup() argument to run(). This also removes another problematic use of parseCommandLine() in setupTestReporters(). --- lib/internal/main/test_runner.js | 6 +----- lib/internal/test_runner/harness.js | 6 +++--- lib/internal/test_runner/runner.js | 1 + lib/internal/test_runner/utils.js | 20 ++++++++++---------- 4 files changed, 15 insertions(+), 18 deletions(-) diff --git a/lib/internal/main/test_runner.js b/lib/internal/main/test_runner.js index 9785a74cd1a665..cc853da7388821 100644 --- a/lib/internal/main/test_runner.js +++ b/lib/internal/main/test_runner.js @@ -10,10 +10,7 @@ const { } = require('internal/process/pre_execution'); const { isUsingInspector } = require('internal/util/inspector'); const { run } = require('internal/test_runner/runner'); -const { - parseCommandLine, - setupTestReporters, -} = require('internal/test_runner/utils'); +const { parseCommandLine } = require('internal/test_runner/utils'); const { exitCodes: { kGenericUserError } } = internalBinding('errors'); let debug = require('internal/util/debuglog').debuglog('test_runner', (fn) => { debug = fn; @@ -31,7 +28,6 @@ if (isUsingInspector()) { options.inspectPort = process.debugPort; } -options.setup = setupTestReporters; options.globPatterns = ArrayPrototypeSlice(process.argv, 1); debug('test runner configuration:', options); diff --git a/lib/internal/test_runner/harness.js b/lib/internal/test_runner/harness.js index 9f78319bef5727..9c372c115e90f2 100644 --- a/lib/internal/test_runner/harness.js +++ b/lib/internal/test_runner/harness.js @@ -21,7 +21,6 @@ const { kCancelledByParent, Test, Suite } = require('internal/test_runner/test') const { parseCommandLine, reporterScope, - setupTestReporters, shouldColorizeTestFiles, } = require('internal/test_runner/utils'); const { queueMicrotask } = require('internal/process/task_queues'); @@ -231,13 +230,14 @@ function lazyBootstrapRoot() { __proto__: null, entryFile: process.argv?.[1], }; - createTestTree(rootTestOptions, parseCommandLine()); + const globalOptions = parseCommandLine(); + createTestTree(rootTestOptions, globalOptions); globalRoot.reporter.on('test:fail', (data) => { if (data.todo === undefined || data.todo === false) { process.exitCode = kGenericUserError; } }); - globalRoot.harness.bootstrapPromise = setupTestReporters(globalRoot.reporter); + globalRoot.harness.bootstrapPromise = globalOptions.setup(globalRoot.reporter); } return globalRoot; } diff --git a/lib/internal/test_runner/runner.js b/lib/internal/test_runner/runner.js index 301f5a0e28eba3..80601beeb64571 100644 --- a/lib/internal/test_runner/runner.js +++ b/lib/internal/test_runner/runner.js @@ -568,6 +568,7 @@ function run(options = kEmptyObject) { // parseCommandLine() should not be used here. However, The existing run() // behavior has relied on it, so removing it must be done in a semver major. ...parseCommandLine(), + setup, // This line can be removed when parseCommandLine() is removed here. }; const root = createTestTree(rootTestOptions, globalOptions); diff --git a/lib/internal/test_runner/utils.js b/lib/internal/test_runner/utils.js index bbd69aa4211415..e6c421ff870bbd 100644 --- a/lib/internal/test_runner/utils.js +++ b/lib/internal/test_runner/utils.js @@ -176,15 +176,6 @@ async function getReportersMap(reporters, destinations) { } const reporterScope = new AsyncResource('TestReporterScope'); -const setupTestReporters = reporterScope.bind(async (rootReporter) => { - const { reporters, destinations } = parseCommandLine(); - const reportersMap = await getReportersMap(reporters, destinations); - for (let i = 0; i < reportersMap.length; i++) { - const { reporter, destination } = reportersMap[i]; - compose(rootReporter, reporter).pipe(destination); - } -}); - let globalTestOptions; function parseCommandLine() { @@ -281,6 +272,15 @@ function parseCommandLine() { coverageIncludeGlobs = getOptionValue('--test-coverage-include'); } + const setup = reporterScope.bind(async (rootReporter) => { + const reportersMap = await getReportersMap(reporters, destinations); + + for (let i = 0; i < reportersMap.length; i++) { + const { reporter, destination } = reportersMap[i]; + compose(rootReporter, reporter).pipe(destination); + } + }); + globalTestOptions = { __proto__: null, isTestRunner, @@ -292,6 +292,7 @@ function parseCommandLine() { forceExit, only, reporters, + setup, shard, sourceMaps, testNamePatterns, @@ -480,7 +481,6 @@ module.exports = { kDefaultPattern, parseCommandLine, reporterScope, - setupTestReporters, shouldColorizeTestFiles, getCoverageReport, }; From 3ad749cd45f6a036fd9c1c3a0a19d8f94ea9731b Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 12 Aug 2024 23:15:38 -0400 Subject: [PATCH 5/6] test_runner: refactor hook creation This commit makes hook creation more consistent by always passing in a reference to the test that owns the hook. It also removes some unnecessary validation on internal API. --- lib/internal/test_runner/test.js | 59 ++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index 9fe5cf9ccd0e9c..d043d507a3d6ce 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -311,23 +311,43 @@ class TestContext { } before(fn, options) { - this.#test - .createHook('before', fn, { __proto__: null, ...options, hookType: 'before', loc: getCallerLocation() }); + this.#test.createHook('before', fn, { + __proto__: null, + ...options, + parent: this.#test, + hookType: 'before', + loc: getCallerLocation(), + }); } after(fn, options) { - this.#test - .createHook('after', fn, { __proto__: null, ...options, hookType: 'after', loc: getCallerLocation() }); + this.#test.createHook('after', fn, { + __proto__: null, + ...options, + parent: this.#test, + hookType: 'after', + loc: getCallerLocation(), + }); } beforeEach(fn, options) { - this.#test - .createHook('beforeEach', fn, { __proto__: null, ...options, hookType: 'beforeEach', loc: getCallerLocation() }); + this.#test.createHook('beforeEach', fn, { + __proto__: null, + ...options, + parent: this.#test, + hookType: 'beforeEach', + loc: getCallerLocation(), + }); } afterEach(fn, options) { - this.#test - .createHook('afterEach', fn, { __proto__: null, ...options, hookType: 'afterEach', loc: getCallerLocation() }); + this.#test.createHook('afterEach', fn, { + __proto__: null, + ...options, + parent: this.#test, + hookType: 'afterEach', + loc: getCallerLocation(), + }); } } @@ -1089,14 +1109,17 @@ class Test extends AsyncResource { class TestHook extends Test { #args; constructor(fn, options) { - if (options === null || typeof options !== 'object') { - options = kEmptyObject; - } - const { loc, timeout, signal } = options; - super({ __proto__: null, fn, loc, timeout, signal }); - - this.parentTest = options.parent ?? null; - this.hookType = options.hookType; + const { hookType, loc, parent, timeout, signal } = options; + super({ + __proto__: null, + fn, + loc, + timeout, + signal, + harness: parent.root.harness, + }); + this.parentTest = parent; + this.hookType = hookType; } run(args) { if (this.error && !this.outerSignal?.aborted) { @@ -1120,9 +1143,7 @@ class TestHook extends Test { const { error, loc, parentTest: parent } = this; // Report failures in the root test's after() hook. - if (error && parent !== null && - parent === parent.root && this.hookType === 'after') { - + if (error && parent === parent.root && this.hookType === 'after') { if (isTestFailureError(error)) { error.failureType = kHookFailure; } From 44bfa3bda2acd638e39f05b79f873f6a7e183ab1 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 13 Aug 2024 09:17:20 -0400 Subject: [PATCH 6/6] test_runner: remove parseCommandLine() from test.js The lib/internal/test_runner/test.js should not use the parseCommandLine() function. This commit refactors the code to avoid doing so. --- lib/internal/test_runner/test.js | 47 +++++++++---------- test/parallel/test-runner-v8-deserializer.mjs | 5 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/lib/internal/test_runner/test.js b/lib/internal/test_runner/test.js index d043d507a3d6ce..99872c1e1d773a 100644 --- a/lib/internal/test_runner/test.js +++ b/lib/internal/test_runner/test.js @@ -45,7 +45,6 @@ const { createDeferredCallback, countCompletedTest, isTestFailureError, - parseCommandLine, } = require('internal/test_runner/utils'); const { createDeferredPromise, @@ -79,14 +78,6 @@ const kHookNames = ObjectSeal(['before', 'after', 'beforeEach', 'afterEach']); const kUnwrapErrors = new SafeSet() .add(kTestCodeFailure).add(kHookFailure) .add('uncaughtException').add('unhandledRejection'); -const { - forceExit, - sourceMaps, - testNamePatterns, - testSkipPatterns, - only: testOnlyFlag, - updateSnapshots, -} = parseCommandLine(); let kResistStopPropagation; let assertObj; let findSourceMap; @@ -132,7 +123,7 @@ function lazyAssertObject(harness) { const { getOptionValue } = require('internal/options'); if (getOptionValue('--experimental-test-snapshots')) { const { SnapshotManager } = require('internal/test_runner/snapshot'); - harness.snapshotManager = new SnapshotManager(updateSnapshots); + harness.snapshotManager = new SnapshotManager(harness.config.updateSnapshots); assertObj.set('snapshot', harness.snapshotManager.createAssert()); } } @@ -406,16 +397,17 @@ class Test extends AsyncResource { this.filtered = false; if (parent === null) { + this.root = this; + this.harness = options.harness; + this.config = this.harness.config; this.concurrency = 1; this.nesting = 0; - this.only = testOnlyFlag; + this.only = this.config.only; this.reporter = new TestsStream(); this.runOnlySubtests = this.only; this.childNumber = 0; this.timeout = kDefaultTimeout; this.entryFile = entryFile; - this.root = this; - this.harness = options.harness; this.hooks = { __proto__: null, before: [], @@ -428,6 +420,9 @@ class Test extends AsyncResource { const nesting = parent.parent === null ? parent.nesting : parent.nesting + 1; + this.root = parent.root; + this.harness = null; + this.config = this.root.harness.config; this.concurrency = parent.concurrency; this.nesting = nesting; this.only = only ?? (parent.only && !parent.runOnlySubtests); @@ -436,8 +431,6 @@ class Test extends AsyncResource { this.childNumber = parent.subtests.length + 1; this.timeout = parent.timeout; this.entryFile = parent.entryFile; - this.root = parent.root; - this.harness = null; this.hooks = { __proto__: null, before: [], @@ -452,7 +445,7 @@ class Test extends AsyncResource { this.parent.filteredSubtestCount++; } - if (testOnlyFlag && only === false) { + if (this.config.only && only === false) { fn = noop; } } @@ -522,7 +515,7 @@ class Test extends AsyncResource { this.waitingOn = 0; this.finished = false; - if (!testOnlyFlag && (only || this.parent?.runOnlySubtests)) { + if (!this.config.only && (only || this.parent?.runOnlySubtests)) { const warning = "'only' and 'runOnly' require the --test-only command-line option."; this.diagnostic(warning); @@ -538,7 +531,7 @@ class Test extends AsyncResource { file: loc[2], }; - if (sourceMaps === true) { + if (this.config.sourceMaps === true) { const map = lazyFindSourceMap(this.loc.file); const entry = map?.findEntry(this.loc.line - 1, this.loc.column - 1); @@ -556,7 +549,9 @@ class Test extends AsyncResource { } willBeFiltered() { - if (testOnlyFlag && !this.only) return true; + if (this.config.only && !this.only) return true; + + const { testNamePatterns, testSkipPatterns } = this.config; if (testNamePatterns && !testMatchesPattern(this, testNamePatterns)) { return true; @@ -920,7 +915,7 @@ class Test extends AsyncResource { // This helps catch any asynchronous activity that occurs after the tests // have finished executing. this.postRun(); - } else if (forceExit) { + } else if (this.config.forceExit) { // This is the root test, and all known tests and hooks have finished // executing. If the user wants to force exit the process regardless of // any remaining ref'ed handles, then do that now. It is theoretically @@ -1163,11 +1158,13 @@ class Suite extends Test { constructor(options) { super(options); - if (testNamePatterns !== null && testSkipPatterns !== null && !options.skip) { + if (this.config.testNamePatterns !== null && + this.config.testSkipPatterns !== null && + !options.skip) { this.fn = options.fn || this.fn; this.skipped = false; } - this.runOnlySubtests = testOnlyFlag; + this.runOnlySubtests = this.config.only; try { const { ctx, args } = this.getRunArgs(); @@ -1198,9 +1195,9 @@ class Suite extends Test { this.filtered = false; this.parent.filteredSubtestCount--; } else if ( - testOnlyFlag && - testNamePatterns == null && - testSkipPatterns == null && + this.config.only && + this.config.testNamePatterns == null && + this.config.testSkipPatterns == null && this.filteredSubtestCount === this.subtests.length ) { // If no subtests are marked as "only", run them all diff --git a/test/parallel/test-runner-v8-deserializer.mjs b/test/parallel/test-runner-v8-deserializer.mjs index 9b4447d5a24291..42a8a84d1fe09f 100644 --- a/test/parallel/test-runner-v8-deserializer.mjs +++ b/test/parallel/test-runner-v8-deserializer.mjs @@ -26,7 +26,10 @@ describe('v8 deserializer', () => { let reported; beforeEach(() => { reported = []; - fileTest = new runner.FileTest({ name: 'filetest' }); + fileTest = new runner.FileTest({ + name: 'filetest', + harness: { config: {} }, + }); fileTest.reporter.on('data', (data) => reported.push(data)); assert(fileTest.isClearToSend()); });