From 8d6d1e359e50badc27c48e5b1aa0c577907663e9 Mon Sep 17 00:00:00 2001 From: Nico Jansen Date: Mon, 1 Mar 2021 16:01:50 +0100 Subject: [PATCH] fix(esm): allow `import` from mocha in parallel (#4574) --- lib/mocha.js | 63 +++++++++++---- test/integration/common-js-require.spec.js | 20 +++++ .../fixtures/common-js-require.fixture.js | 76 +++++++++++++++++++ test/integration/fixtures/parallel/test1.mjs | 5 ++ test/integration/fixtures/parallel/test2.mjs | 5 ++ test/integration/fixtures/parallel/test3.mjs | 7 ++ test/integration/parallel.spec.js | 28 +++++++ 7 files changed, 189 insertions(+), 15 deletions(-) create mode 100644 test/integration/common-js-require.spec.js create mode 100644 test/integration/fixtures/common-js-require.fixture.js create mode 100644 test/integration/fixtures/parallel/test1.mjs create mode 100644 test/integration/fixtures/parallel/test2.mjs create mode 100644 test/integration/fixtures/parallel/test3.mjs create mode 100644 test/integration/parallel.spec.js diff --git a/lib/mocha.js b/lib/mocha.js index 611c33a951..c1bd896b70 100644 --- a/lib/mocha.js +++ b/lib/mocha.js @@ -96,6 +96,52 @@ exports.Suite = Suite; exports.Hook = require('./hook'); exports.Test = require('./test'); +let currentContext; +exports.afterEach = function(...args) { + (currentContext.afterEach || currentContext.teardown).apply(this, args); +}; +exports.after = function(...args) { + (currentContext.after || currentContext.suiteTeardown).apply(this, args); +}; +exports.beforeEach = function(...args) { + (currentContext.beforeEach || currentContext.setup).apply(this, args); +}; +exports.before = function(...args) { + (currentContext.before || currentContext.suiteSetup).apply(this, args); +}; +exports.describe = function(...args) { + (currentContext.describe || currentContext.suite).apply(this, args); +}; +exports.describe.only = function(...args) { + (currentContext.describe || currentContext.suite).only.apply(this, args); +}; +exports.describe.skip = function(...args) { + (currentContext.describe || currentContext.suite).skip.apply(this, args); +}; +exports.it = function(...args) { + (currentContext.it || currentContext.test).apply(this, args); +}; +exports.it.only = function(...args) { + (currentContext.it || currentContext.test).only.apply(this, args); +}; +exports.it.skip = function(...args) { + ( + currentContext.xit || + (currentContext.test && currentContext.test.skip) + ).apply(this, args); +}; +exports.xdescribe = exports.describe.skip; +exports.xit = exports.it.skip; +exports.setup = exports.beforeEach; +exports.suiteSetup = exports.before; +exports.suiteTeardown = exports.after; +exports.suite = exports.describe; +exports.teardown = exports.afterEach; +exports.test = exports.it; +exports.run = function(...args) { + currentContext.run.apply(this, args); +}; + /** * Constructs a new Mocha instance with `options`. * @@ -351,20 +397,7 @@ Mocha.prototype.ui = function(ui) { bindInterface(this.suite); this.suite.on(EVENT_FILE_PRE_REQUIRE, function(context) { - exports.afterEach = context.afterEach || context.teardown; - exports.after = context.after || context.suiteTeardown; - exports.beforeEach = context.beforeEach || context.setup; - exports.before = context.before || context.suiteSetup; - exports.describe = context.describe || context.suite; - exports.it = context.it || context.test; - exports.xit = context.xit || (context.test && context.test.skip); - exports.setup = context.setup || context.beforeEach; - exports.suiteSetup = context.suiteSetup || context.before; - exports.suiteTeardown = context.suiteTeardown || context.after; - exports.suite = context.suite || context.describe; - exports.teardown = context.teardown || context.afterEach; - exports.test = context.test || context.it; - exports.run = context.run; + currentContext = context; }); return this; @@ -1299,7 +1332,7 @@ Mocha.prototype.hasGlobalTeardownFixtures = function hasGlobalTeardownFixtures() * A (sync) function to assert a user-supplied plugin implementation is valid. * * Defined in a {@link PluginDefinition}. - + * @callback PluginValidator * @param {*} value - Value to check * @this {PluginDefinition} diff --git a/test/integration/common-js-require.spec.js b/test/integration/common-js-require.spec.js new file mode 100644 index 0000000000..43a59d6532 --- /dev/null +++ b/test/integration/common-js-require.spec.js @@ -0,0 +1,20 @@ +'use strict'; + +const {runMochaAsync} = require('./helpers'); + +describe('common js require', () => { + it('should be able to run a test where all mocha exports are used', async () => { + const result = await runMochaAsync('common-js-require.fixture.js', [ + '--delay' + ]); + expect(result.output, 'to contain', 'running before'); + expect(result.output, 'to contain', 'running suiteSetup'); + expect(result.output, 'to contain', 'running setup'); + expect(result.output, 'to contain', 'running beforeEach'); + expect(result.output, 'to contain', 'running it'); + expect(result.output, 'to contain', 'running afterEach'); + expect(result.output, 'to contain', 'running teardown'); + expect(result.output, 'to contain', 'running suiteTeardown'); + expect(result.output, 'to contain', 'running after'); + }); +}); diff --git a/test/integration/fixtures/common-js-require.fixture.js b/test/integration/fixtures/common-js-require.fixture.js new file mode 100644 index 0000000000..0573f6f0f9 --- /dev/null +++ b/test/integration/fixtures/common-js-require.fixture.js @@ -0,0 +1,76 @@ +const { afterEach, + after, + beforeEach, + before, + describe, + xdescribe, + it, + xit, + setup, + suiteSetup, + suiteTeardown, + suite, + teardown, + test, + run } = require('../../..'); + + +suite('root suite', () => { + setup(() => { + console.log('running setup'); + }) + before(() => { + console.log('running before'); + }); + beforeEach(() => { + console.log('running beforeEach'); + }); + afterEach(() => { + console.log('running afterEach'); + }); + after(() => { + console.log('running after'); + }); + teardown(() => { + console.log('running teardown'); + }); + suiteSetup(() => { + console.log('running suiteSetup'); + }); + suiteTeardown(() => { + console.log('running suiteTeardown'); + }); + + describe.only('describe only', () => { + it('it', () => { + console.log('running it'); + }); + xit('it', () => { + console.log('running xit'); + }); + it.only('it.only', () => { + console.log('running it.only'); + }); + it.skip('it.skip', () => { + console.log('running it.skip'); + }); + test('test', () => { + console.log('running test'); + }); + }); + + describe('describe', () => {}); + + xdescribe('xdescribe', () => {}); + + describe.skip('describe.skip', () => {}); + + suite.only('suite only', () => {}); + + suite.skip('suite.skip', () => {}); + +}); + +// using `run` here makes it so this suite needs to be run with `--delay` mode. +// adding it here to test that `run` is correctly exported from mocha. +setTimeout(run, 0); diff --git a/test/integration/fixtures/parallel/test1.mjs b/test/integration/fixtures/parallel/test1.mjs new file mode 100644 index 0000000000..5be1220adb --- /dev/null +++ b/test/integration/fixtures/parallel/test1.mjs @@ -0,0 +1,5 @@ +import {describe,it} from "../../../../index.js"; + +describe('test1', () => { + it('should pass', () => {}); +}); diff --git a/test/integration/fixtures/parallel/test2.mjs b/test/integration/fixtures/parallel/test2.mjs new file mode 100644 index 0000000000..abd1f97ae0 --- /dev/null +++ b/test/integration/fixtures/parallel/test2.mjs @@ -0,0 +1,5 @@ +import {describe,it} from "../../../../index.js"; + +describe('test2', () => { + it('should pass', () => {}); +}); diff --git a/test/integration/fixtures/parallel/test3.mjs b/test/integration/fixtures/parallel/test3.mjs new file mode 100644 index 0000000000..5210bd9b95 --- /dev/null +++ b/test/integration/fixtures/parallel/test3.mjs @@ -0,0 +1,7 @@ +import {describe,it} from "../../../../index.js"; + +describe('test3', () => { + it('should fail', () => { + throw new Error('expecting this error to fail'); + }); +}); diff --git a/test/integration/parallel.spec.js b/test/integration/parallel.spec.js new file mode 100644 index 0000000000..5f6a1f7459 --- /dev/null +++ b/test/integration/parallel.spec.js @@ -0,0 +1,28 @@ +'use strict'; + +const assert = require('assert'); +const {runMochaJSONAsync} = require('./helpers'); +const semver = require('semver'); + +describe('parallel run', () => { + /** + * @see https://github.com/mochajs/mocha/issues/4559 + */ + it('should allow `import {it} from "mocha"` module syntax', async () => { + if (semver.major(process.version) <= 10) { + console.log( + `[SKIPPED] for node ${process.version} (es module syntax isn't supported on node <= 10)` + ); + } else { + const result = await runMochaJSONAsync('parallel/test3.mjs', [ + '--parallel', + '--jobs', + '2', + require.resolve('./fixtures/parallel/test1.mjs'), + require.resolve('./fixtures/parallel/test2.mjs') + ]); + assert.strictEqual(result.stats.failures, 1); + assert.strictEqual(result.stats.passes, 2); + } + }); +});