Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

esm entrypoint with named exports #4298

Closed
wants to merge 10 commits into from
12 changes: 12 additions & 0 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ overrides:
mocha: true
globals:
expect: readonly
- files:
- test/interfaces/*.{js,mjs}
- lib/entrypoints/*.{js,mjs}
parserOptions:
ecmaVersion: 2018
env:
mocha: true
browser: false
node: true
globals:
expect: readonly
- files:
- bin/*
- lib/**/*.js
Expand Down Expand Up @@ -86,6 +97,7 @@ overrides:
message: *GH-237
- files:
- test/**/*.mjs
- lib/**/*.mjs
parserOptions:
ecmaVersion: 2018
sourceType: module
Expand Down
72 changes: 66 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1523,7 +1523,7 @@ describe('my test suite', function() {

Running `mocha --require test/hooks.js test/test.spec.js` will run as before (and is now ready to be used with [`--parallel`](#-parallel-p)).

### Migrating a Library to use Root Hook PLugins
### Migrating a Library to use Root Hook Plugins

If you're a library maintainer, and your library uses root hooks, you can migrate by refactoring your entry point:

Expand Down Expand Up @@ -1708,6 +1708,13 @@ describe('Array', function() {
});
```

If you prefer not to use globals, you can `require` (CJS) or `import` (ESM) these functions via
the `mocha/bdd` entry point. Example:

```js
const {describe, it} = require('mocha/bdd');
```

### TDD

The **TDD** interface provides `suite()`, `test()`, `suiteSetup()`, `suiteTeardown()`, `setup()`, and `teardown()`:
Expand All @@ -1726,6 +1733,13 @@ suite('Array', function() {
});
```

If you prefer not to use globals, you can `require` (CJS) or `import` (ESM) these functions via
the `mocha/tdd` entry point. Example:

```js
const {suite, test} = require('mocha/tdd');
```

### Exports

The **Exports** interface is much like Mocha's predecessor [expresso][]. The keys `before`, `after`, `beforeEach`, and `afterEach` are special-cased, object values are suites, and function values are test-cases:
Expand Down Expand Up @@ -1776,11 +1790,8 @@ test('#length', function() {
});
```

### Require

The `require` interface allows you to require the `describe` and friend words directly using `require` and call them whatever you want. This interface is also useful if you want to avoid global variables in your tests.

_Note_: The `require` interface cannot be run via the `node` executable, and must be run via `mocha`.
If you prefer not to use globals, you can `require` (CJS) or `import` (ESM) these functions via
the `mocha/qunit` entry point. Example:

```js
var testCase = require('mocha').describe;
Expand All @@ -1801,6 +1812,55 @@ testCase('Array', function() {
});
```

## CommonJS and ESM entrypoints

Instead of relying on the `describe`, `it`, ... globals, you can `require` (CommonJS) or `import` (ES Modules) `mocha`
to import these functions, as described in [interfaces](#interfaces).

_Note_: if you use one interface (using `--ui ...`), the other test functions from the other
interfaces will be `undefined`.

_Note_: If `require` or `import` is used to avoid the use of globals,
the tests cannot be run via the `node` executable, and must be run via `mocha`.

CommonJS example (for the default BDD interface):

```js
const {describe, before, it} = require('mocha');
const assert = require('assert');

describe('Array', function() {
before(function() {
// ...
});

describe('#indexOf()', function() {
it('should return -1 when not present', function() {
assert.strictEqual([1, 2, 3].indexOf(4), -1);
});
});
});
```

ESM example (for the TDD interface):

```js
import {suite, setup, test} from 'mocha';
import assert from 'assert';

suite('Array', function() {
setup(function() {
// ...
});

suite('#indexOf()', function() {
test('should return -1 when not present', function() {
assert.strictEqual([1, 2, 3].indexOf(4), -1);
});
});
});
```

## Reporters

Mocha reporters adjust to the terminal window, and always disable ANSI-escape coloring when the stdio streams are not associated with a TTY.
Expand Down
57 changes: 57 additions & 0 deletions index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/** This file exists only for Node v10. Once v10 support is removed, we can safely delete this file */
import Mocha from './index.js';

export default Mocha;

// API stuff
export const utils = Mocha.utils;
export const interfaces = Mocha.interfaces;
export const reporters = Mocha.reporters;
export const Runnable = Mocha.Runnable;
export const Context = Mocha.Context;
export const Runner = Mocha.Runner;
export const Suite = Mocha.Suite;
export const Hook = Mocha.Hook;
export const Test = Mocha.Test;
export const unloadFile = Mocha.unloadFile;

/*
* Why do we not export Mocha.* directory, but rather pass throug proxy functions?
* Because Mocha.* is changed on each creation of a new Mocha instance,
* and the static Mocha.* is set before running a test suite, and so we
* changes on each new Mocha instance. Usually this is not a problem, as there is only
* one Mocha instance. Except in the instance of parallel execution, where a worker is
* reused to run another test file, and so creates another Mocha instance.
*
*/

// functions used by BDD tests
export const describe = (...args) => Mocha.describe(...args);
describe.only = (...args) => Mocha.describe.only(...args);
describe.skip = (...args) => Mocha.describe.skip(...args);
export const context = (...args) => Mocha.describe(...args);
context.only = (...args) => Mocha.describe.only(...args);
context.skip = (...args) => Mocha.describe.skip(...args);
export const it = (...args) => Mocha.it(...args);
it.only = (...args) => Mocha.it.only(...args);
it.skip = (...args) => Mocha.it.skip(...args);
export const specify = (...args) => Mocha.it(...args);
specify.only = (...args) => Mocha.it.only(...args);
specify.skip = (...args) => Mocha.it.skip(...args);
export const xit = (...args) => Mocha.xit(...args);
export const before = (...args) => Mocha.before(...args); // also used by QUNIT tests
export const after = (...args) => Mocha.after(...args); // also used by QUNIT tests
export const beforeEach = (...args) => Mocha.beforeEach(...args); // also used by QUNIT tests
export const afterEach = (...args) => Mocha.afterEach(...args); // also used by QUNIT tests

// functions used by TDD tests
export const suite = (...args) => Mocha.suite(...args); // also used by QUNIT tests
suite.only = (...args) => Mocha.suite.only(...args);
suite.skip = (...args) => Mocha.suite.skip(...args);
export const test = (...args) => Mocha.test(...args); // also used by QUNIT tests
test.only = (...args) => Mocha.it.only(...args);
test.skip = (...args) => Mocha.it.skip(...args);
export const suiteSetup = (...args) => Mocha.suiteSetup(...args);
export const suiteTeardown = (...args) => Mocha.suiteTeardown(...args);
export const setup = (...args) => Mocha.setup(...args);
export const teardown = (...args) => Mocha.teardown(...args);
20 changes: 20 additions & 0 deletions lib/entrypoints/bdd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'use strict';
const Mocha = require('../../index.js');

exports.describe = (...args) => Mocha.describe(...args);
exports.describe.only = (...args) => Mocha.describe.only(...args);
exports.describe.skip = (...args) => Mocha.describe.skip(...args);
exports.context = (...args) => Mocha.describe(...args);
exports.context.only = (...args) => Mocha.describe.only(...args);
exports.context.skip = (...args) => Mocha.describe.skip(...args);
exports.it = (...args) => Mocha.it(...args);
exports.it.only = (...args) => Mocha.it.only(...args);
exports.it.skip = (...args) => Mocha.it.skip(...args);
exports.specify = (...args) => Mocha.it(...args);
exports.specify.only = (...args) => Mocha.it.only(...args);
exports.specify.skip = (...args) => Mocha.it.skip(...args);
exports.xit = (...args) => Mocha.xit(...args);
exports.before = (...args) => Mocha.before(...args);
exports.after = (...args) => Mocha.after(...args);
exports.beforeEach = (...args) => Mocha.beforeEach(...args);
exports.afterEach = (...args) => Mocha.afterEach(...args);
17 changes: 17 additions & 0 deletions lib/entrypoints/bdd.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import Mocha from '../../index.js';

export const describe = (...args) => Mocha.describe(...args);
describe.only = (...args) => Mocha.describe.only(...args);
describe.skip = (...args) => Mocha.describe.skip(...args);
export const context = (...args) => Mocha.describe(...args);
export const it = (...args) => Mocha.it(...args);
it.only = (...args) => Mocha.it.only(...args);
it.skip = (...args) => Mocha.it.skip(...args);
export const specify = (...args) => Mocha.it(...args);
specify.only = (...args) => Mocha.it.only(...args);
specify.skip = (...args) => Mocha.it.skip(...args);
export const xit = (...args) => Mocha.xit(...args);
export const before = (...args) => Mocha.before(...args);
export const after = (...args) => Mocha.after(...args);
export const beforeEach = (...args) => Mocha.beforeEach(...args);
export const afterEach = (...args) => Mocha.afterEach(...args);
56 changes: 56 additions & 0 deletions lib/entrypoints/index.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Mocha from '../../index.js';

export default Mocha;

// API stuff
export const utils = Mocha.utils;
export const interfaces = Mocha.interfaces;
export const reporters = Mocha.reporters;
export const Runnable = Mocha.Runnable;
export const Context = Mocha.Context;
export const Runner = Mocha.Runner;
export const Suite = Mocha.Suite;
export const Hook = Mocha.Hook;
export const Test = Mocha.Test;
export const unloadFile = Mocha.unloadFile;

/*
* Why do we not export Mocha.* directory, but rather pass throug proxy functions?
* Because Mocha.* is changed on each creation of a new Mocha instance,
* and the static Mocha.* is set before running a test suite, and so we
* changes on each new Mocha instance. Usually this is not a problem, as there is only
* one Mocha instance. Except in the instance of parallel execution, where a worker is
* reused to run another test file, and so creates another Mocha instance.
*
*/

// functions used by BDD tests
export const describe = (...args) => Mocha.describe(...args);
describe.only = (...args) => Mocha.describe.only(...args);
describe.skip = (...args) => Mocha.describe.skip(...args);
export const context = (...args) => Mocha.describe(...args);
context.only = (...args) => Mocha.describe.only(...args);
context.skip = (...args) => Mocha.describe.skip(...args);
export const it = (...args) => Mocha.it(...args);
it.only = (...args) => Mocha.it.only(...args);
it.skip = (...args) => Mocha.it.skip(...args);
export const specify = (...args) => Mocha.it(...args);
specify.only = (...args) => Mocha.it.only(...args);
specify.skip = (...args) => Mocha.it.skip(...args);
export const xit = (...args) => Mocha.xit(...args);
export const before = (...args) => Mocha.before(...args); // also used by QUNIT tests
export const after = (...args) => Mocha.after(...args); // also used by QUNIT tests
export const beforeEach = (...args) => Mocha.beforeEach(...args); // also used by QUNIT tests
export const afterEach = (...args) => Mocha.afterEach(...args); // also used by QUNIT tests

// functions used by TDD tests
export const suite = (...args) => Mocha.suite(...args); // also used by QUNIT tests
suite.only = (...args) => Mocha.suite.only(...args);
suite.skip = (...args) => Mocha.suite.skip(...args);
export const test = (...args) => Mocha.test(...args); // also used by QUNIT tests
test.only = (...args) => Mocha.it.only(...args);
test.skip = (...args) => Mocha.it.skip(...args);
export const suiteSetup = (...args) => Mocha.suiteSetup(...args);
export const suiteTeardown = (...args) => Mocha.suiteTeardown(...args);
export const setup = (...args) => Mocha.setup(...args);
export const teardown = (...args) => Mocha.teardown(...args);
13 changes: 13 additions & 0 deletions lib/entrypoints/qunit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
const Mocha = require('../../index.js');

exports.suite = (...args) => Mocha.suite(...args);
exports.suite.only = (...args) => Mocha.suite.only(...args);
exports.suite.skip = (...args) => Mocha.suite.skip(...args);
exports.test = (...args) => Mocha.test(...args);
exports.test.only = (...args) => Mocha.test.only(...args);
exports.test.skip = (...args) => Mocha.test.skip(...args);
exports.before = (...args) => Mocha.before(...args);
exports.after = (...args) => Mocha.after(...args);
exports.beforeEach = (...args) => Mocha.beforeEach(...args);
exports.afterEach = (...args) => Mocha.afterEach(...args);
12 changes: 12 additions & 0 deletions lib/entrypoints/qunit.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Mocha from '../../index.js';

export const suite = (...args) => Mocha.suite(...args);
suite.only = (...args) => Mocha.suite.only(...args);
suite.skip = (...args) => Mocha.suite.skip(...args);
export const test = (...args) => Mocha.test(...args);
test.only = (...args) => Mocha.it.only(...args);
test.skip = (...args) => Mocha.it.skip(...args);
export const before = (...args) => Mocha.before(...args);
export const after = (...args) => Mocha.after(...args);
export const beforeEach = (...args) => Mocha.beforeEach(...args);
export const afterEach = (...args) => Mocha.afterEach(...args);
13 changes: 13 additions & 0 deletions lib/entrypoints/tdd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
const Mocha = require('../../index.js');

exports.suite = (...args) => Mocha.suite(...args);
exports.suite.only = (...args) => Mocha.suite.only(...args);
exports.suite.skip = (...args) => Mocha.suite.skip(...args);
exports.test = (...args) => Mocha.test(...args);
exports.test.only = (...args) => Mocha.test.only(...args);
exports.test.skip = (...args) => Mocha.test.skip(...args);
exports.suiteSetup = (...args) => Mocha.suiteSetup(...args);
exports.suiteTeardown = (...args) => Mocha.suiteTeardown(...args);
exports.setup = (...args) => Mocha.setup(...args);
exports.teardown = (...args) => Mocha.teardown(...args);
12 changes: 12 additions & 0 deletions lib/entrypoints/tdd.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Mocha from '../../index.js';

export const suite = (...args) => Mocha.suite(...args);
suite.only = (...args) => Mocha.suite.only(...args);
suite.skip = (...args) => Mocha.suite.skip(...args);
export const test = (...args) => Mocha.test(...args);
test.only = (...args) => Mocha.it.only(...args);
test.skip = (...args) => Mocha.it.skip(...args);
export const suiteSetup = (...args) => Mocha.suiteSetup(...args);
export const suiteTeardown = (...args) => Mocha.suiteTeardown(...args);
export const setup = (...args) => Mocha.setup(...args);
export const teardown = (...args) => Mocha.teardown(...args);
Loading