UNPKG

@nrwl/jest

Version:

The Nx Plugin for Jest contains executors and generators allowing your workspace to use the powerful Jest testing capabilities.

153 lines (152 loc) • 8.54 kB
"use strict"; var _a; var _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.batchJest = exports.jestConfigParser = exports.jestExecutor = void 0; const tslib_1 = require("tslib"); require("dotenv/config"); const jest_1 = require("jest"); const jest_config_1 = require("jest-config"); const reporters_1 = require("@jest/reporters"); const test_result_1 = require("@jest/test-result"); const path = require("path"); const path_1 = require("path"); const devkit_1 = require("@nrwl/devkit"); const summary_1 = require("./summary"); const fs_1 = require("fs"); (_a = (_b = process.env).NODE_ENV) !== null && _a !== void 0 ? _a : (_b.NODE_ENV = 'test'); function jestExecutor(options, context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const config = yield jestConfigParser(options, context); const { results } = yield (0, jest_1.runCLI)(config, [options.jestConfig]); return { success: results.success }; }); } exports.jestExecutor = jestExecutor; function getExtraArgs(options, schema) { const extraArgs = {}; for (const key of Object.keys(options)) { if (!schema.properties[key]) { extraArgs[key] = options[key]; } } return extraArgs; } function jestConfigParser(options, context, multiProjects = false) { var _a; return tslib_1.__awaiter(this, void 0, void 0, function* () { let jestConfig; // support passing extra args to jest cli supporting 3rd party plugins // like 'jest-runner-groups' --group arg const schema = yield Promise.resolve().then(() => require('./schema.json')); const extraArgs = getExtraArgs(options, schema); const config = Object.assign(Object.assign({}, extraArgs), { $0: undefined, _: [], config: options.config, coverage: options.codeCoverage, bail: options.bail, ci: options.ci, color: options.color, detectOpenHandles: options.detectOpenHandles, logHeapUsage: options.logHeapUsage, detectLeaks: options.detectLeaks, json: options.json, maxWorkers: options.maxWorkers, onlyChanged: options.onlyChanged, changedSince: options.changedSince, outputFile: options.outputFile, passWithNoTests: options.passWithNoTests, runInBand: options.runInBand, showConfig: options.showConfig, silent: options.silent, testLocationInResults: options.testLocationInResults, testNamePattern: options.testNamePattern, testPathPattern: options.testPathPattern, testPathIgnorePatterns: options.testPathIgnorePatterns, testTimeout: options.testTimeout, colors: options.colors, verbose: options.verbose, testResultsProcessor: options.testResultsProcessor, updateSnapshot: options.updateSnapshot, useStderr: options.useStderr, watch: options.watch, watchAll: options.watchAll }); if (!multiProjects) { options.jestConfig = path.resolve(context.root, options.jestConfig); jestConfig = (yield (0, jest_config_1.readConfig)(config, options.jestConfig)).projectConfig; } // for backwards compatibility if (options.setupFile && !multiProjects) { const setupFilesAfterEnvSet = new Set([ ...((_a = jestConfig.setupFilesAfterEnv) !== null && _a !== void 0 ? _a : []), path.resolve(context.root, options.setupFile), ]); config.setupFilesAfterEnv = Array.from(setupFilesAfterEnvSet); } if (options.testFile) { config._.push(options.testFile); } if (options.findRelatedTests) { const parsedTests = options.findRelatedTests .split(',') .map((s) => s.trim()); config._.push(...parsedTests); config.findRelatedTests = true; } if (options.coverageDirectory) { config.coverageDirectory = path.join(context.root, options.coverageDirectory); } if (options.clearCache) { config.clearCache = true; } if (options.reporters && options.reporters.length > 0) { config.reporters = options.reporters; } if (Array.isArray(options.coverageReporters) && options.coverageReporters.length > 0) { config.coverageReporters = options.coverageReporters; } return config; }); } exports.jestConfigParser = jestConfigParser; exports.default = jestExecutor; function batchJest(taskGraph, inputs, overrides, context) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let configPaths = []; let selectedProjects = []; let projectsWithNoName = []; for (const task of taskGraph.roots) { let configPath = path.resolve(context.root, inputs[task].jestConfig); configPaths.push(configPath); /* The display name in the jest.config.js is the correct project name jest * uses to determine projects. It is usually the same as the Nx projectName * but it can be changed. The safest method is to extract the displayName * from the config file, but skip the project if it does not exist. */ const displayNameValueRegex = new RegExp(/(['"]+.*['"])(?<=displayName+.*)/, 'g'); const fileContents = (0, fs_1.readFileSync)(configPath, { encoding: 'utf-8' }); if (!displayNameValueRegex.test(fileContents)) { projectsWithNoName.push([task.split(':')[0], configPath]); continue; } const displayName = fileContents .match(displayNameValueRegex) .map((value) => value.substring(1, value.length - 1))[0]; selectedProjects.push(displayName); } if (projectsWithNoName.length > 0) { throw new Error((0, devkit_1.stripIndents) `Some projects do not have a "displayName" property. Jest Batch Mode requires this to be set. Please ensure this value is set. Projects missing "displayName": ${projectsWithNoName.map(([project, configPath]) => ` - ${project} - ${configPath}\r\n`)} You can learn more about this requirement from Jest here: https://jestjs.io/docs/cli#--selectprojects-project1--projectn`); } const parsedConfigs = yield jestConfigParser(overrides, context, true); const { globalConfig, results } = yield (0, jest_1.runCLI)(Object.assign(Object.assign({}, parsedConfigs), { selectProjects: selectedProjects }), [devkit_1.workspaceRoot]); const { configs } = yield (0, jest_config_1.readConfigs)({ $0: undefined, _: [] }, configPaths); const jestTaskExecutionResults = {}; for (let i = 0; i < taskGraph.roots.length; i++) { let root = taskGraph.roots[i]; const aggregatedResults = (0, test_result_1.makeEmptyAggregatedTestResult)(); aggregatedResults.startTime = results.startTime; let endTime; const projectRoot = (0, path_1.join)(context.root, taskGraph.tasks[root].projectRoot); let resultOutput = ''; for (const testResult of results.testResults) { if (testResult.testFilePath.startsWith(projectRoot)) { aggregatedResults.startTime = aggregatedResults.startTime ? Math.min(aggregatedResults.startTime, testResult.perfStats.start) : testResult.perfStats.start; endTime = endTime ? Math.max(testResult.perfStats.end, endTime) : testResult.perfStats.end; (0, test_result_1.addResult)(aggregatedResults, testResult); resultOutput += '\n\r' + reporters_1.utils.getResultHeader(testResult, globalConfig, configs[i]); } } aggregatedResults.numTotalTestSuites = aggregatedResults.testResults.length; jestTaskExecutionResults[root] = { startTime: aggregatedResults.startTime, endTime, success: aggregatedResults.numFailedTests === 0, // TODO(caleb): getSummary assumed endTime is Date.now(). // might need to make own method to correctly set the endtime base on tests instead of _now_ terminalOutput: resultOutput + '\n\r\n\r' + (0, summary_1.getSummary)(aggregatedResults), }; } return jestTaskExecutionResults; }); } exports.batchJest = batchJest; //# sourceMappingURL=jest.impl.js.map