You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					299 lines
				
				7.7 KiB
			
		
		
			
		
	
	
					299 lines
				
				7.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _exit() {
							 | 
						||
| 
								 | 
							
								  const data = _interopRequireDefault(require('exit'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _exit = function _exit() {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _throat() {
							 | 
						||
| 
								 | 
							
								  const data = _interopRequireDefault(require('throat'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _throat = function _throat() {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _jestWorker() {
							 | 
						||
| 
								 | 
							
								  const data = _interopRequireDefault(require('jest-worker'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _jestWorker = function _jestWorker() {
							 | 
						||
| 
								 | 
							
								    return data;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return data;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _runTest = _interopRequireDefault(require('./runTest'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _testWorker = require('./testWorker');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireDefault(obj) {
							 | 
						||
| 
								 | 
							
								  return obj && obj.__esModule ? obj : {default: obj};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _objectSpread(target) {
							 | 
						||
| 
								 | 
							
								  for (var i = 1; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								    var source = arguments[i] != null ? arguments[i] : {};
							 | 
						||
| 
								 | 
							
								    var ownKeys = Object.keys(source);
							 | 
						||
| 
								 | 
							
								    if (typeof Object.getOwnPropertySymbols === 'function') {
							 | 
						||
| 
								 | 
							
								      ownKeys = ownKeys.concat(
							 | 
						||
| 
								 | 
							
								        Object.getOwnPropertySymbols(source).filter(function(sym) {
							 | 
						||
| 
								 | 
							
								          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ownKeys.forEach(function(key) {
							 | 
						||
| 
								 | 
							
								      _defineProperty(target, key, source[key]);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return target;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    var info = gen[key](arg);
							 | 
						||
| 
								 | 
							
								    var value = info.value;
							 | 
						||
| 
								 | 
							
								  } catch (error) {
							 | 
						||
| 
								 | 
							
								    reject(error);
							 | 
						||
| 
								 | 
							
								    return;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (info.done) {
							 | 
						||
| 
								 | 
							
								    resolve(value);
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    Promise.resolve(value).then(_next, _throw);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _asyncToGenerator(fn) {
							 | 
						||
| 
								 | 
							
								  return function() {
							 | 
						||
| 
								 | 
							
								    var self = this,
							 | 
						||
| 
								 | 
							
								      args = arguments;
							 | 
						||
| 
								 | 
							
								    return new Promise(function(resolve, reject) {
							 | 
						||
| 
								 | 
							
								      var gen = fn.apply(self, args);
							 | 
						||
| 
								 | 
							
								      function _next(value) {
							 | 
						||
| 
								 | 
							
								        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      function _throw(err) {
							 | 
						||
| 
								 | 
							
								        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      _next(undefined);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _defineProperty(obj, key, value) {
							 | 
						||
| 
								 | 
							
								  if (key in obj) {
							 | 
						||
| 
								 | 
							
								    Object.defineProperty(obj, key, {
							 | 
						||
| 
								 | 
							
								      value: value,
							 | 
						||
| 
								 | 
							
								      enumerable: true,
							 | 
						||
| 
								 | 
							
								      configurable: true,
							 | 
						||
| 
								 | 
							
								      writable: true
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    obj[key] = value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const TEST_WORKER_PATH = require.resolve('./testWorker');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* eslint-disable-next-line no-redeclare */
							 | 
						||
| 
								 | 
							
								class TestRunner {
							 | 
						||
| 
								 | 
							
								  constructor(globalConfig, context) {
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_globalConfig', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    _defineProperty(this, '_context', void 0);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this._globalConfig = globalConfig;
							 | 
						||
| 
								 | 
							
								    this._context = context || {};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  runTests(tests, watcher, onStart, onResult, onFailure, options) {
							 | 
						||
| 
								 | 
							
								    var _this = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return _asyncToGenerator(function*() {
							 | 
						||
| 
								 | 
							
								      return yield options.serial
							 | 
						||
| 
								 | 
							
								        ? _this._createInBandTestRun(
							 | 
						||
| 
								 | 
							
								            tests,
							 | 
						||
| 
								 | 
							
								            watcher,
							 | 
						||
| 
								 | 
							
								            onStart,
							 | 
						||
| 
								 | 
							
								            onResult,
							 | 
						||
| 
								 | 
							
								            onFailure
							 | 
						||
| 
								 | 
							
								          )
							 | 
						||
| 
								 | 
							
								        : _this._createParallelTestRun(
							 | 
						||
| 
								 | 
							
								            tests,
							 | 
						||
| 
								 | 
							
								            watcher,
							 | 
						||
| 
								 | 
							
								            onStart,
							 | 
						||
| 
								 | 
							
								            onResult,
							 | 
						||
| 
								 | 
							
								            onFailure
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								    })();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _createInBandTestRun(tests, watcher, onStart, onResult, onFailure) {
							 | 
						||
| 
								 | 
							
								    var _this2 = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return _asyncToGenerator(function*() {
							 | 
						||
| 
								 | 
							
								      process.env.JEST_WORKER_ID = '1';
							 | 
						||
| 
								 | 
							
								      const mutex = (0, _throat().default)(1);
							 | 
						||
| 
								 | 
							
								      return tests.reduce(
							 | 
						||
| 
								 | 
							
								        (promise, test) =>
							 | 
						||
| 
								 | 
							
								          mutex(() =>
							 | 
						||
| 
								 | 
							
								            promise
							 | 
						||
| 
								 | 
							
								              .then(
							 | 
						||
| 
								 | 
							
								                /*#__PURE__*/
							 | 
						||
| 
								 | 
							
								                _asyncToGenerator(function*() {
							 | 
						||
| 
								 | 
							
								                  if (watcher.isInterrupted()) {
							 | 
						||
| 
								 | 
							
								                    throw new CancelRun();
							 | 
						||
| 
								 | 
							
								                  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                  yield onStart(test);
							 | 
						||
| 
								 | 
							
								                  return (0,
							 | 
						||
| 
								 | 
							
								                  _runTest.default)(test.path, _this2._globalConfig, test.context.config, test.context.resolver, _this2._context);
							 | 
						||
| 
								 | 
							
								                })
							 | 
						||
| 
								 | 
							
								              )
							 | 
						||
| 
								 | 
							
								              .then(result => onResult(test, result))
							 | 
						||
| 
								 | 
							
								              .catch(err => onFailure(test, err))
							 | 
						||
| 
								 | 
							
								          ),
							 | 
						||
| 
								 | 
							
								        Promise.resolve()
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    })();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  _createParallelTestRun(tests, watcher, onStart, onResult, onFailure) {
							 | 
						||
| 
								 | 
							
								    var _this3 = this;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return _asyncToGenerator(function*() {
							 | 
						||
| 
								 | 
							
								      const resolvers = new Map();
							 | 
						||
| 
								 | 
							
								      var _iteratorNormalCompletion = true;
							 | 
						||
| 
								 | 
							
								      var _didIteratorError = false;
							 | 
						||
| 
								 | 
							
								      var _iteratorError = undefined;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        for (
							 | 
						||
| 
								 | 
							
								          var _iterator = tests[Symbol.iterator](), _step;
							 | 
						||
| 
								 | 
							
								          !(_iteratorNormalCompletion = (_step = _iterator.next()).done);
							 | 
						||
| 
								 | 
							
								          _iteratorNormalCompletion = true
							 | 
						||
| 
								 | 
							
								        ) {
							 | 
						||
| 
								 | 
							
								          const test = _step.value;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (!resolvers.has(test.context.config.name)) {
							 | 
						||
| 
								 | 
							
								            resolvers.set(test.context.config.name, {
							 | 
						||
| 
								 | 
							
								              config: test.context.config,
							 | 
						||
| 
								 | 
							
								              serializableModuleMap: test.context.moduleMap.toJSON()
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } catch (err) {
							 | 
						||
| 
								 | 
							
								        _didIteratorError = true;
							 | 
						||
| 
								 | 
							
								        _iteratorError = err;
							 | 
						||
| 
								 | 
							
								      } finally {
							 | 
						||
| 
								 | 
							
								        try {
							 | 
						||
| 
								 | 
							
								          if (!_iteratorNormalCompletion && _iterator.return != null) {
							 | 
						||
| 
								 | 
							
								            _iterator.return();
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        } finally {
							 | 
						||
| 
								 | 
							
								          if (_didIteratorError) {
							 | 
						||
| 
								 | 
							
								            throw _iteratorError;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const worker = new (_jestWorker()).default(TEST_WORKER_PATH, {
							 | 
						||
| 
								 | 
							
								        exposedMethods: ['worker'],
							 | 
						||
| 
								 | 
							
								        forkOptions: {
							 | 
						||
| 
								 | 
							
								          stdio: 'pipe'
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        maxRetries: 3,
							 | 
						||
| 
								 | 
							
								        numWorkers: _this3._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)(_this3._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(
							 | 
						||
| 
								 | 
							
								          /*#__PURE__*/
							 | 
						||
| 
								 | 
							
								          _asyncToGenerator(function*() {
							 | 
						||
| 
								 | 
							
								            if (watcher.isInterrupted()) {
							 | 
						||
| 
								 | 
							
								              return Promise.reject();
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            yield onStart(test);
							 | 
						||
| 
								 | 
							
								            return worker.worker({
							 | 
						||
| 
								 | 
							
								              config: test.context.config,
							 | 
						||
| 
								 | 
							
								              context: _objectSpread({}, _this3._context, {
							 | 
						||
| 
								 | 
							
								                changedFiles:
							 | 
						||
| 
								 | 
							
								                  _this3._context.changedFiles &&
							 | 
						||
| 
								 | 
							
								                  Array.from(_this3._context.changedFiles)
							 | 
						||
| 
								 | 
							
								              }),
							 | 
						||
| 
								 | 
							
								              globalConfig: _this3._globalConfig,
							 | 
						||
| 
								 | 
							
								              path: test.path
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								          })
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const onError =
							 | 
						||
| 
								 | 
							
								        /*#__PURE__*/
							 | 
						||
| 
								 | 
							
								        (function() {
							 | 
						||
| 
								 | 
							
								          var _ref3 = _asyncToGenerator(function*(err, test) {
							 | 
						||
| 
								 | 
							
								            yield onFailure(test, err);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (err.type === 'ProcessTerminatedError') {
							 | 
						||
| 
								 | 
							
								              console.error(
							 | 
						||
| 
								 | 
							
								                'A worker process has quit unexpectedly! ' +
							 | 
						||
| 
								 | 
							
								                  'Most likely this is an initialization error.'
							 | 
						||
| 
								 | 
							
								              );
							 | 
						||
| 
								 | 
							
								              (0, _exit().default)(1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          return function onError(_x, _x2) {
							 | 
						||
| 
								 | 
							
								            return _ref3.apply(this, arguments);
							 | 
						||
| 
								 | 
							
								          };
							 | 
						||
| 
								 | 
							
								        })();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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(testResult => onResult(test, testResult))
							 | 
						||
| 
								 | 
							
								            .catch(error => onError(error, test))
							 | 
						||
| 
								 | 
							
								        )
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const cleanup = () => worker.end();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      return Promise.race([runAllTests, onInterrupt]).then(cleanup, cleanup);
							 | 
						||
| 
								 | 
							
								    })();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class CancelRun extends Error {
							 | 
						||
| 
								 | 
							
								  constructor(message) {
							 | 
						||
| 
								 | 
							
								    super(message);
							 | 
						||
| 
								 | 
							
								    this.name = 'CancelRun';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = TestRunner;
							 |