From 8f2ced2f53db0174344881525e361fd98566ff87 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Fri, 21 Nov 2025 08:29:35 +0100 Subject: [PATCH 1/5] src: rename config file testRunner to test --- doc/api/cli.md | 4 +-- doc/node-config-schema.json | 2 +- src/node_config_file.cc | 14 +++++++++- src/node_options.h | 2 +- .../options-as-flags/test-config.json | 2 +- .../rc/deprecated-testrunner-namespace.json | 5 ++++ .../node.config.json | 2 +- test/fixtures/rc/empty-valid-namespace.json | 2 +- test/fixtures/rc/namespace-with-array.json | 2 +- .../rc/namespace-with-disallowed-envvar.json | 2 +- test/fixtures/rc/namespaced/node.config.json | 2 +- test/fixtures/rc/override-namespace.json | 2 +- .../override-node-option-with-namespace.json | 2 +- test/fixtures/rc/unknown-flag-namespace.json | 2 +- .../options-propagation/node.config.json | 2 +- test/parallel/test-config-file.js | 14 +++++++++- test/parallel/test-runner-flag-propagation.js | 26 +++++++++---------- 17 files changed, 58 insertions(+), 29 deletions(-) create mode 100644 test/fixtures/rc/deprecated-testrunner-namespace.json diff --git a/doc/api/cli.md b/doc/api/cli.md index 79fe3094ba2301..67685462b244df 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1016,7 +1016,7 @@ in the `$schema` must be replaced with the version of Node.js you are using. "watch-path": "src", "watch-preserve-output": true }, - "testRunner": { + "test": { "test-isolation": "process" }, "watch": { @@ -1029,7 +1029,7 @@ The configuration file supports namespace-specific options: * The `nodeOptions` field contains CLI flags that are allowed in [`NODE_OPTIONS`][]. -* Namespace fields like `testRunner` contain configuration specific to that subsystem. +* Namespace fields like `test` contain configuration specific to that subsystem. No-op flags are not supported. Not all V8 flags are currently supported. diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index 916bc1c4f62002..c773f3fbd2aae0 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -655,7 +655,7 @@ } } }, - "testRunner": { + "test": { "type": "object", "additionalProperties": false, "properties": { diff --git a/src/node_config_file.cc b/src/node_config_file.cc index e6c049b4d14f10..58dfdc35829f83 100644 --- a/src/node_config_file.cc +++ b/src/node_config_file.cc @@ -262,8 +262,20 @@ ParseResult ConfigReader::ParseConfig(const std::string_view& config_path) { return ParseResult::InvalidContent; } - // Check if this field is a valid namespace std::string namespace_name(field_name); + + // TODO(@marco-ippolito): Remove warning for testRunner namespace + if (namespace_name == "testRunner") { + FPrintF(stderr, + "the \"testRunner\" namespace has been removed. " + "Use \"test\" instead.\n"); + // Better to throw an error than to ignore it + // Otherwise users might think their test suite is green + // when it's not running + return ParseResult::InvalidContent; + } + + // Check if this field is a valid namespace if (!valid_namespaces.contains(namespace_name)) { // If not, skip it continue; diff --git a/src/node_options.h b/src/node_options.h index 9afdeb983d6b26..dd782b460aef79 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -415,7 +415,7 @@ std::vector MapAvailableNamespaces(); // Define all namespace entries #define OPTION_NAMESPACE_LIST(V) \ V(kNoNamespace, "") \ - V(kTestRunnerNamespace, "testRunner") \ + V(kTestRunnerNamespace, "test") \ V(kWatchNamespace, "watch") \ V(kPermissionNamespace, "permission") diff --git a/test/fixtures/options-as-flags/test-config.json b/test/fixtures/options-as-flags/test-config.json index c80ffa4069fbf5..aa6355c37a1681 100644 --- a/test/fixtures/options-as-flags/test-config.json +++ b/test/fixtures/options-as-flags/test-config.json @@ -3,7 +3,7 @@ "experimental-transform-types": true, "max-http-header-size": 8192 }, - "testRunner": { + "test": { "test-isolation": "none" } } diff --git a/test/fixtures/rc/deprecated-testrunner-namespace.json b/test/fixtures/rc/deprecated-testrunner-namespace.json new file mode 100644 index 00000000000000..d8a01949418cf7 --- /dev/null +++ b/test/fixtures/rc/deprecated-testrunner-namespace.json @@ -0,0 +1,5 @@ +{ + "testRunner": { + "test-isolation": "none" + } +} diff --git a/test/fixtures/rc/duplicate-namespace-option/node.config.json b/test/fixtures/rc/duplicate-namespace-option/node.config.json index 4d948fbd33961d..948dc4e6c5570b 100644 --- a/test/fixtures/rc/duplicate-namespace-option/node.config.json +++ b/test/fixtures/rc/duplicate-namespace-option/node.config.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "test-name-pattern": "first-pattern", "test-name-pattern": "second-pattern" } diff --git a/test/fixtures/rc/empty-valid-namespace.json b/test/fixtures/rc/empty-valid-namespace.json index dbeb33d7aa8b59..c267aa9bde2918 100644 --- a/test/fixtures/rc/empty-valid-namespace.json +++ b/test/fixtures/rc/empty-valid-namespace.json @@ -1,3 +1,3 @@ { - "testRunner": {} + "test": {} } diff --git a/test/fixtures/rc/namespace-with-array.json b/test/fixtures/rc/namespace-with-array.json index 056a4291e9b666..1cddcdfd6c4ccd 100644 --- a/test/fixtures/rc/namespace-with-array.json +++ b/test/fixtures/rc/namespace-with-array.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "test-coverage-exclude": ["config-pattern1", "config-pattern2"] } } diff --git a/test/fixtures/rc/namespace-with-disallowed-envvar.json b/test/fixtures/rc/namespace-with-disallowed-envvar.json index 6152684e0583f4..f545f0ff62781f 100644 --- a/test/fixtures/rc/namespace-with-disallowed-envvar.json +++ b/test/fixtures/rc/namespace-with-disallowed-envvar.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "test-concurrency": 1, "experimental-test-coverage": true } diff --git a/test/fixtures/rc/namespaced/node.config.json b/test/fixtures/rc/namespaced/node.config.json index df929d25c10b52..0870c4c86033b2 100644 --- a/test/fixtures/rc/namespaced/node.config.json +++ b/test/fixtures/rc/namespaced/node.config.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "test-isolation": "none" } } diff --git a/test/fixtures/rc/override-namespace.json b/test/fixtures/rc/override-namespace.json index acb37b2eec485c..be79cf5d4415b5 100644 --- a/test/fixtures/rc/override-namespace.json +++ b/test/fixtures/rc/override-namespace.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "test-isolation": "process" }, "nodeOptions": { diff --git a/test/fixtures/rc/override-node-option-with-namespace.json b/test/fixtures/rc/override-node-option-with-namespace.json index 2db9e1a47f07ea..e5912da99590b4 100644 --- a/test/fixtures/rc/override-node-option-with-namespace.json +++ b/test/fixtures/rc/override-node-option-with-namespace.json @@ -2,7 +2,7 @@ "nodeOptions": { "test-isolation": "none" }, - "testRunner": { + "test": { "test-isolation": "process" } } diff --git a/test/fixtures/rc/unknown-flag-namespace.json b/test/fixtures/rc/unknown-flag-namespace.json index b5d87ad8dd3acd..01dd62824cf2b9 100644 --- a/test/fixtures/rc/unknown-flag-namespace.json +++ b/test/fixtures/rc/unknown-flag-namespace.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "unknown-flag": true } } diff --git a/test/fixtures/test-runner/options-propagation/node.config.json b/test/fixtures/test-runner/options-propagation/node.config.json index 98a35b7d3eebd2..7bb3d5c80fe0e5 100644 --- a/test/fixtures/test-runner/options-propagation/node.config.json +++ b/test/fixtures/test-runner/options-propagation/node.config.json @@ -1,5 +1,5 @@ { - "testRunner": { + "test": { "experimental-test-coverage": true } } diff --git a/test/parallel/test-config-file.js b/test/parallel/test-config-file.js index 4f4e6703f88702..ca4c89200fd5b0 100644 --- a/test/parallel/test-config-file.js +++ b/test/parallel/test-config-file.js @@ -421,7 +421,7 @@ describe('namespace-scoped options', () => { fixtures.path('rc/unknown-flag-namespace.json'), '-p', '"Hello, World!"', ]); - assert.match(result.stderr, /Unknown or not allowed option unknown-flag for namespace testRunner/); + assert.match(result.stderr, /Unknown or not allowed option unknown-flag for namespace test/); assert.strictEqual(result.stdout, ''); assert.strictEqual(result.code, 9); }); @@ -542,4 +542,16 @@ describe('namespace-scoped options', () => { assert.strictEqual(result.stdout, '2\n'); assert.strictEqual(result.code, 0); }); + + it('should throw an error for removed "testRunner" namespace', async () => { + const result = await spawnPromisified(process.execPath, [ + '--no-warnings', + '--experimental-config-file', + fixtures.path('rc/deprecated-testrunner-namespace.json'), + '-p', '"Hello, World!"', + ]); + assert.match(result.stderr, /the "testRunner" namespace has been removed\. Use "test" instead\./); + assert.strictEqual(result.stdout, ''); + assert.strictEqual(result.code, 9); + }); }); diff --git a/test/parallel/test-runner-flag-propagation.js b/test/parallel/test-runner-flag-propagation.js index d5190251ef8db7..3248b91bcef24d 100644 --- a/test/parallel/test-runner-flag-propagation.js +++ b/test/parallel/test-runner-flag-propagation.js @@ -68,19 +68,19 @@ describe('test runner flag propagation', () => { describe('via config file', () => { const configFilePropagationTests = [ - ['--test-concurrency', 2, 2, 'testRunner'], - ['--test-timeout', 5000, 5000, 'testRunner'], - ['--test-coverage-branches', 100, 100, 'testRunner'], - ['--test-coverage-functions', 100, 100, 'testRunner'], - ['--test-coverage-lines', 100, 100, 'testRunner'], - ['--experimental-test-coverage', true, false, 'testRunner'], - ['--test-coverage-exclude', 'test/**', 'test/**', 'testRunner'], - ['--test-coverage-include', 'src/**', 'src/**', 'testRunner'], - ['--test-update-snapshots', true, true, 'testRunner'], - ['--test-concurrency', 3, 3, 'testRunner'], - ['--test-timeout', 2500, 2500, 'testRunner'], - ['--test-coverage-branches', 90, 90, 'testRunner'], - ['--test-coverage-functions', 85, 85, 'testRunner'], + ['--test-concurrency', 2, 2, 'test'], + ['--test-timeout', 5000, 5000, 'test'], + ['--test-coverage-branches', 100, 100, 'test'], + ['--test-coverage-functions', 100, 100, 'test'], + ['--test-coverage-lines', 100, 100, 'test'], + ['--experimental-test-coverage', true, false, 'test'], + ['--test-coverage-exclude', 'test/**', 'test/**', 'test'], + ['--test-coverage-include', 'src/**', 'src/**', 'test'], + ['--test-update-snapshots', true, true, 'test'], + ['--test-concurrency', 3, 3, 'test'], + ['--test-timeout', 2500, 2500, 'test'], + ['--test-coverage-branches', 90, 90, 'test'], + ['--test-coverage-functions', 85, 85, 'test'], ]; for (const [flagName, configValue, expectedValue, namespace] of configFilePropagationTests) { From a2c66aa4ca654eb4e2e71501eceea6fe63f54c78 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Fri, 21 Nov 2025 08:49:24 +0100 Subject: [PATCH 2/5] src: add test flag to config file --- doc/node-config-schema.json | 3 +++ src/node_options.cc | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index c773f3fbd2aae0..140f23de84ff1d 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -665,6 +665,9 @@ "experimental-test-module-mocks": { "type": "boolean" }, + "test": { + "type": "boolean" + }, "test-concurrency": { "type": "number" }, diff --git a/src/node_options.cc b/src/node_options.cc index 959a5df163b609..b37296f76faab6 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -839,7 +839,9 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { AddOption("--test", "launch test runner on startup", &EnvironmentOptions::test_runner, - kDisallowedInEnvvar); + kDisallowedInEnvvar, + false, + OptionNamespaces::kTestRunnerNamespace); AddOption("--test-concurrency", "specify test runner concurrency", &EnvironmentOptions::test_runner_concurrency, From 3808504f514fe8db5fec8c87886ae6cd4e563ab0 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Fri, 21 Nov 2025 08:50:55 +0100 Subject: [PATCH 3/5] src: add permission flag to config file --- doc/node-config-schema.json | 3 +++ src/node_options.cc | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index 140f23de84ff1d..6bf7ffd8e74228 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -652,6 +652,9 @@ }, "allow-worker": { "type": "boolean" + }, + "permission": { + "type": "boolean" } } }, diff --git a/src/node_options.cc b/src/node_options.cc index b37296f76faab6..baa3936075cd05 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -599,7 +599,8 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() { "enable the permission system", &EnvironmentOptions::permission, kAllowedInEnvvar, - false); + false, + OptionNamespaces::kPermissionNamespace); AddOption("--allow-fs-read", "allow permissions to read the filesystem", &EnvironmentOptions::allow_fs_read, From be02a0251cb3680dee01805a129090e66af9757b Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Fri, 21 Nov 2025 09:09:25 +0100 Subject: [PATCH 4/5] doc: fix webstorage config file property --- doc/node-config-schema.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/node-config-schema.json b/doc/node-config-schema.json index 6bf7ffd8e74228..22f52952af54d4 100644 --- a/doc/node-config-schema.json +++ b/doc/node-config-schema.json @@ -186,6 +186,9 @@ "experimental-websocket": { "type": "boolean" }, + "experimental-webstorage": { + "type": "boolean" + }, "extra-info-on-fatal-exception": { "type": "boolean" }, @@ -594,9 +597,6 @@ "watch-preserve-output": { "type": "boolean" }, - "webstorage": { - "type": "boolean" - }, "zero-fill-buffers": { "type": "boolean" } From 95f4f389ef90f090c5c2fea3dde11366d4d6bf57 Mon Sep 17 00:00:00 2001 From: Marco Ippolito Date: Fri, 21 Nov 2025 10:02:54 +0100 Subject: [PATCH 5/5] src: implicitly enable namespace in config --- doc/api/cli.md | 35 +++++++++++++++- doc/api/permissions.md | 5 ++- src/node_config_file.cc | 23 ++++++++++ .../options-as-flags/test-config.json | 1 + test/fixtures/rc/empty-valid-namespace.json | 2 +- test/fixtures/rc/permission-namespace.json | 5 +++ .../rc/test-namespace-explicit-false.json | 6 +++ test/fixtures/rc/watch-namespace.json | 5 +++ test/parallel/test-config-file.js | 42 +++++++++++++++++++ 9 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/rc/permission-namespace.json create mode 100644 test/fixtures/rc/test-namespace-explicit-false.json create mode 100644 test/fixtures/rc/watch-namespace.json diff --git a/doc/api/cli.md b/doc/api/cli.md index 67685462b244df..aeb901973c2af6 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1029,7 +1029,40 @@ The configuration file supports namespace-specific options: * The `nodeOptions` field contains CLI flags that are allowed in [`NODE_OPTIONS`][]. -* Namespace fields like `test` contain configuration specific to that subsystem. +* Namespace fields like `test`, `watch`, and `permission` contain configuration specific to that subsystem. + +When a namespace is present in the +configuration file, Node.js automatically enables the corresponding flag +(e.g., `--test`, `--watch`, `--permission`). This allows you to configure +subsystem-specific options without explicitly passing the flag on the command line. + +For example: + +```json +{ + "test": { + "test-isolation": "process" + } +} +``` + +is equivalent to: + +```bash +node --test --test-isolation=process +``` + +To disable the automatic flag while still using namespace options, you can +explicitly set the flag to `false` within the namespace: + +```json +{ + "test": { + "test": false, + "test-isolation": "process" + } +} +``` No-op flags are not supported. Not all V8 flags are currently supported. diff --git a/doc/api/permissions.md b/doc/api/permissions.md index dedb314f43e7eb..d36590ec3ae9cd 100644 --- a/doc/api/permissions.md +++ b/doc/api/permissions.md @@ -175,10 +175,11 @@ Example `node.config.json`: } ``` -Run with the configuration file: +When the `permission` namespace is present in the configuration file, Node.js +automatically enables the `--permission` flag. Run with: ```console -$ node --permission --experimental-default-config-file app.js +$ node --experimental-default-config-file app.js ``` #### Using the Permission Model with `npx` diff --git a/src/node_config_file.cc b/src/node_config_file.cc index 58dfdc35829f83..39ea8f3a0634fd 100644 --- a/src/node_config_file.cc +++ b/src/node_config_file.cc @@ -255,6 +255,9 @@ ParseResult ConfigReader::ParseConfig(const std::string_view& config_path) { available_namespaces.end()); // Create a set to track unique options std::unordered_set unique_options; + // Namespaces in OPTION_NAMESPACE_LIST + std::unordered_set namespaces_with_implicit_flags; + // Iterate through the main object to find all namespaces for (auto field : main_object) { std::string_view field_name; @@ -281,6 +284,15 @@ ParseResult ConfigReader::ParseConfig(const std::string_view& config_path) { continue; } + // List of implicit namespace flags + for (auto ns_enum : options_parser::AllNamespaces()) { + std::string ns_str = options_parser::NamespaceEnumToString(ns_enum); + if (!ns_str.empty() && namespace_name == ns_str) { + namespaces_with_implicit_flags.insert(namespace_name); + break; + } + } + // Get the namespace object simdjson::ondemand::object namespace_object; auto field_error = field.value().get_object().get(namespace_object); @@ -302,6 +314,17 @@ ParseResult ConfigReader::ParseConfig(const std::string_view& config_path) { } } + // Add implicit flags for namespaces (--test, --permission, --watch) + // These flags are automatically enabled when their namespace is present + for (const auto& ns : namespaces_with_implicit_flags) { + std::string flag = "--" + ns; + std::string no_flag = "--no-" + ns; + // We skip if the user has already set the flag or its negation + if (!unique_options.contains(flag) && !unique_options.contains(no_flag)) { + namespace_options_.push_back(flag); + } + } + return ParseResult::Valid; } diff --git a/test/fixtures/options-as-flags/test-config.json b/test/fixtures/options-as-flags/test-config.json index aa6355c37a1681..c956eb6d274785 100644 --- a/test/fixtures/options-as-flags/test-config.json +++ b/test/fixtures/options-as-flags/test-config.json @@ -4,6 +4,7 @@ "max-http-header-size": 8192 }, "test": { + "test": false, "test-isolation": "none" } } diff --git a/test/fixtures/rc/empty-valid-namespace.json b/test/fixtures/rc/empty-valid-namespace.json index c267aa9bde2918..9f6cb4b89f91be 100644 --- a/test/fixtures/rc/empty-valid-namespace.json +++ b/test/fixtures/rc/empty-valid-namespace.json @@ -1,3 +1,3 @@ { - "test": {} + "permission": {} } diff --git a/test/fixtures/rc/permission-namespace.json b/test/fixtures/rc/permission-namespace.json new file mode 100644 index 00000000000000..72167d77dd18ec --- /dev/null +++ b/test/fixtures/rc/permission-namespace.json @@ -0,0 +1,5 @@ +{ + "permission": { + "allow-fs-read": "*" + } +} diff --git a/test/fixtures/rc/test-namespace-explicit-false.json b/test/fixtures/rc/test-namespace-explicit-false.json new file mode 100644 index 00000000000000..42e68aa6a43f59 --- /dev/null +++ b/test/fixtures/rc/test-namespace-explicit-false.json @@ -0,0 +1,6 @@ +{ + "test": { + "test": false, + "test-isolation": "none" + } +} diff --git a/test/fixtures/rc/watch-namespace.json b/test/fixtures/rc/watch-namespace.json new file mode 100644 index 00000000000000..11aad97fffd315 --- /dev/null +++ b/test/fixtures/rc/watch-namespace.json @@ -0,0 +1,5 @@ +{ + "watch": { + "watch-preserve-output": true + } +} diff --git a/test/parallel/test-config-file.js b/test/parallel/test-config-file.js index ca4c89200fd5b0..438a138f6ba227 100644 --- a/test/parallel/test-config-file.js +++ b/test/parallel/test-config-file.js @@ -407,6 +407,7 @@ describe('namespace-scoped options', () => { '--expose-internals', '--experimental-config-file', fixtures.path('rc/namespaced/node.config.json'), + '--no-test', '-p', 'require("internal/options").getOptionValue("--test-isolation")', ]); assert.strictEqual(result.stderr, ''); @@ -483,6 +484,7 @@ describe('namespace-scoped options', () => { '--test-isolation', 'process', '--experimental-config-file', fixtures.path('rc/namespaced/node.config.json'), + '--no-test', '-p', 'require("internal/options").getOptionValue("--test-isolation")', ]); assert.strictEqual(result.stderr, ''); @@ -498,6 +500,7 @@ describe('namespace-scoped options', () => { '--test-coverage-exclude', 'cli-pattern2', '--experimental-config-file', fixtures.path('rc/namespace-with-array.json'), + '--no-test', '-p', 'JSON.stringify(require("internal/options").getOptionValue("--test-coverage-exclude"))', ]); assert.strictEqual(result.stderr, ''); @@ -520,6 +523,7 @@ describe('namespace-scoped options', () => { '--expose-internals', '--experimental-config-file', fixtures.path('rc/namespace-with-disallowed-envvar.json'), + '--no-test', '-p', 'require("internal/options").getOptionValue("--test-concurrency")', ]); assert.strictEqual(result.stderr, ''); @@ -536,6 +540,7 @@ describe('namespace-scoped options', () => { '--test-concurrency', '2', '--experimental-config-file', fixtures.path('rc/namespace-with-disallowed-envvar.json'), + '--no-test', '-p', 'require("internal/options").getOptionValue("--test-concurrency")', ]); assert.strictEqual(result.stderr, ''); @@ -554,4 +559,41 @@ describe('namespace-scoped options', () => { assert.strictEqual(result.stdout, ''); assert.strictEqual(result.code, 9); }); + + it('should automatically enable --test flag when test namespace is present', async () => { + const result = await spawnPromisified(process.execPath, [ + '--no-warnings', + '--experimental-config-file', + fixtures.path('rc/namespaced/node.config.json'), + fixtures.path('rc/test.js'), + ]); + assert.strictEqual(result.code, 0); + assert.match(result.stdout, /tests 1/); + }); + + it('should automatically enable --permission flag when permission namespace is present', async () => { + const result = await spawnPromisified(process.execPath, [ + '--no-warnings', + '--expose-internals', + '--experimental-config-file', + fixtures.path('rc/permission-namespace.json'), + '-p', 'require("internal/options").getOptionValue("--permission")', + ]); + assert.strictEqual(result.stderr, ''); + assert.strictEqual(result.stdout, 'true\n'); + assert.strictEqual(result.code, 0); + }); + + it('should respect explicit test: false in test namespace', async () => { + const result = await spawnPromisified(process.execPath, [ + '--no-warnings', + '--expose-internals', + '--experimental-config-file', + fixtures.path('rc/test-namespace-explicit-false.json'), + '-p', 'require("internal/options").getOptionValue("--test")', + ]); + assert.strictEqual(result.stderr, ''); + assert.strictEqual(result.stdout, 'false\n'); + assert.strictEqual(result.code, 0); + }); });