'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); Object.defineProperty(exports, 'CallbackTestRunner', { enumerable: true, get: function () { return _types.CallbackTestRunner; } }); Object.defineProperty(exports, 'EmittingTestRunner', { enumerable: true, get: function () { return _types.EmittingTestRunner; } }); exports.default = void 0; function _chalk() { const data = _interopRequireDefault(require('chalk')); _chalk = function () { return data; }; return data; } function _emittery() { const data = _interopRequireDefault(require('emittery')); _emittery = function () { return data; }; return data; } function _throat() { const data = _interopRequireDefault(require('throat')); _throat = function () { return data; }; return data; } function _jestUtil() { const data = require('jest-util'); _jestUtil = function () { return data; }; return data; } function _jestWorker() { const data = require('jest-worker'); _jestWorker = function () { return data; }; return data; } var _runTest = _interopRequireDefault(require('./runTest')); var _types = require('./types'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : {default: obj}; } function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); } function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); } function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError( 'Cannot initialize the same private elements twice on an object' ); } } function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, 'get'); return _classApplyDescriptorGet(receiver, descriptor); } function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError( 'attempted to ' + action + ' private field on non-instance' ); } return privateMap.get(receiver); } function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; } function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError('attempted to get private field on non-instance'); } return fn; } var _eventEmitter = /*#__PURE__*/ new WeakMap(); var _createInBandTestRun = /*#__PURE__*/ new WeakSet(); var _createParallelTestRun = /*#__PURE__*/ new WeakSet(); class TestRunner extends _types.EmittingTestRunner { constructor(..._args) { super(..._args); _classPrivateMethodInitSpec(this, _createParallelTestRun); _classPrivateMethodInitSpec(this, _createInBandTestRun); _classPrivateFieldInitSpec(this, _eventEmitter, { writable: true, value: new (_emittery().default)() }); } async runTests(tests, watcher, options) { return await (options.serial ? _classPrivateMethodGet( this, _createInBandTestRun, _createInBandTestRun2 ).call(this, tests, watcher) : _classPrivateMethodGet( this, _createParallelTestRun, _createParallelTestRun2 ).call(this, tests, watcher)); } on(eventName, listener) { return _classPrivateFieldGet(this, _eventEmitter).on(eventName, listener); } } exports.default = TestRunner; async function _createInBandTestRun2(tests, watcher) { process.env.JEST_WORKER_ID = '1'; const mutex = (0, _throat().default)(1); return tests.reduce( (promise, test) => mutex(() => promise .then(async () => { if (watcher.isInterrupted()) { throw new CancelRun(); } // `deepCyclicCopy` used here to avoid mem-leak const sendMessageToJest = (eventName, args) => _classPrivateFieldGet(this, _eventEmitter).emit( eventName, (0, _jestUtil().deepCyclicCopy)(args, { keepPrototype: false }) ); await _classPrivateFieldGet(this, _eventEmitter).emit( 'test-file-start', [test] ); return (0, _runTest.default)( test.path, this._globalConfig, test.context.config, test.context.resolver, this._context, sendMessageToJest ); }) .then( result => _classPrivateFieldGet(this, _eventEmitter).emit( 'test-file-success', [test, result] ), error => _classPrivateFieldGet(this, _eventEmitter).emit( 'test-file-failure', [test, error] ) ) ), Promise.resolve() ); } async function _createParallelTestRun2(tests, watcher) { const resolvers = new Map(); for (const test of tests) { if (!resolvers.has(test.context.config.id)) { resolvers.set(test.context.config.id, { config: test.context.config, serializableModuleMap: test.context.moduleMap.toJSON() }); } } const worker = new (_jestWorker().Worker)(require.resolve('./testWorker'), { exposedMethods: ['worker'], // @ts-expect-error: option does not exist on the node 12 types forkOptions: { serialization: 'json', stdio: 'pipe' }, maxRetries: 3, numWorkers: this._globalConfig.maxWorkers, setupArgs: [ { serializableResolvers: Array.from(resolvers.values()) } ] }); if (worker.getStdout()) worker.getStdout().pipe(process.stdout); if (worker.getStderr()) worker.getStderr().pipe(process.stderr); const mutex = (0, _throat().default)(this._globalConfig.maxWorkers); // Send test suites to workers continuously instead of all at once to track // the start time of individual tests. const runTestInWorker = test => mutex(async () => { if (watcher.isInterrupted()) { return Promise.reject(); } await _classPrivateFieldGet(this, _eventEmitter).emit('test-file-start', [ test ]); const promise = worker.worker({ config: test.context.config, context: { ...this._context, changedFiles: this._context.changedFiles && Array.from(this._context.changedFiles), sourcesRelatedToTestsInChangedFiles: this._context.sourcesRelatedToTestsInChangedFiles && Array.from(this._context.sourcesRelatedToTestsInChangedFiles) }, globalConfig: this._globalConfig, path: test.path }); if (promise.UNSTABLE_onCustomMessage) { // TODO: Get appropriate type for `onCustomMessage` promise.UNSTABLE_onCustomMessage(([event, payload]) => _classPrivateFieldGet(this, _eventEmitter).emit(event, payload) ); } return promise; }); const onInterrupt = new Promise((_, reject) => { watcher.on('change', state => { if (state.interrupted) { reject(new CancelRun()); } }); }); const runAllTests = Promise.all( tests.map(test => runTestInWorker(test).then( result => _classPrivateFieldGet(this, _eventEmitter).emit('test-file-success', [ test, result ]), error => _classPrivateFieldGet(this, _eventEmitter).emit('test-file-failure', [ test, error ]) ) ) ); const cleanup = async () => { const {forceExited} = await worker.end(); if (forceExited) { console.error( _chalk().default.yellow( 'A worker process has failed to exit gracefully and has been force exited. ' + 'This is likely caused by tests leaking due to improper teardown. ' + 'Try running with --detectOpenHandles to find leaks. ' + 'Active timers can also cause this, ensure that .unref() was called on them.' ) ); } }; return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup); } class CancelRun extends Error { constructor(message) { super(message); this.name = 'CancelRun'; } }