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.
		
		
		
		
		
			
		
			
				
					
					
						
							298 lines
						
					
					
						
							7.7 KiB
						
					
					
				
			
		
		
	
	
							298 lines
						
					
					
						
							7.7 KiB
						
					
					
				'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;
 | 
						|
 |