Skip to content

Commit 320ddc0

Browse files
cjihrigtargos
authored andcommitted
test_runner: centralize CLI option handling
The test runner relies on a few CLI options. That code was spread across a few locations. This commit centralizes that logic. PR-URL: #46707 Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent e5b8597 commit 320ddc0

File tree

3 files changed

+65
-27
lines changed

3 files changed

+65
-27
lines changed

lib/internal/test_runner/harness.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ const {
1616
const { exitCodes: { kGenericUserError } } = internalBinding('errors');
1717

1818
const { kEmptyObject } = require('internal/util');
19-
const { getOptionValue } = require('internal/options');
2019
const { kCancelledByParent, Test, ItTest, Suite } = require('internal/test_runner/test');
21-
const { setupTestReporters } = require('internal/test_runner/utils');
20+
const {
21+
parseCommandLine,
22+
setupTestReporters,
23+
} = require('internal/test_runner/utils');
2224
const { bigint: hrtime } = process.hrtime;
2325

24-
const isTestRunnerCli = getOptionValue('--test');
2526
const testResources = new SafeMap();
2627
const wasRootSetup = new SafeWeakSet();
2728

@@ -56,8 +57,8 @@ function createProcessEventHandler(eventName, rootTest) {
5657
};
5758
}
5859

59-
function configureCoverage(rootTest) {
60-
if (!getOptionValue('--experimental-test-coverage')) {
60+
function configureCoverage(rootTest, globalOptions) {
61+
if (!globalOptions.coverage) {
6162
return null;
6263
}
6364

@@ -98,6 +99,11 @@ function setup(root) {
9899
if (wasRootSetup.has(root)) {
99100
return root;
100101
}
102+
103+
// Parse the command line options before the hook is enabled. We don't want
104+
// global input validation errors to end up in the uncaughtException handler.
105+
const globalOptions = parseCommandLine();
106+
101107
const hook = createHook({
102108
init(asyncId, type, triggerAsyncId, resource) {
103109
if (resource instanceof Test) {
@@ -122,7 +128,7 @@ function setup(root) {
122128
createProcessEventHandler('uncaughtException', root);
123129
const rejectionHandler =
124130
createProcessEventHandler('unhandledRejection', root);
125-
const coverage = configureCoverage(root);
131+
const coverage = configureCoverage(root, globalOptions);
126132
const exitHandler = () => {
127133
root.coverage = collectCoverage(root, coverage);
128134
root.postRun(new ERR_TEST_FAILURE(
@@ -142,8 +148,8 @@ function setup(root) {
142148
process.on('uncaughtException', exceptionHandler);
143149
process.on('unhandledRejection', rejectionHandler);
144150
process.on('beforeExit', exitHandler);
145-
// TODO(MoLow): Make it configurable to hook when isTestRunnerCli === false.
146-
if (isTestRunnerCli) {
151+
// TODO(MoLow): Make it configurable to hook when isTestRunner === false.
152+
if (globalOptions.isTestRunner) {
147153
process.on('SIGINT', terminationHandler);
148154
process.on('SIGTERM', terminationHandler);
149155
}

lib/internal/test_runner/test.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict';
22
const {
3-
ArrayPrototypeMap,
43
ArrayPrototypePush,
54
ArrayPrototypeReduce,
65
ArrayPrototypeShift,
@@ -31,13 +30,12 @@ const {
3130
},
3231
AbortError,
3332
} = require('internal/errors');
34-
const { getOptionValue } = require('internal/options');
3533
const { MockTracker } = require('internal/test_runner/mock');
3634
const { TestsStream } = require('internal/test_runner/tests_stream');
3735
const {
38-
convertStringToRegExp,
3936
createDeferredCallback,
4037
isTestFailureError,
38+
parseCommandLine,
4139
} = require('internal/test_runner/utils');
4240
const {
4341
createDeferredPromise,
@@ -64,22 +62,13 @@ const kTestTimeoutFailure = 'testTimeoutFailure';
6462
const kHookFailure = 'hookFailed';
6563
const kDefaultTimeout = null;
6664
const noop = FunctionPrototype;
67-
const isTestRunner = getOptionValue('--test');
68-
const testOnlyFlag = !isTestRunner && getOptionValue('--test-only');
69-
const testNamePatternFlag = isTestRunner ? null :
70-
getOptionValue('--test-name-pattern');
71-
const testNamePatterns = testNamePatternFlag?.length > 0 ?
72-
ArrayPrototypeMap(
73-
testNamePatternFlag,
74-
(re) => convertStringToRegExp(re, '--test-name-pattern'),
75-
) : null;
7665
const kShouldAbort = Symbol('kShouldAbort');
7766
const kFilename = process.argv?.[1];
7867
const kHookNames = ObjectSeal(['before', 'after', 'beforeEach', 'afterEach']);
7968
const kUnwrapErrors = new SafeSet()
8069
.add(kTestCodeFailure).add(kHookFailure)
8170
.add('uncaughtException').add('unhandledRejection');
82-
71+
const { testNamePatterns, testOnlyFlag } = parseCommandLine();
8372

8473
function stopTest(timeout, signal) {
8574
if (timeout === kDefaultTimeout) {

lib/internal/test_runner/utils.js

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use strict';
22
const {
3+
ArrayPrototypeMap,
34
ArrayPrototypePush,
45
ObjectGetOwnPropertyDescriptor,
56
SafePromiseAllReturnArrayLike,
@@ -148,8 +149,27 @@ async function getReportersMap(reporters, destinations) {
148149

149150

150151
async function setupTestReporters(testsStream) {
152+
const { reporters, destinations } = parseCommandLine();
153+
const reportersMap = await getReportersMap(reporters, destinations);
154+
for (let i = 0; i < reportersMap.length; i++) {
155+
const { reporter, destination } = reportersMap[i];
156+
compose(testsStream, reporter).pipe(destination);
157+
}
158+
}
159+
160+
let globalTestOptions;
161+
162+
function parseCommandLine() {
163+
if (globalTestOptions) {
164+
return globalTestOptions;
165+
}
166+
167+
const isTestRunner = getOptionValue('--test');
168+
const coverage = getOptionValue('--experimental-test-coverage');
151169
const destinations = getOptionValue('--test-reporter-destination');
152170
const reporters = getOptionValue('--test-reporter');
171+
let testNamePatterns;
172+
let testOnlyFlag;
153173

154174
if (reporters.length === 0 && destinations.length === 0) {
155175
ArrayPrototypePush(reporters, kDefaultReporter);
@@ -160,15 +180,37 @@ async function setupTestReporters(testsStream) {
160180
}
161181

162182
if (destinations.length !== reporters.length) {
163-
throw new ERR_INVALID_ARG_VALUE('--test-reporter', reporters,
164-
'must match the number of specified \'--test-reporter-destination\'');
183+
throw new ERR_INVALID_ARG_VALUE(
184+
'--test-reporter',
185+
reporters,
186+
'must match the number of specified \'--test-reporter-destination\'',
187+
);
165188
}
166189

167-
const reportersMap = await getReportersMap(reporters, destinations);
168-
for (let i = 0; i < reportersMap.length; i++) {
169-
const { reporter, destination } = reportersMap[i];
170-
compose(testsStream, reporter).pipe(destination);
190+
if (isTestRunner) {
191+
testOnlyFlag = false;
192+
testNamePatterns = null;
193+
} else {
194+
const testNamePatternFlag = getOptionValue('--test-name-pattern');
195+
testOnlyFlag = getOptionValue('--test-only');
196+
testNamePatterns = testNamePatternFlag?.length > 0 ?
197+
ArrayPrototypeMap(
198+
testNamePatternFlag,
199+
(re) => convertStringToRegExp(re, '--test-name-pattern'),
200+
) : null;
171201
}
202+
203+
globalTestOptions = {
204+
__proto__: null,
205+
isTestRunner,
206+
coverage,
207+
testOnlyFlag,
208+
testNamePatterns,
209+
reporters,
210+
destinations,
211+
};
212+
213+
return globalTestOptions;
172214
}
173215

174216
module.exports = {
@@ -177,5 +219,6 @@ module.exports = {
177219
doesPathMatchFilter,
178220
isSupportedFileType,
179221
isTestFailureError,
222+
parseCommandLine,
180223
setupTestReporters,
181224
};

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy