From c8d00a92caf56d719221776f1397fe96b62f7774 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Mon, 24 Apr 2023 20:44:27 +0200
Subject: [PATCH 1/9] test(cli): add tests borrowed from #4407

---
 .../config/mocharc-extended/base.json         |  6 +++++
 .../config/mocharc-extended/extends.json      |  3 +++
 .../config/mocharc-extended/modifiers.json    |  5 ++++
 test/integration/options.spec.js              | 23 +++++++++++++++++++
 4 files changed, 37 insertions(+)
 create mode 100644 test/integration/fixtures/config/mocharc-extended/base.json
 create mode 100644 test/integration/fixtures/config/mocharc-extended/extends.json
 create mode 100644 test/integration/fixtures/config/mocharc-extended/modifiers.json
 create mode 100644 test/integration/options.spec.js

diff --git a/test/integration/fixtures/config/mocharc-extended/base.json b/test/integration/fixtures/config/mocharc-extended/base.json
new file mode 100644
index 0000000000..89c92825f9
--- /dev/null
+++ b/test/integration/fixtures/config/mocharc-extended/base.json
@@ -0,0 +1,6 @@
+{
+  "require": ["foo", "bar"],
+  "bail": true,
+  "reporter": "dot",
+  "slow": 60
+}
diff --git a/test/integration/fixtures/config/mocharc-extended/extends.json b/test/integration/fixtures/config/mocharc-extended/extends.json
new file mode 100644
index 0000000000..715639efd7
--- /dev/null
+++ b/test/integration/fixtures/config/mocharc-extended/extends.json
@@ -0,0 +1,3 @@
+{
+  "extends": "./modifiers.json"
+}
diff --git a/test/integration/fixtures/config/mocharc-extended/modifiers.json b/test/integration/fixtures/config/mocharc-extended/modifiers.json
new file mode 100644
index 0000000000..8e6dcb1d3c
--- /dev/null
+++ b/test/integration/fixtures/config/mocharc-extended/modifiers.json
@@ -0,0 +1,5 @@
+{
+  "extends": "./base.json",
+  "reporter": "html",
+  "slow": 30
+}
diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
new file mode 100644
index 0000000000..b7ad906a7c
--- /dev/null
+++ b/test/integration/options.spec.js
@@ -0,0 +1,23 @@
+'use strict';
+
+var path = require('path');
+var loadOptions = require('../../lib/cli/options').loadOptions;
+
+describe('options', function () {
+  it('Should support extended options', function () {
+    var configDir = path.join(
+      __dirname,
+      'fixtures',
+      'config',
+      'mocharc-extended'
+    );
+    var extended = loadOptions([
+      '--config',
+      path.join(configDir, 'extends.json')
+    ]);
+    expect(extended.require, 'to equal', ['foo', 'bar']);
+    expect(extended.bail, 'to equal', true);
+    expect(extended.reporter, 'to equal', 'html');
+    expect(extended.slow, 'to equal', 30);
+  });
+});

From 865b4ff4f3d4f4cf10cd560c0361169b9de658db Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Mon, 24 Apr 2023 20:45:36 +0200
Subject: [PATCH 2/9] fix(cli): handle `extends` setting properly

---
 lib/cli/config.js | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/lib/cli/config.js b/lib/cli/config.js
index ac719833cf..dcd0defd35 100644
--- a/lib/cli/config.js
+++ b/lib/cli/config.js
@@ -11,6 +11,7 @@ const fs = require('fs');
 const path = require('path');
 const debug = require('debug')('mocha:cli:config');
 const findUp = require('find-up');
+const yargs = require('yargs/yargs');
 const {createUnparsableFileError} = require('../errors');
 const utils = require('../utils');
 
@@ -76,6 +77,10 @@ exports.loadConfig = filepath => {
     } else {
       config = parsers.json(filepath);
     }
+
+    config = yargs(undefined, path.dirname(filepath))
+      .parserConfiguration(require('./options').YARGS_PARSER_CONFIG)
+      .config(config);
   } catch (err) {
     throw createUnparsableFileError(
       `Unable to read/parse ${filepath}: ${err}`,

From 17b190e7ccebc3b02899d55d299111810a44d8c0 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Mon, 24 Apr 2023 21:15:08 +0200
Subject: [PATCH 3/9] test(cli): test the functionality for rc files

---
 .../config/mocharc-extended/.mocharc.json     |  3 ++
 test/integration/options.spec.js              | 35 ++++++++++++++-----
 2 files changed, 30 insertions(+), 8 deletions(-)
 create mode 100644 test/integration/fixtures/config/mocharc-extended/.mocharc.json

diff --git a/test/integration/fixtures/config/mocharc-extended/.mocharc.json b/test/integration/fixtures/config/mocharc-extended/.mocharc.json
new file mode 100644
index 0000000000..98aae677ca
--- /dev/null
+++ b/test/integration/fixtures/config/mocharc-extended/.mocharc.json
@@ -0,0 +1,3 @@
+{
+  "extends": "./extends.json"
+}
diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
index b7ad906a7c..77841ccdd9 100644
--- a/test/integration/options.spec.js
+++ b/test/integration/options.spec.js
@@ -4,20 +4,39 @@ var path = require('path');
 var loadOptions = require('../../lib/cli/options').loadOptions;
 
 describe('options', function () {
-  it('Should support extended options', function () {
-    var configDir = path.join(
-      __dirname,
-      'fixtures',
-      'config',
-      'mocharc-extended'
-    );
+  var workingDirectory;
+  const workspaceDir = path.join(
+    __dirname,
+    'fixtures',
+    'config',
+    'mocharc-extended'
+  );
+
+  beforeEach(function () {
+    workingDirectory = process.cwd();
+    process.chdir(workspaceDir);
+  });
+
+  afterEach(function () {
+    process.chdir(workingDirectory);
+  });
+
+  it('Should support extended options using --config parameter', function () {
     var extended = loadOptions([
       '--config',
-      path.join(configDir, 'extends.json')
+      path.join(workspaceDir, 'extends.json')
     ]);
     expect(extended.require, 'to equal', ['foo', 'bar']);
     expect(extended.bail, 'to equal', true);
     expect(extended.reporter, 'to equal', 'html');
     expect(extended.slow, 'to equal', 30);
   });
+
+  it('Should support extended options using rc file', function () {
+    var extended = loadOptions([]);
+    expect(extended.require, 'to equal', ['foo', 'bar']);
+    expect(extended.bail, 'to equal', true);
+    expect(extended.reporter, 'to equal', 'html');
+    expect(extended.slow, 'to equal', 30);
+  });
 });

From a41006d497705c0031bd4e98d97084f3e88d5d8f Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 18 Jan 2025 00:20:25 +0100
Subject: [PATCH 4/9] fix(cli): malfunctioning config parsing

---
 lib/cli/config.js | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/lib/cli/config.js b/lib/cli/config.js
index dcd0defd35..b50bc36feb 100644
--- a/lib/cli/config.js
+++ b/lib/cli/config.js
@@ -78,9 +78,11 @@ exports.loadConfig = filepath => {
       config = parsers.json(filepath);
     }
 
-    config = yargs(undefined, path.dirname(filepath))
+    const {$0, ...options} = yargs(undefined, path.dirname(filepath))
       .parserConfiguration(require('./options').YARGS_PARSER_CONFIG)
-      .config(config);
+      .config(config).argv;
+
+    config = options;
   } catch (err) {
     throw createUnparsableFileError(
       `Unable to read/parse ${filepath}: ${err}`,

From f5b93cd057443f3c901b24dd6353956af08de7ac Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 18 Jan 2025 00:55:57 +0100
Subject: [PATCH 5/9] test(cli): add failing use case to tests

---
 .../fixtures/config/mocharc-extended/extends.json     |  3 ++-
 test/integration/options.spec.js                      | 11 +++++++----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/test/integration/fixtures/config/mocharc-extended/extends.json b/test/integration/fixtures/config/mocharc-extended/extends.json
index 715639efd7..54cb7122c5 100644
--- a/test/integration/fixtures/config/mocharc-extended/extends.json
+++ b/test/integration/fixtures/config/mocharc-extended/extends.json
@@ -1,3 +1,4 @@
 {
-  "extends": "./modifiers.json"
+  "extends": "./modifiers.json",
+  "_": ["**/*.spec.js"]
 }
diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
index 77841ccdd9..78c892e07c 100644
--- a/test/integration/options.spec.js
+++ b/test/integration/options.spec.js
@@ -11,6 +11,7 @@ describe('options', function () {
     'config',
     'mocharc-extended'
   );
+  const configFile = path.join(workspaceDir, 'extends.json');
 
   beforeEach(function () {
     workingDirectory = process.cwd();
@@ -21,11 +22,13 @@ describe('options', function () {
     process.chdir(workingDirectory);
   });
 
+  it('Should load `_`-option properly', function () {
+    var extended = loadOptions(['--config', configFile]);
+    expect(extended._, 'to equal', ['**/*.spec.js']);
+  });
+
   it('Should support extended options using --config parameter', function () {
-    var extended = loadOptions([
-      '--config',
-      path.join(workspaceDir, 'extends.json')
-    ]);
+    var extended = loadOptions(['--config', configFile]);
     expect(extended.require, 'to equal', ['foo', 'bar']);
     expect(extended.bail, 'to equal', true);
     expect(extended.reporter, 'to equal', 'html');

From 0ca8850a4c66433b3d45bd6db61e43a4aed18bb6 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 18 Jan 2025 00:56:29 +0100
Subject: [PATCH 6/9] fix(cli): treatment of `_` option

---
 lib/cli/config.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cli/config.js b/lib/cli/config.js
index b50bc36feb..a18443296b 100644
--- a/lib/cli/config.js
+++ b/lib/cli/config.js
@@ -78,7 +78,7 @@ exports.loadConfig = filepath => {
       config = parsers.json(filepath);
     }
 
-    const {$0, ...options} = yargs(undefined, path.dirname(filepath))
+    const {$0, ...options} = yargs(config._, path.dirname(filepath))
       .parserConfiguration(require('./options').YARGS_PARSER_CONFIG)
       .config(config).argv;
 

From 4254c8b37a2f353b40d763b8dab1e8949a6f5dab Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 18 Jan 2025 01:13:46 +0100
Subject: [PATCH 7/9] test(cli): add a test for inheritance in `package.json`
 files

---
 test/integration/options.spec.js | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
index 78c892e07c..b9a2b659f0 100644
--- a/test/integration/options.spec.js
+++ b/test/integration/options.spec.js
@@ -42,4 +42,16 @@ describe('options', function () {
     expect(extended.reporter, 'to equal', 'html');
     expect(extended.slow, 'to equal', 30);
   });
+
+  it('Should support extended options using package.json', function () {
+    var extended = loadOptions([
+      '--package',
+      path.join(workspaceDir, 'package-lock.json')
+    ]);
+    expect(extended.require, 'to equal', ['foo', 'bar']);
+    expect(extended.bail, 'to equal', true);
+    expect(extended.reporter, 'to equal', 'html');
+    expect(extended.slow, 'to equal', 30);
+    expect(extended.grep, 'to equal', 'package');
+  });
 });

From 0bda388c840646d29eab25ba67b992e76b832fb2 Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Sat, 18 Jan 2025 01:26:39 +0100
Subject: [PATCH 8/9] fix(cli): add proper `extends` support for `package.json`
 files

---
 lib/cli/config.js                             |  7 -------
 lib/cli/options.js                            | 20 +++++++++++++++++--
 .../config/mocharc-extended/package-lock.json |  6 ++++++
 test/integration/options.spec.js              |  1 +
 4 files changed, 25 insertions(+), 9 deletions(-)
 create mode 100644 test/integration/fixtures/config/mocharc-extended/package-lock.json

diff --git a/lib/cli/config.js b/lib/cli/config.js
index a18443296b..ac719833cf 100644
--- a/lib/cli/config.js
+++ b/lib/cli/config.js
@@ -11,7 +11,6 @@ const fs = require('fs');
 const path = require('path');
 const debug = require('debug')('mocha:cli:config');
 const findUp = require('find-up');
-const yargs = require('yargs/yargs');
 const {createUnparsableFileError} = require('../errors');
 const utils = require('../utils');
 
@@ -77,12 +76,6 @@ exports.loadConfig = filepath => {
     } else {
       config = parsers.json(filepath);
     }
-
-    const {$0, ...options} = yargs(config._, path.dirname(filepath))
-      .parserConfiguration(require('./options').YARGS_PARSER_CONFIG)
-      .config(config).argv;
-
-    config = options;
   } catch (err) {
     throw createUnparsableFileError(
       `Unable to read/parse ${filepath}: ${err}`,
diff --git a/lib/cli/options.js b/lib/cli/options.js
index 09351957b4..bd4b115a7f 100644
--- a/lib/cli/options.js
+++ b/lib/cli/options.js
@@ -8,7 +8,9 @@
  */
 
 const fs = require('fs');
+const path = require('path');
 const ansi = require('ansi-colors');
+const yargs = require('yargs/yargs');
 const yargsParser = require('yargs-parser');
 const {
   types,
@@ -212,7 +214,7 @@ const parse = (args = [], defaultValues = {}, ...configObjects) => {
 const loadRc = (args = {}) => {
   if (args.config !== false) {
     const config = args.config || findConfig();
-    return config ? loadConfig(config) : {};
+    return config ? loadRcFile(loadConfig(config), config) : {};
   }
 };
 
@@ -254,7 +256,7 @@ const loadPkgRc = (args = {}) => {
       const pkg = JSON.parse(configData);
       if (pkg.mocha) {
         debug('`mocha` prop of package.json parsed: %O', pkg.mocha);
-        result = pkg.mocha;
+        result = loadRcFile(pkg.mocha, filepath);
       } else {
         debug('no config found in %s', filepath);
       }
@@ -271,6 +273,20 @@ const loadPkgRc = (args = {}) => {
 
 module.exports.loadPkgRc = loadPkgRc;
 
+/**
+ * Loads the inherited configuration of the rc file located at the specified {@linkcode filePath}.
+ *
+ * @param {Object} config - The parsed configuration of the rc file.
+ * @param {string} filePath - The name of the file containing the parsed configuration.
+ */
+const loadRcFile = (config, filePath) => {
+  const {$0, ...options} = yargs(config._, path.dirname(filePath))
+    .parserConfiguration(configuration)
+    .config(config).argv;
+
+  return options;
+};
+
 /**
  * Priority list:
  *
diff --git a/test/integration/fixtures/config/mocharc-extended/package-lock.json b/test/integration/fixtures/config/mocharc-extended/package-lock.json
new file mode 100644
index 0000000000..12dd16138f
--- /dev/null
+++ b/test/integration/fixtures/config/mocharc-extended/package-lock.json
@@ -0,0 +1,6 @@
+{
+    "mocha": {
+        "extends": "./extends.json",
+        "grep": "package"
+    }
+}
diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
index b9a2b659f0..6f03fca663 100644
--- a/test/integration/options.spec.js
+++ b/test/integration/options.spec.js
@@ -45,6 +45,7 @@ describe('options', function () {
 
   it('Should support extended options using package.json', function () {
     var extended = loadOptions([
+      '--no-config',
       '--package',
       path.join(workspaceDir, 'package-lock.json')
     ]);

From 8f748dd8b51758e1d2f0de429f8a8add6a412c0b Mon Sep 17 00:00:00 2001
From: Manuel Thalmann <m@nuth.ch>
Date: Tue, 28 Jan 2025 22:02:09 +0100
Subject: [PATCH 9/9] test(cli): test base file alongside extending files
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Josh Goldberg ✨ <git@joshuakgoldberg.com>
---
 test/integration/options.spec.js | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/test/integration/options.spec.js b/test/integration/options.spec.js
index 6f03fca663..cc79cdf672 100644
--- a/test/integration/options.spec.js
+++ b/test/integration/options.spec.js
@@ -43,6 +43,13 @@ describe('options', function () {
     expect(extended.slow, 'to equal', 30);
   });
 
+  it('Should support standalone options using standalone rc file', function () {
+    var extended = loadOptions(['--config', configFileStandalone]);
+    expect(extended.require, 'to equal', ['foo', 'bar']);
+    expect(extended.bail, 'to equal', true);
+    expect(extended.reporter, 'to equal', 'dot');
+    expect(extended.slow, 'to equal', 60);
+  });
   it('Should support extended options using package.json', function () {
     var extended = loadOptions([
       '--no-config',