in packages/jest-core/src/runJest.ts [127:305]
export default async function runJest({
contexts,
globalConfig,
outputStream,
testWatcher,
jestHooks = new JestHook().getEmitter(),
startRun,
changedFilesPromise,
onComplete,
failedTestsCache,
filter,
}: {
globalConfig: Config.GlobalConfig;
contexts: Array<Context>;
outputStream: NodeJS.WriteStream;
testWatcher: TestWatcher;
jestHooks?: JestHookEmitter;
startRun: (globalConfig: Config.GlobalConfig) => void;
changedFilesPromise?: ChangedFilesPromise;
onComplete: (testResults: AggregatedResult) => void;
failedTestsCache?: FailedTestsCache;
filter?: Filter;
}): Promise<void> {
// Clear cache for required modules - there might be different resolutions
// from Jest's config loading to running the tests
Resolver.clearDefaultResolverCache();
const Sequencer: typeof TestSequencer = await requireOrImportModule(
globalConfig.testSequencer,
);
const sequencer = new Sequencer();
let allTests: Array<Test> = [];
if (changedFilesPromise && globalConfig.watch) {
const {repos} = await changedFilesPromise;
const noSCM = (
Object.keys(repos) as Array<keyof ChangedFiles['repos']>
).every(scm => repos[scm].size === 0);
if (noSCM) {
process.stderr.write(
`\n${chalk.bold(
'--watch',
)} is not supported without git/hg, please use --watchAll\n`,
);
exit(1);
}
}
const searchSources = contexts.map(context => new SearchSource(context));
const testRunData: TestRunData = await Promise.all(
contexts.map(async (context, index) => {
const searchSource = searchSources[index];
const matches = await getTestPaths(
globalConfig,
searchSource,
outputStream,
changedFilesPromise && (await changedFilesPromise),
jestHooks,
filter,
);
allTests = allTests.concat(matches.tests);
return {context, matches};
}),
);
if (globalConfig.shard) {
if (typeof sequencer.shard !== 'function') {
throw new Error(
`Shard ${globalConfig.shard.shardIndex}/${globalConfig.shard.shardCount} requested, but test sequencer ${Sequencer.name} in ${globalConfig.testSequencer} has no shard method.`,
);
}
allTests = await sequencer.shard(allTests, globalConfig.shard);
}
allTests = await sequencer.sort(allTests);
if (globalConfig.listTests) {
const testsPaths = Array.from(new Set(allTests.map(test => test.path)));
/* eslint-disable no-console */
if (globalConfig.json) {
console.log(JSON.stringify(testsPaths));
} else {
console.log(testsPaths.join('\n'));
}
/* eslint-enable */
onComplete && onComplete(makeEmptyAggregatedTestResult());
return;
}
if (globalConfig.onlyFailures) {
if (failedTestsCache) {
allTests = failedTestsCache.filterTests(allTests);
} else {
allTests = await sequencer.allFailedTests(allTests);
}
}
const hasTests = allTests.length > 0;
if (!hasTests) {
const {exitWith0, message: noTestsFoundMessage} = getNoTestsFoundMessage(
testRunData,
globalConfig,
);
if (exitWith0) {
new CustomConsole(outputStream, outputStream).log(noTestsFoundMessage);
} else {
new CustomConsole(outputStream, outputStream).error(noTestsFoundMessage);
exit(1);
}
} else if (
allTests.length === 1 &&
globalConfig.silent !== true &&
globalConfig.verbose !== false
) {
const newConfig: Config.GlobalConfig = {...globalConfig, verbose: true};
globalConfig = Object.freeze(newConfig);
}
let collectHandles;
if (globalConfig.detectOpenHandles) {
collectHandles = collectNodeHandles();
}
if (hasTests) {
await runGlobalHook({allTests, globalConfig, moduleName: 'globalSetup'});
}
if (changedFilesPromise) {
const changedFilesInfo = await changedFilesPromise;
if (changedFilesInfo.changedFiles) {
testSchedulerContext.changedFiles = changedFilesInfo.changedFiles;
const sourcesRelatedToTestsInChangedFilesArray = (
await Promise.all(
contexts.map(async (_, index) => {
const searchSource = searchSources[index];
return searchSource.findRelatedSourcesFromTestsInChangedFiles(
changedFilesInfo,
);
}),
)
).reduce((total, paths) => total.concat(paths), []);
testSchedulerContext.sourcesRelatedToTestsInChangedFiles = new Set(
sourcesRelatedToTestsInChangedFilesArray,
);
}
}
const scheduler = await createTestScheduler(
globalConfig,
{startRun},
testSchedulerContext,
);
const results = await scheduler.scheduleTests(allTests, testWatcher);
sequencer.cacheResults(allTests, results);
if (hasTests) {
await runGlobalHook({allTests, globalConfig, moduleName: 'globalTeardown'});
}
await processResults(results, {
collectHandles,
json: globalConfig.json,
onComplete,
outputFile: globalConfig.outputFile,
outputStream,
testResultsProcessor: globalConfig.testResultsProcessor,
});
}