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.
		
		
		
		
		
			
		
			
				
					
					
						
							482 lines
						
					
					
						
							12 KiB
						
					
					
				
			
		
		
	
	
							482 lines
						
					
					
						
							12 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
Object.defineProperty(exports, '__esModule', { | 
						|
  value: true | 
						|
}); | 
						|
exports.default = runTest; | 
						|
 | 
						|
function _console() { | 
						|
  const data = require('@jest/console'); | 
						|
 | 
						|
  _console = function _console() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _gracefulFs() { | 
						|
  const data = _interopRequireDefault(require('graceful-fs')); | 
						|
 | 
						|
  _gracefulFs = function _gracefulFs() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _jestUtil() { | 
						|
  const data = require('jest-util'); | 
						|
 | 
						|
  _jestUtil = function _jestUtil() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _jestLeakDetector() { | 
						|
  const data = _interopRequireDefault(require('jest-leak-detector')); | 
						|
 | 
						|
  _jestLeakDetector = function _jestLeakDetector() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _jestConfig() { | 
						|
  const data = require('jest-config'); | 
						|
 | 
						|
  _jestConfig = function _jestConfig() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function docblock() { | 
						|
  const data = _interopRequireWildcard(require('jest-docblock')); | 
						|
 | 
						|
  docblock = function docblock() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _jestMessageUtil() { | 
						|
  const data = require('jest-message-util'); | 
						|
 | 
						|
  _jestMessageUtil = function _jestMessageUtil() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _sourceMapSupport() { | 
						|
  const data = _interopRequireDefault(require('source-map-support')); | 
						|
 | 
						|
  _sourceMapSupport = function _sourceMapSupport() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _chalk() { | 
						|
  const data = _interopRequireDefault(require('chalk')); | 
						|
 | 
						|
  _chalk = function _chalk() { | 
						|
    return data; | 
						|
  }; | 
						|
 | 
						|
  return data; | 
						|
} | 
						|
 | 
						|
function _interopRequireWildcard(obj) { | 
						|
  if (obj && obj.__esModule) { | 
						|
    return obj; | 
						|
  } else { | 
						|
    var newObj = {}; | 
						|
    if (obj != null) { | 
						|
      for (var key in obj) { | 
						|
        if (Object.prototype.hasOwnProperty.call(obj, key)) { | 
						|
          var desc = | 
						|
            Object.defineProperty && Object.getOwnPropertyDescriptor | 
						|
              ? Object.getOwnPropertyDescriptor(obj, key) | 
						|
              : {}; | 
						|
          if (desc.get || desc.set) { | 
						|
            Object.defineProperty(newObj, key, desc); | 
						|
          } else { | 
						|
            newObj[key] = obj[key]; | 
						|
          } | 
						|
        } | 
						|
      } | 
						|
    } | 
						|
    newObj.default = obj; | 
						|
    return newObj; | 
						|
  } | 
						|
} | 
						|
 | 
						|
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 _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; | 
						|
} | 
						|
 | 
						|
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 freezeConsole(testConsole, config) { | 
						|
  // @ts-ignore: `_log` is `private` - we should figure out some proper API here | 
						|
  testConsole._log = function fakeConsolePush(_type, message) { | 
						|
    const error = new (_jestUtil()).ErrorWithStack( | 
						|
      `${_chalk().default.red( | 
						|
        `${_chalk().default.bold( | 
						|
          'Cannot log after tests are done.' | 
						|
        )} Did you forget to wait for something async in your test?` | 
						|
      )}\nAttempted to log "${message}".`, | 
						|
      fakeConsolePush | 
						|
    ); | 
						|
    const formattedError = (0, _jestMessageUtil().formatExecError)( | 
						|
      error, | 
						|
      config, | 
						|
      { | 
						|
        noStackTrace: false | 
						|
      }, | 
						|
      undefined, | 
						|
      true | 
						|
    ); | 
						|
    process.stderr.write('\n' + formattedError + '\n'); // TODO: set exit code in Jest 25 | 
						|
    // process.exitCode = 1; | 
						|
  }; | 
						|
} // Keeping the core of "runTest" as a separate function (as "runTestInternal") | 
						|
// is key to be able to detect memory leaks. Since all variables are local to | 
						|
// the function, when "runTestInternal" finishes its execution, they can all be | 
						|
// freed, UNLESS something else is leaking them (and that's why we can detect | 
						|
// the leak!). | 
						|
// | 
						|
// If we had all the code in a single function, we should manually nullify all | 
						|
// references to verify if there is a leak, which is not maintainable and error | 
						|
// prone. That's why "runTestInternal" CANNOT be inlined inside "runTest". | 
						|
 | 
						|
function runTestInternal(_x, _x2, _x3, _x4, _x5) { | 
						|
  return _runTestInternal.apply(this, arguments); | 
						|
} | 
						|
 | 
						|
function _runTestInternal() { | 
						|
  _runTestInternal = _asyncToGenerator(function*( | 
						|
    path, | 
						|
    globalConfig, | 
						|
    config, | 
						|
    resolver, | 
						|
    context | 
						|
  ) { | 
						|
    const testSource = _gracefulFs().default.readFileSync(path, 'utf8'); | 
						|
 | 
						|
    const docblockPragmas = docblock().parse(docblock().extract(testSource)); | 
						|
    const customEnvironment = docblockPragmas['jest-environment']; | 
						|
    let testEnvironment = config.testEnvironment; | 
						|
 | 
						|
    if (customEnvironment) { | 
						|
      if (Array.isArray(customEnvironment)) { | 
						|
        throw new Error( | 
						|
          `You can only define a single test environment through docblocks, got "${customEnvironment.join( | 
						|
            ', ' | 
						|
          )}"` | 
						|
        ); | 
						|
      } | 
						|
 | 
						|
      testEnvironment = (0, _jestConfig().getTestEnvironment)( | 
						|
        _objectSpread({}, config, { | 
						|
          testEnvironment: customEnvironment | 
						|
        }) | 
						|
      ); | 
						|
    } | 
						|
 | 
						|
    const TestEnvironment = (0, _jestUtil().interopRequireDefault)( | 
						|
      require(testEnvironment) | 
						|
    ).default; | 
						|
    const testFramework = | 
						|
      process.env.JEST_CIRCUS === '1' | 
						|
        ? require('jest-circus/runner') // eslint-disable-line import/no-extraneous-dependencies | 
						|
        : require(config.testRunner); | 
						|
    const Runtime = config.moduleLoader | 
						|
      ? require(config.moduleLoader) | 
						|
      : require('jest-runtime'); | 
						|
    let runtime = undefined; | 
						|
    const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; | 
						|
 | 
						|
    const consoleFormatter = (type, message) => | 
						|
      (0, _console().getConsoleOutput)( | 
						|
        config.cwd, | 
						|
        !!globalConfig.verbose, // 4 = the console call is buried 4 stack frames deep | 
						|
        _console().BufferedConsole.write( | 
						|
          [], | 
						|
          type, | 
						|
          message, | 
						|
          4, | 
						|
          runtime && runtime.getSourceMaps() | 
						|
        ) | 
						|
      ); | 
						|
 | 
						|
    let testConsole; | 
						|
 | 
						|
    if (globalConfig.silent) { | 
						|
      testConsole = new (_console()).NullConsole( | 
						|
        consoleOut, | 
						|
        consoleOut, | 
						|
        consoleFormatter | 
						|
      ); | 
						|
    } else if (globalConfig.verbose) { | 
						|
      testConsole = new (_console()).CustomConsole( | 
						|
        consoleOut, | 
						|
        consoleOut, | 
						|
        consoleFormatter | 
						|
      ); | 
						|
    } else { | 
						|
      testConsole = new (_console()).BufferedConsole( | 
						|
        () => runtime && runtime.getSourceMaps() | 
						|
      ); | 
						|
    } | 
						|
 | 
						|
    const environment = new TestEnvironment(config, { | 
						|
      console: testConsole, | 
						|
      docblockPragmas, | 
						|
      testPath: path | 
						|
    }); | 
						|
    const leakDetector = config.detectLeaks | 
						|
      ? new (_jestLeakDetector()).default(environment) | 
						|
      : null; | 
						|
    const cacheFS = { | 
						|
      [path]: testSource | 
						|
    }; | 
						|
    (0, _jestUtil().setGlobal)(environment.global, 'console', testConsole); | 
						|
    runtime = new Runtime(config, environment, resolver, cacheFS, { | 
						|
      changedFiles: context && context.changedFiles, | 
						|
      collectCoverage: globalConfig.collectCoverage, | 
						|
      collectCoverageFrom: globalConfig.collectCoverageFrom, | 
						|
      collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom | 
						|
    }); | 
						|
    const start = Date.now(); | 
						|
    const sourcemapOptions = { | 
						|
      environment: 'node', | 
						|
      handleUncaughtExceptions: false, | 
						|
      retrieveSourceMap: source => { | 
						|
        const sourceMaps = runtime && runtime.getSourceMaps(); | 
						|
        const sourceMapSource = sourceMaps && sourceMaps[source]; | 
						|
 | 
						|
        if (sourceMapSource) { | 
						|
          try { | 
						|
            return { | 
						|
              map: JSON.parse( | 
						|
                _gracefulFs().default.readFileSync(sourceMapSource, 'utf8') | 
						|
              ), | 
						|
              url: source | 
						|
            }; | 
						|
          } catch (e) {} | 
						|
        } | 
						|
 | 
						|
        return null; | 
						|
      } | 
						|
    }; // For tests | 
						|
 | 
						|
    runtime | 
						|
      .requireInternalModule( | 
						|
        require.resolve('source-map-support'), | 
						|
        'source-map-support' | 
						|
      ) | 
						|
      .install(sourcemapOptions); // For runtime errors | 
						|
 | 
						|
    _sourceMapSupport().default.install(sourcemapOptions); | 
						|
 | 
						|
    if ( | 
						|
      environment.global && | 
						|
      environment.global.process && | 
						|
      environment.global.process.exit | 
						|
    ) { | 
						|
      const realExit = environment.global.process.exit; | 
						|
 | 
						|
      environment.global.process.exit = function exit(...args) { | 
						|
        const error = new (_jestUtil()).ErrorWithStack( | 
						|
          `process.exit called with "${args.join(', ')}"`, | 
						|
          exit | 
						|
        ); | 
						|
        const formattedError = (0, _jestMessageUtil().formatExecError)( | 
						|
          error, | 
						|
          config, | 
						|
          { | 
						|
            noStackTrace: false | 
						|
          }, | 
						|
          undefined, | 
						|
          true | 
						|
        ); | 
						|
        process.stderr.write(formattedError); | 
						|
        return realExit(...args); | 
						|
      }; | 
						|
    } | 
						|
 | 
						|
    try { | 
						|
      yield environment.setup(); | 
						|
      let result; | 
						|
 | 
						|
      try { | 
						|
        result = yield testFramework( | 
						|
          globalConfig, | 
						|
          config, | 
						|
          environment, | 
						|
          runtime, | 
						|
          path | 
						|
        ); | 
						|
      } catch (err) { | 
						|
        // Access stack before uninstalling sourcemaps | 
						|
        err.stack; | 
						|
        throw err; | 
						|
      } | 
						|
 | 
						|
      freezeConsole(testConsole, config); | 
						|
      const testCount = | 
						|
        result.numPassingTests + | 
						|
        result.numFailingTests + | 
						|
        result.numPendingTests + | 
						|
        result.numTodoTests; | 
						|
      result.perfStats = { | 
						|
        end: Date.now(), | 
						|
        start | 
						|
      }; | 
						|
      result.testFilePath = path; | 
						|
      result.console = testConsole.getBuffer(); | 
						|
      result.skipped = testCount === result.numPendingTests; | 
						|
      result.displayName = config.displayName; | 
						|
      const coverage = runtime.getAllCoverageInfoCopy(); | 
						|
 | 
						|
      if (coverage) { | 
						|
        const coverageKeys = Object.keys(coverage); | 
						|
 | 
						|
        if (coverageKeys.length) { | 
						|
          result.coverage = coverage; | 
						|
          result.sourceMaps = runtime.getSourceMapInfo(new Set(coverageKeys)); | 
						|
        } | 
						|
      } | 
						|
 | 
						|
      if (globalConfig.logHeapUsage) { | 
						|
        if (global.gc) { | 
						|
          global.gc(); | 
						|
        } | 
						|
 | 
						|
        result.memoryUsage = process.memoryUsage().heapUsed; | 
						|
      } // Delay the resolution to allow log messages to be output. | 
						|
 | 
						|
      return new Promise(resolve => { | 
						|
        setImmediate(() => | 
						|
          resolve({ | 
						|
            leakDetector, | 
						|
            result | 
						|
          }) | 
						|
        ); | 
						|
      }); | 
						|
    } finally { | 
						|
      yield environment.teardown(); | 
						|
 | 
						|
      _sourceMapSupport().default.resetRetrieveHandlers(); | 
						|
    } | 
						|
  }); | 
						|
  return _runTestInternal.apply(this, arguments); | 
						|
} | 
						|
 | 
						|
function runTest(_x6, _x7, _x8, _x9, _x10) { | 
						|
  return _runTest.apply(this, arguments); | 
						|
} | 
						|
 | 
						|
function _runTest() { | 
						|
  _runTest = _asyncToGenerator(function*( | 
						|
    path, | 
						|
    globalConfig, | 
						|
    config, | 
						|
    resolver, | 
						|
    context | 
						|
  ) { | 
						|
    const _ref = yield runTestInternal( | 
						|
        path, | 
						|
        globalConfig, | 
						|
        config, | 
						|
        resolver, | 
						|
        context | 
						|
      ), | 
						|
      leakDetector = _ref.leakDetector, | 
						|
      result = _ref.result; | 
						|
 | 
						|
    if (leakDetector) { | 
						|
      // We wanna allow a tiny but time to pass to allow last-minute cleanup | 
						|
      yield new Promise(resolve => setTimeout(resolve, 100)); // Resolve leak detector, outside the "runTestInternal" closure. | 
						|
 | 
						|
      result.leaks = leakDetector.isLeaking(); | 
						|
    } else { | 
						|
      result.leaks = false; | 
						|
    } | 
						|
 | 
						|
    return result; | 
						|
  }); | 
						|
  return _runTest.apply(this, arguments); | 
						|
}
 | 
						|
 |