Skip to content

Commit

Permalink
added more tests, implementation. needs #4366 for browser compat
Browse files Browse the repository at this point in the history
- removed dead code in `lib/cli/run-helpers.js`
- be sure not to send certain options to the worker processes
- fix root hook bug in worker
- send global fixtures to `Runner` constructor
- removed debugs
- **add `Process.unhandledRejection` listeners** which might be bad
- fix some tests while I'm fixing tests
  • Loading branch information
boneskull committed Jul 16, 2020
1 parent 4ba5c08 commit 458ac02
Show file tree
Hide file tree
Showing 16 changed files with 272 additions and 103 deletions.
26 changes: 0 additions & 26 deletions lib/cli/run-helpers.js
Expand Up @@ -12,7 +12,6 @@ const path = require('path');
const debug = require('debug')('mocha:cli:run:helpers');
const {watchRun, watchParallelRun} = require('./watch-run');
const collectFiles = require('./collect-files');
const {type} = require('../utils');
const {format} = require('util');
const {createInvalidPluginError} = require('../errors');
const {requireOrImport} = require('../esm-utils');
Expand Down Expand Up @@ -101,31 +100,6 @@ exports.handleRequires = async (requires = []) => {
return pluginLoader.finalize();
};

/**
* Loads root hooks as exported via `mochaHooks` from required files.
* These can be sync/async functions returning objects, or just objects.
* Flattens to a single object.
* @param {Array<MochaRootHookObject|MochaRootHookFunction>} rootHooks - Array of root hooks
* @private
* @returns {MochaRootHookObject}
*/
exports.loadRootHooks = async rootHooks => {
const rootHookObjects = await Promise.all(
rootHooks.map(async hook => (/function$/.test(type(hook)) ? hook() : hook))
);

return rootHookObjects.reduce(
(acc, hook) => {
acc.beforeAll = acc.beforeAll.concat(hook.beforeAll || []);
acc.beforeEach = acc.beforeEach.concat(hook.beforeEach || []);
acc.afterAll = acc.afterAll.concat(hook.afterAll || []);
acc.afterEach = acc.afterEach.concat(hook.afterEach || []);
return acc;
},
{beforeAll: [], beforeEach: [], afterAll: [], afterEach: []}
);
};

/**
* Collect and load test files, then run mocha instance.
* @param {Mocha} mocha - Mocha instance
Expand Down
19 changes: 13 additions & 6 deletions lib/mocha.js
Expand Up @@ -969,7 +969,9 @@ Mocha.prototype.run = function(fn) {
options.files = this.files;
var runner = new this._runnerClass(suite, {
delay: options.delay,
cleanReferencesAfterRun: this._cleanReferencesAfterRun
cleanReferencesAfterRun: this._cleanReferencesAfterRun,
globalSetup: options.globalSetup,
globalTeardown: options.globalTeardown
});
createStatsCollector(runner);
var reporter = new this._reporter(runner, options);
Expand Down Expand Up @@ -1097,7 +1099,7 @@ Mocha.prototype.lazyLoadFiles = function lazyLoadFiles(enable) {
return this;
};

Mocha.prototype.globalSetup = function globalSetup(setupFns = []) {
Mocha.prototype.globalSetup = function globalSetup(setupFns) {
if (setupFns) {
setupFns = utils.castArray(setupFns);
this.options.globalSetup = setupFns;
Expand All @@ -1106,7 +1108,7 @@ Mocha.prototype.globalSetup = function globalSetup(setupFns = []) {
return this;
};

Mocha.prototype.globalTeardown = function globalTeardown(teardownFns = []) {
Mocha.prototype.globalTeardown = function globalTeardown(teardownFns) {
if (teardownFns) {
teardownFns = utils.castArray(teardownFns);
this.options.globalTeardown = teardownFns;
Expand All @@ -1117,7 +1119,6 @@ Mocha.prototype.globalTeardown = function globalTeardown(teardownFns = []) {

/**
* An alternative way to define root hooks that works with parallel runs.
* @private
* @typedef {Object} MochaRootHookObject
* @property {Function|Function[]} [beforeAll] - "Before all" hook(s)
* @property {Function|Function[]} [beforeEach] - "Before each" hook(s)
Expand All @@ -1127,7 +1128,13 @@ Mocha.prototype.globalTeardown = function globalTeardown(teardownFns = []) {

/**
* An function that returns a {@link MochaRootHookObject}, either sync or async.
* @private
* @callback MochaRootHookFunction
@callback MochaRootHookFunction
* @returns {MochaRootHookObject|Promise<MochaRootHookObject>}
*/

/**
* A function that's invoked _once_ which is either sync or async.
* Can be a "teardown" or "setup". These will all share the same context.
* @callback MochaGlobalFixture
* @returns {*|Promise<*>}
*/
17 changes: 17 additions & 0 deletions lib/nodejs/parallel-buffered-runner.js
Expand Up @@ -14,6 +14,18 @@ const {BufferedWorkerPool} = require('./buffered-worker-pool');
const {setInterval, clearInterval} = global;
const {createMap} = require('../utils');

/**
* List of options to _not_ serialize for transmission to workers
*/
const DENY_OPTIONS = [
'globalSetup',
'globalTeardown',
'parallel',
'p',
'jobs',
'j'
];

/**
* Outputs a debug statement with worker stats
* @param {BufferedWorkerPool} pool - Worker pool
Expand Down Expand Up @@ -237,6 +249,11 @@ class ParallelBufferedRunner extends Runner {

await this.runGlobalSetup();

options = {...options};
DENY_OPTIONS.forEach(opt => {
delete options[opt];
});

const results = await allSettled(
files.map(this._createFileRunner(pool, options))
);
Expand Down
2 changes: 1 addition & 1 deletion lib/nodejs/worker.js
Expand Up @@ -45,7 +45,7 @@ let bootstrap = async argv => {
validateLegacyPlugin(argv, 'ui', Mocha.interfaces);

// globalSetup and globalTeardown do not run in workers
argv.rootHooks = plugins.rootHooks;
rootHooks = plugins.rootHooks;
bootstrap = () => {};
debug('bootstrap(): finished with args: %O', argv);
};
Expand Down
1 change: 0 additions & 1 deletion lib/plugin.js
Expand Up @@ -120,7 +120,6 @@ const aggregateRootHooks = (exports.aggregateRootHooks = async (
rootHooks.map(async hook => (typeof hook === 'function' ? hook() : hook))
);

console.dir(rootHookObjects);
return rootHookObjects.reduce(
(acc, hook) => {
hook = {
Expand Down
62 changes: 41 additions & 21 deletions lib/runner.js
Expand Up @@ -184,6 +184,13 @@ function Runner(suite, opts) {
this.globals(this.globalProps());

this.uncaught = this._uncaught.bind(this);

/**
* An object used as the context shared between global fixtures
* @private
* @memberof Runner
*/
this._globalContext = {};
}

/**
Expand Down Expand Up @@ -985,38 +992,49 @@ Runner.prototype._uncaught = function(err) {
Runner.prototype.runGlobalSetup = async function runGlobalSetup() {
this.emit(constants.EVENT_PRE_GLOBAL_SETUP);
const {globalSetup} = this._opts;
if (globalSetup) {
if (globalSetup && globalSetup.length) {
debug('run(): global setup starting');
await this.runGlobalFixtures(globalSetup, {
begin: constants.EVENT_GLOBAL_SETUP_BEGIN,
end: constants.EVENT_GLOBAL_SETUP_END
});
await this.runGlobalFixtures(
{
begin: constants.EVENT_GLOBAL_SETUP_BEGIN,
end: constants.EVENT_GLOBAL_SETUP_END
},
globalSetup
);
debug('run(): global setup complete');
}
debug('run(): global setup complete');
this.emit(constants.EVENT_POST_GLOBAL_SETUP);
};

Runner.prototype.runGlobalTeardown = async function runGlobalTeardown() {
this.emit(constants.EVENT_PRE_GLOBAL_TEARDOWN);
const {globalTeardown} = this._opts;
if (globalTeardown) {
if (globalTeardown && globalTeardown.length) {
debug('run(): global teardown starting');
await this.runGlobalFixtures(globalTeardown, {
begin: constants.EVENT_GLOBAL_TEARDOWN_BEGIN,
end: constants.EVENT_GLOBAL_TEARDOWN_END
});
await this.runGlobalFixtures(
{
begin: constants.EVENT_GLOBAL_TEARDOWN_BEGIN,
end: constants.EVENT_GLOBAL_TEARDOWN_END
},
globalTeardown
);
}
debug('run(): global teardown complete');
this.emit(constants.EVENT_POST_GLOBAL_TEARDOWN);
};

Runner.prototype.runGlobalFixtures = function runGlobalFixtures(
fixtureFns,
events
/**
* Run global fixtures sequentially in context {@link Runner#_globalContext}
* @private
* @param {{begin: string, end: string}} events - `begin` and `end` event names to emit
* @param {MochaGlobalFixture[]} [fixtureFns]- Fixtures to run
*/
Runner.prototype.runGlobalFixtures = async function runGlobalFixtures(
events,
fixtureFns = []
) {
const context = (this._globalContext = this._globalContext || {});
return fixtureFns.reduce(async (promise, fixtureFn) => {
await promise;
const context = this._globalContext;
for await (const fixtureFn of fixtureFns) {
this.emit(events.begin, {
value: fixtureFn,
context: context
Expand All @@ -1027,7 +1045,7 @@ Runner.prototype.runGlobalFixtures = function runGlobalFixtures(
context: context,
fulfilled: retVal
});
}, Promise.resolve());
}
};

/**
Expand All @@ -1053,11 +1071,13 @@ Runner.prototype.run = function(fn, opts = {}) {
debug('run(): emitted %s', constants.EVENT_RUN_END);
};

const begin = () => {
const begin = async () => {
debug('run(): emitting %s', constants.EVENT_RUN_BEGIN);
this.emit(constants.EVENT_RUN_BEGIN);
debug('run(): emitted %s', constants.EVENT_RUN_BEGIN);

await this.runGlobalSetup();

this.runSuite(rootSuite, async () => {
await this.runGlobalTeardown();
end();
Expand All @@ -1077,8 +1097,6 @@ Runner.prototype.run = function(fn, opts = {}) {
debug('run(): "delay" ended');
}

await this.runGlobalSetup();

return begin();
};

Expand All @@ -1098,7 +1116,9 @@ Runner.prototype.run = function(fn, opts = {}) {
});

this._removeEventListener(process, 'uncaughtException', this.uncaught);
this._removeEventListener(process, 'unhandledRejection', this.uncaught);
this._addEventListener(process, 'uncaughtException', this.uncaught);
this._addEventListener(process, 'unhandledRejection', this.uncaught);

if (this._delay) {
// for reporters, I guess.
Expand Down
12 changes: 11 additions & 1 deletion test/integration/fixtures/runner/events-bail-retries.fixture.js
Expand Up @@ -12,9 +12,17 @@ var EVENT_TEST_BEGIN = constants.EVENT_TEST_BEGIN;
var EVENT_TEST_END = constants.EVENT_TEST_END;
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
var EVENT_TEST_RETRY = constants.EVENT_TEST_RETRY;
const {
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN
} = constants;

var emitOrder = [
EVENT_RUN_BEGIN,
EVENT_RUN_BEGIN,
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_SUITE_BEGIN,
EVENT_SUITE_BEGIN,
EVENT_HOOK_BEGIN,
Expand All @@ -36,6 +44,8 @@ var emitOrder = [
EVENT_HOOK_END,
EVENT_SUITE_END,
EVENT_SUITE_END,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN,
EVENT_RUN_END
];

Expand Down
10 changes: 10 additions & 0 deletions test/integration/fixtures/runner/events-bail.fixture.js
Expand Up @@ -11,9 +11,17 @@ var EVENT_SUITE_END = constants.EVENT_SUITE_END;
var EVENT_TEST_BEGIN = constants.EVENT_TEST_BEGIN;
var EVENT_TEST_END = constants.EVENT_TEST_END;
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
const {
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN
} = constants;

var emitOrder = [
EVENT_RUN_BEGIN,
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_SUITE_BEGIN,
EVENT_SUITE_BEGIN,
EVENT_HOOK_BEGIN,
Expand All @@ -29,6 +37,8 @@ var emitOrder = [
EVENT_HOOK_END,
EVENT_SUITE_END,
EVENT_SUITE_END,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN,
EVENT_RUN_END
];

Expand Down
5 changes: 5 additions & 0 deletions test/integration/fixtures/runner/events-basic.fixture.js
Expand Up @@ -16,9 +16,12 @@ var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
var EVENT_TEST_RETRY = constants.EVENT_TEST_RETRY;
const {EVENT_PRE_GLOBAL_SETUP, EVENT_POST_GLOBAL_SETUP, EVENT_PRE_GLOBAL_TEARDOWN, EVENT_POST_GLOBAL_TEARDOWN} = constants;

var emitOrder = [
EVENT_RUN_BEGIN,
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_SUITE_BEGIN,
EVENT_SUITE_BEGIN,
EVENT_HOOK_BEGIN,
Expand All @@ -43,6 +46,8 @@ var emitOrder = [
EVENT_HOOK_END,
EVENT_SUITE_END,
EVENT_SUITE_END,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN,
EVENT_RUN_END
];

Expand Down
6 changes: 6 additions & 0 deletions test/integration/fixtures/runner/events-delay.fixture.js
Expand Up @@ -17,10 +17,14 @@ var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
var EVENT_TEST_PENDING = constants.EVENT_TEST_PENDING;
var EVENT_TEST_RETRY = constants.EVENT_TEST_RETRY;

const {EVENT_PRE_GLOBAL_SETUP, EVENT_POST_GLOBAL_SETUP, EVENT_PRE_GLOBAL_TEARDOWN, EVENT_POST_GLOBAL_TEARDOWN} = constants;

var emitOrder = [
EVENT_DELAY_BEGIN,
EVENT_DELAY_END,
EVENT_RUN_BEGIN,
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_SUITE_BEGIN,
EVENT_SUITE_BEGIN,
EVENT_HOOK_BEGIN,
Expand All @@ -45,6 +49,8 @@ var emitOrder = [
EVENT_HOOK_END,
EVENT_SUITE_END,
EVENT_SUITE_END,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN,
EVENT_RUN_END
];

Expand Down
10 changes: 10 additions & 0 deletions test/integration/fixtures/runner/events-retries.fixture.js
Expand Up @@ -12,9 +12,17 @@ var EVENT_TEST_BEGIN = constants.EVENT_TEST_BEGIN;
var EVENT_TEST_END = constants.EVENT_TEST_END;
var EVENT_TEST_FAIL = constants.EVENT_TEST_FAIL;
var EVENT_TEST_RETRY = constants.EVENT_TEST_RETRY;
const {
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN
} = constants;

var emitOrder = [
EVENT_RUN_BEGIN,
EVENT_PRE_GLOBAL_SETUP,
EVENT_POST_GLOBAL_SETUP,
EVENT_SUITE_BEGIN,
EVENT_SUITE_BEGIN,
EVENT_HOOK_BEGIN,
Expand All @@ -36,6 +44,8 @@ var emitOrder = [
EVENT_HOOK_END,
EVENT_SUITE_END,
EVENT_SUITE_END,
EVENT_PRE_GLOBAL_TEARDOWN,
EVENT_POST_GLOBAL_TEARDOWN,
EVENT_RUN_END
];

Expand Down

0 comments on commit 458ac02

Please sign in to comment.