Skip to content
Merged
3 changes: 2 additions & 1 deletion docs-next/src/content/docs/running/configuring.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ title: Configuring Mocha (Node.js)
Mocha supports configuration files, typical of modern command-line tools, in several formats:

- **JavaScript**: Create a `.mocharc.js` (or `.mocharc.cjs` when using [`"type"="module"`](/explainers/nodejs-native-esm-support) in your `package.json`)
in your project's root directory, and export an object (`module.exports = {/* ... */}`) containing your configuration.
in your project's root directory, and export an object (`module.exports = {/* ... */}`) containing your configuration. For native ESM and using `type="module"`
or using `.mjs`, use a default export (`default export {/* ... */}`).
- **YAML**: Create a `.mocharc.yaml` (or `.mocharc.yml`) in your project's root directory.
- **JSON**: Create a `.mocharc.json` (or `.mocharc.jsonc`) in your project's root directory.
Comments--while not valid JSON--are allowed in this file, and will be ignored by Mocha.
Expand Down
4 changes: 3 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2257,7 +2257,9 @@ The HTML reporter is the default reporter when running Mocha in the browser. It

Mocha supports configuration files, typical of modern command-line tools, in several formats:

- **JavaScript**: Create a `.mocharc.js` (or `.mocharc.cjs` when using [`"type"="module"`](#nodejs-native-esm-support) in your `package.json`)
- **JavaScript**: Create a `.mocharc.js` (or `.mocharc.cjs` when using [`"type"="module"`](/explainers/nodejs-native-esm-support) in your `package.json`)
in your project's root directory, and export an object (`module.exports = {/* ... */}`) containing your configuration. For native ESM and using `type="module"`
or using `.mjs`, use a default export (`default export {/* ... */}`).
in your project's root directory, and export an object (`module.exports = {/* ... */}`) containing your configuration.
- **YAML**: Create a `.mocharc.yaml` (or `.mocharc.yml`) in your project's root directory.
- **JSON**: Create a `.mocharc.json` (or `.mocharc.jsonc`) in your project's root directory. Comments — while not valid JSON — are allowed in this file, and will be ignored by Mocha.
Expand Down
6 changes: 4 additions & 2 deletions lib/cli/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const utils = require("../utils");
exports.CONFIG_FILES = [
".mocharc.cjs",
".mocharc.js",
".mocharc.mjs",
".mocharc.yaml",
".mocharc.yml",
".mocharc.jsonc",
Expand Down Expand Up @@ -72,8 +73,9 @@ exports.loadConfig = (filepath) => {
try {
if (ext === ".yml" || ext === ".yaml") {
config = parsers.yaml(filepath);
} else if (ext === ".js" || ext === ".cjs") {
config = parsers.js(filepath);
} else if (ext === ".js" || ext === ".cjs" || ext === ".mjs") {
const parsedConfig = parsers.js(filepath);
config = parsedConfig.default ?? parsedConfig;
} else {
config = parsers.json(filepath);
}
Expand Down
10 changes: 6 additions & 4 deletions test/integration/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ var loadConfig = require("../../lib/cli/config").loadConfig;
describe("config", function () {
it("should return the same values for all supported config types", function () {
var configDir = path.join(__dirname, "fixtures", "config");
var js = loadConfig(path.join(configDir, "mocharc.js"));
var js = loadConfig(path.join(configDir, "mocharc.js")); // canonical form
var cjs = loadConfig(path.join(configDir, "mocharc.cjs"));
var json = loadConfig(path.join(configDir, "mocharc.json"));
var mjs = loadConfig(path.join(configDir, "mocharc.mjs"));
var yaml = loadConfig(path.join(configDir, "mocharc.yaml"));
expect(js, "to equal", json);
expect(js, "to equal", cjs);
expect(json, "to equal", yaml);
expect(cjs, "to equal", js);
expect(json, "to equal", js);
expect(mjs, "to equal", js);
expect(yaml, "to equal", js);
});

describe('when configuring Mocha via a ".js" file', function () {
Expand Down
7 changes: 7 additions & 0 deletions test/integration/fixtures/config/mocharc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// a comment
export default {
require: ['foo', 'bar'],
bail: true,
reporter: 'dot',
slow: 60
};
61 changes: 36 additions & 25 deletions test/node-unit/cli/config.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,12 @@ describe("cli/config", function () {
sinon.stub(parsers, "js").returns(phonyConfigObject);
});

describe('when supplied a filepath with ".yaml" extension', function () {
const filepath = "foo.yaml";

it("should use the YAML parser", function () {
loadConfig(filepath);
expect(parsers.yaml, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
});

describe('when supplied a filepath with ".yml" extension', function () {
const filepath = "foo.yml";
describe('when supplied a filepath with ".cjs" extension', function () {
const filepath = "foo.cjs";

it("should use the YAML parser", function () {
it("should use the JS parser", function () {
loadConfig(filepath);
expect(parsers.yaml, "to have calls satisfying", [
expect(parsers.js, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
Expand All @@ -63,12 +52,12 @@ describe("cli/config", function () {
});
});

describe('when supplied a filepath with ".cjs" extension', function () {
const filepath = "foo.cjs";
describe('when supplied a filepath with ".json" extension', function () {
const filepath = "foo.json";

it("should use the JS parser", function () {
loadConfig(filepath);
expect(parsers.js, "to have calls satisfying", [
it("should use the JSON parser", function () {
loadConfig("foo.json");
expect(parsers.json, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
Expand All @@ -85,12 +74,34 @@ describe("cli/config", function () {
});
});

describe('when supplied a filepath with ".json" extension', function () {
const filepath = "foo.json";
describe('when supplied a filepath with ".mjs" extension', function () {
const filepath = "foo.mjs";

it("should use the JSON parser", function () {
loadConfig("foo.json");
expect(parsers.json, "to have calls satisfying", [
it("should use the JS parser", function () {
loadConfig(filepath);
expect(parsers.js, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
});

describe('when supplied a filepath with ".yaml" extension', function () {
const filepath = "foo.yaml";

it("should use the YAML parser", function () {
loadConfig(filepath);
expect(parsers.yaml, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
});

describe('when supplied a filepath with ".yml" extension', function () {
const filepath = "foo.yml";

it("should use the YAML parser", function () {
loadConfig(filepath);
expect(parsers.yaml, "to have calls satisfying", [
{ args: [filepath], returned: phonyConfigObject },
]).and("was called once");
});
Expand Down