github-pages-deploy-action/node_modules/@jest/core/build/TestScheduler.js

463 lines
12 KiB
JavaScript
Raw Normal View History

2020-03-31 20:42:07 +08:00
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _chalk() {
const data = _interopRequireDefault(require('chalk'));
_chalk = 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 _jestRunner() {
const data = _interopRequireDefault(require('jest-runner'));
_jestRunner = function () {
return data;
};
return data;
}
function _reporters() {
const data = require('@jest/reporters');
_reporters = function () {
return data;
};
return data;
}
function _exit() {
const data = _interopRequireDefault(require('exit'));
_exit = function () {
return data;
};
return data;
}
function _testResult() {
const data = require('@jest/test-result');
_testResult = 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;
}
// The default jest-runner is required because it is the default test runner
// and required implicitly through the `runner` ProjectConfig option.
_jestRunner().default;
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;
this._setupReporters();
}
addReporter(reporter) {
this._dispatcher.register(reporter);
}
removeReporter(ReporterClass) {
this._dispatcher.unregister(ReporterClass);
}
async scheduleTests(tests, watcher) {
const onStart = this._dispatcher.onTestStart.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.onTestResult(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.onTestResult(test, testResult, aggregatedResults);
};
const updateSnapshotState = () => {
contexts.forEach(context => {
const status = _jestSnapshot().default.cleanup(
context.hasteFS,
this._globalConfig.updateSnapshot,
_jestSnapshot().default.buildSnapshotResolver(context.config),
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);
contexts.forEach(({config}) => {
if (!testRunners[config.runner]) {
const Runner = require(config.runner);
testRunners[config.runner] = new Runner(this._globalConfig, {
changedFiles: this._context && this._context.changedFiles
});
}
});
const testsByRunner = this._partitionTests(testRunners, tests);
if (testsByRunner) {
try {
for (const runner of Object.keys(testRunners)) {
await testRunners[runner].runTests(
testsByRunner[runner],
watcher,
onStart,
onResult,
onFailure,
{
serial: runInBand || Boolean(testRunners[runner].isSerial)
}
);
}
} catch (error) {
if (!watcher.isInterrupted()) {
throw error;
}
}
}
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'
)
);
}
_setupReporters() {
const {collectCoverage, notify, reporters} = this._globalConfig;
const isDefault = this._shouldAddDefaultReporters(reporters);
if (isDefault) {
this._setupDefaultReporters(collectCoverage);
}
if (!isDefault && collectCoverage) {
this.addReporter(
new (_reporters().CoverageReporter)(this._globalConfig, {
changedFiles: this._context && this._context.changedFiles
})
);
}
if (notify) {
this.addReporter(
new (_reporters().NotifyReporter)(
this._globalConfig,
this._options.startRun,
this._context
)
);
}
if (reporters && Array.isArray(reporters)) {
this._addCustomReporters(reporters);
}
}
_setupDefaultReporters(collectCoverage) {
this.addReporter(
this._globalConfig.verbose
? new (_reporters().VerboseReporter)(this._globalConfig)
: new (_reporters().DefaultReporter)(this._globalConfig)
);
if (collectCoverage) {
this.addReporter(
new (_reporters().CoverageReporter)(this._globalConfig, {
changedFiles: this._context && this._context.changedFiles
})
);
}
this.addReporter(new (_reporters().SummaryReporter)(this._globalConfig));
}
_addCustomReporters(reporters) {
reporters.forEach(reporter => {
const {options, path} = this._getReporterProps(reporter);
if (path === 'default') return;
try {
// TODO: Use `requireAndTranspileModule` for Jest 26
const Reporter = (0, _jestUtil().interopRequireDefault)(require(path))
.default;
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');
}
_bailIfNeeded(contexts, aggregatedResults, watcher) {
if (
this._globalConfig.bail !== 0 &&
aggregatedResults.numFailedTests >= this._globalConfig.bail
) {
if (watcher.isWatchMode()) {
watcher.setState({
interrupted: true
});
} else {
const failureExit = () => (0, _exit().default)(1);
return this._dispatcher
.onRunComplete(contexts, aggregatedResults)
.then(failureExit)
.catch(failureExit);
}
}
return Promise.resolve();
}
}
exports.default = TestScheduler;
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) {
return 0;
}
const max = Math.max.apply(null, timings);
return timings.length <= workers
? max
: Math.max(timings.reduce((sum, time) => sum + time) / workers, max);
};