123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', {
- value: true
- });
- exports.createTestScheduler = createTestScheduler;
- function _chalk() {
- const data = _interopRequireDefault(require('chalk'));
- _chalk = function () {
- return data;
- };
- return data;
- }
- function _exit() {
- const data = _interopRequireDefault(require('exit'));
- _exit = function () {
- return data;
- };
- return data;
- }
- function _reporters() {
- const data = require('@jest/reporters');
- _reporters = function () {
- return data;
- };
- return data;
- }
- function _testResult() {
- const data = require('@jest/test-result');
- _testResult = function () {
- return data;
- };
- return data;
- }
- function _transform() {
- const data = require('@jest/transform');
- _transform = function () {
- return data;
- };
- return data;
- }
- function _jestMessageUtil() {
- const data = require('jest-message-util');
- _jestMessageUtil = function () {
- return data;
- };
- return data;
- }
- function _jestSnapshot() {
- const data = _interopRequireDefault(require('jest-snapshot'));
- _jestSnapshot = function () {
- return data;
- };
- return data;
- }
- function _jestUtil() {
- const data = require('jest-util');
- _jestUtil = function () {
- return data;
- };
- return data;
- }
- var _ReporterDispatcher = _interopRequireDefault(
- require('./ReporterDispatcher')
- );
- var _testSchedulerHelper = require('./testSchedulerHelper');
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {default: obj};
- }
- 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;
- }
- async function createTestScheduler(globalConfig, options, context) {
- const scheduler = new TestScheduler(globalConfig, options, context);
- await scheduler._setupReporters();
- return scheduler;
- }
- class TestScheduler {
- constructor(globalConfig, options, context) {
- _defineProperty(this, '_dispatcher', void 0);
- _defineProperty(this, '_globalConfig', void 0);
- _defineProperty(this, '_options', void 0);
- _defineProperty(this, '_context', void 0);
- this._dispatcher = new _ReporterDispatcher.default();
- this._globalConfig = globalConfig;
- this._options = options;
- this._context = context;
- }
- addReporter(reporter) {
- this._dispatcher.register(reporter);
- }
- removeReporter(ReporterClass) {
- this._dispatcher.unregister(ReporterClass);
- }
- async scheduleTests(tests, watcher) {
- const onTestFileStart = this._dispatcher.onTestFileStart.bind(
- this._dispatcher
- );
- const timings = [];
- const contexts = new Set();
- tests.forEach(test => {
- contexts.add(test.context);
- if (test.duration) {
- timings.push(test.duration);
- }
- });
- const aggregatedResults = createAggregatedResults(tests.length);
- const estimatedTime = Math.ceil(
- getEstimatedTime(timings, this._globalConfig.maxWorkers) / 1000
- );
- const runInBand = (0, _testSchedulerHelper.shouldRunInBand)(
- tests,
- timings,
- this._globalConfig
- );
- const onResult = async (test, testResult) => {
- if (watcher.isInterrupted()) {
- return Promise.resolve();
- }
- if (testResult.testResults.length === 0) {
- const message = 'Your test suite must contain at least one test.';
- return onFailure(test, {
- message,
- stack: new Error(message).stack
- });
- } // Throws when the context is leaked after executing a test.
- if (testResult.leaks) {
- const message =
- _chalk().default.red.bold('EXPERIMENTAL FEATURE!\n') +
- 'Your test suite is leaking memory. Please ensure all references are cleaned.\n' +
- '\n' +
- 'There is a number of things that can leak memory:\n' +
- ' - Async operations that have not finished (e.g. fs.readFile).\n' +
- ' - Timers not properly mocked (e.g. setInterval, setTimeout).\n' +
- ' - Keeping references to the global scope.';
- return onFailure(test, {
- message,
- stack: new Error(message).stack
- });
- }
- (0, _testResult().addResult)(aggregatedResults, testResult);
- await this._dispatcher.onTestFileResult(
- test,
- testResult,
- aggregatedResults
- );
- return this._bailIfNeeded(contexts, aggregatedResults, watcher);
- };
- const onFailure = async (test, error) => {
- if (watcher.isInterrupted()) {
- return;
- }
- const testResult = (0, _testResult().buildFailureTestResult)(
- test.path,
- error
- );
- testResult.failureMessage = (0, _jestMessageUtil().formatExecError)(
- testResult.testExecError,
- test.context.config,
- this._globalConfig,
- test.path
- );
- (0, _testResult().addResult)(aggregatedResults, testResult);
- await this._dispatcher.onTestFileResult(
- test,
- testResult,
- aggregatedResults
- );
- };
- const updateSnapshotState = async () => {
- const contextsWithSnapshotResolvers = await Promise.all(
- Array.from(contexts).map(async context => [
- context,
- await _jestSnapshot().default.buildSnapshotResolver(context.config)
- ])
- );
- contextsWithSnapshotResolvers.forEach(([context, snapshotResolver]) => {
- const status = _jestSnapshot().default.cleanup(
- context.hasteFS,
- this._globalConfig.updateSnapshot,
- snapshotResolver,
- context.config.testPathIgnorePatterns
- );
- aggregatedResults.snapshot.filesRemoved += status.filesRemoved;
- aggregatedResults.snapshot.filesRemovedList = (
- aggregatedResults.snapshot.filesRemovedList || []
- ).concat(status.filesRemovedList);
- });
- const updateAll = this._globalConfig.updateSnapshot === 'all';
- aggregatedResults.snapshot.didUpdate = updateAll;
- aggregatedResults.snapshot.failure = !!(
- !updateAll &&
- (aggregatedResults.snapshot.unchecked ||
- aggregatedResults.snapshot.unmatched ||
- aggregatedResults.snapshot.filesRemoved)
- );
- };
- await this._dispatcher.onRunStart(aggregatedResults, {
- estimatedTime,
- showStatus: !runInBand
- });
- const testRunners = Object.create(null);
- const contextsByTestRunner = new WeakMap();
- await Promise.all(
- Array.from(contexts).map(async context => {
- const {config} = context;
- if (!testRunners[config.runner]) {
- var _this$_context, _this$_context2;
- const transformer = await (0, _transform().createScriptTransformer)(
- config
- );
- const Runner = await transformer.requireAndTranspileModule(
- config.runner
- );
- const runner = new Runner(this._globalConfig, {
- changedFiles:
- (_this$_context = this._context) === null ||
- _this$_context === void 0
- ? void 0
- : _this$_context.changedFiles,
- sourcesRelatedToTestsInChangedFiles:
- (_this$_context2 = this._context) === null ||
- _this$_context2 === void 0
- ? void 0
- : _this$_context2.sourcesRelatedToTestsInChangedFiles
- });
- testRunners[config.runner] = runner;
- contextsByTestRunner.set(runner, context);
- }
- })
- );
- const testsByRunner = this._partitionTests(testRunners, tests);
- if (testsByRunner) {
- try {
- for (const runner of Object.keys(testRunners)) {
- const testRunner = testRunners[runner];
- const context = contextsByTestRunner.get(testRunner);
- invariant(context);
- const tests = testsByRunner[runner];
- const testRunnerOptions = {
- serial: runInBand || Boolean(testRunner.isSerial)
- };
- /**
- * Test runners with event emitters are still not supported
- * for third party test runners.
- */
- if (testRunner.__PRIVATE_UNSTABLE_API_supportsEventEmitters__) {
- const unsubscribes = [
- testRunner.on('test-file-start', ([test]) =>
- onTestFileStart(test)
- ),
- testRunner.on('test-file-success', ([test, testResult]) =>
- onResult(test, testResult)
- ),
- testRunner.on('test-file-failure', ([test, error]) =>
- onFailure(test, error)
- ),
- testRunner.on(
- 'test-case-result',
- ([testPath, testCaseResult]) => {
- const test = {
- context,
- path: testPath
- };
- this._dispatcher.onTestCaseResult(test, testCaseResult);
- }
- )
- ];
- await testRunner.runTests(
- tests,
- watcher,
- undefined,
- undefined,
- undefined,
- testRunnerOptions
- );
- unsubscribes.forEach(sub => sub());
- } else {
- await testRunner.runTests(
- tests,
- watcher,
- onTestFileStart,
- onResult,
- onFailure,
- testRunnerOptions
- );
- }
- }
- } catch (error) {
- if (!watcher.isInterrupted()) {
- throw error;
- }
- }
- }
- await updateSnapshotState();
- aggregatedResults.wasInterrupted = watcher.isInterrupted();
- await this._dispatcher.onRunComplete(contexts, aggregatedResults);
- const anyTestFailures = !(
- aggregatedResults.numFailedTests === 0 &&
- aggregatedResults.numRuntimeErrorTestSuites === 0
- );
- const anyReporterErrors = this._dispatcher.hasErrors();
- aggregatedResults.success = !(
- anyTestFailures ||
- aggregatedResults.snapshot.failure ||
- anyReporterErrors
- );
- return aggregatedResults;
- }
- _partitionTests(testRunners, tests) {
- if (Object.keys(testRunners).length > 1) {
- return tests.reduce((testRuns, test) => {
- const runner = test.context.config.runner;
- if (!testRuns[runner]) {
- testRuns[runner] = [];
- }
- testRuns[runner].push(test);
- return testRuns;
- }, Object.create(null));
- } else if (tests.length > 0 && tests[0] != null) {
- // If there is only one runner, don't partition the tests.
- return Object.assign(Object.create(null), {
- [tests[0].context.config.runner]: tests
- });
- } else {
- return null;
- }
- }
- _shouldAddDefaultReporters(reporters) {
- return (
- !reporters ||
- !!reporters.find(
- reporter => this._getReporterProps(reporter).path === 'default'
- )
- );
- }
- async _setupReporters() {
- const {collectCoverage, notify, reporters} = this._globalConfig;
- const isDefault = this._shouldAddDefaultReporters(reporters);
- if (isDefault) {
- this._setupDefaultReporters(collectCoverage);
- }
- if (!isDefault && collectCoverage) {
- var _this$_context3, _this$_context4;
- this.addReporter(
- new (_reporters().CoverageReporter)(this._globalConfig, {
- changedFiles:
- (_this$_context3 = this._context) === null ||
- _this$_context3 === void 0
- ? void 0
- : _this$_context3.changedFiles,
- sourcesRelatedToTestsInChangedFiles:
- (_this$_context4 = this._context) === null ||
- _this$_context4 === void 0
- ? void 0
- : _this$_context4.sourcesRelatedToTestsInChangedFiles
- })
- );
- }
- if (notify) {
- this.addReporter(
- new (_reporters().NotifyReporter)(
- this._globalConfig,
- this._options.startRun,
- this._context
- )
- );
- }
- if (reporters && Array.isArray(reporters)) {
- await this._addCustomReporters(reporters);
- }
- }
- _setupDefaultReporters(collectCoverage) {
- this.addReporter(
- this._globalConfig.verbose
- ? new (_reporters().VerboseReporter)(this._globalConfig)
- : new (_reporters().DefaultReporter)(this._globalConfig)
- );
- if (collectCoverage) {
- var _this$_context5, _this$_context6;
- this.addReporter(
- new (_reporters().CoverageReporter)(this._globalConfig, {
- changedFiles:
- (_this$_context5 = this._context) === null ||
- _this$_context5 === void 0
- ? void 0
- : _this$_context5.changedFiles,
- sourcesRelatedToTestsInChangedFiles:
- (_this$_context6 = this._context) === null ||
- _this$_context6 === void 0
- ? void 0
- : _this$_context6.sourcesRelatedToTestsInChangedFiles
- })
- );
- }
- this.addReporter(new (_reporters().SummaryReporter)(this._globalConfig));
- }
- async _addCustomReporters(reporters) {
- for (const reporter of reporters) {
- const {options, path} = this._getReporterProps(reporter);
- if (path === 'default') continue;
- try {
- const Reporter = await (0, _jestUtil().requireOrImportModule)(
- path,
- true
- );
- this.addReporter(new Reporter(this._globalConfig, options));
- } catch (error) {
- error.message =
- 'An error occurred while adding the reporter at path "' +
- _chalk().default.bold(path) +
- '".' +
- error.message;
- throw error;
- }
- }
- }
- /**
- * Get properties of a reporter in an object
- * to make dealing with them less painful.
- */
- _getReporterProps(reporter) {
- if (typeof reporter === 'string') {
- return {
- options: this._options,
- path: reporter
- };
- } else if (Array.isArray(reporter)) {
- const [path, options] = reporter;
- return {
- options,
- path
- };
- }
- throw new Error('Reporter should be either a string or an array');
- }
- async _bailIfNeeded(contexts, aggregatedResults, watcher) {
- if (
- this._globalConfig.bail !== 0 &&
- aggregatedResults.numFailedTests >= this._globalConfig.bail
- ) {
- if (watcher.isWatchMode()) {
- await watcher.setState({
- interrupted: true
- });
- return;
- }
- try {
- await this._dispatcher.onRunComplete(contexts, aggregatedResults);
- } finally {
- const exitCode = this._globalConfig.testFailureExitCode;
- (0, _exit().default)(exitCode);
- }
- }
- }
- }
- function invariant(condition, message) {
- if (!condition) {
- throw new Error(message);
- }
- }
- const createAggregatedResults = numTotalTestSuites => {
- const result = (0, _testResult().makeEmptyAggregatedTestResult)();
- result.numTotalTestSuites = numTotalTestSuites;
- result.startTime = Date.now();
- result.success = false;
- return result;
- };
- const getEstimatedTime = (timings, workers) => {
- if (timings.length === 0) {
- return 0;
- }
- const max = Math.max(...timings);
- return timings.length <= workers
- ? max
- : Math.max(timings.reduce((sum, time) => sum + time) / workers, max);
- };
|