@nx/jest
Version:
118 lines (117 loc) • 5.53 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = update;
const devkit_1 = require("@nx/devkit");
const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
const project_configuration_utils_1 = require("nx/src/project-graph/utils/project-configuration-utils");
async function update(tree) {
const nxJson = (0, devkit_1.readNxJson)(tree);
// Don't override anything if there are already target defaults for jest
if (nxJson.targetDefaults?.['@nx/jest:jest']) {
return;
}
nxJson.targetDefaults ??= {};
/**
* A set of targets which does not use any other executors
*/
const jestTargets = new Set();
const graph = await (0, devkit_1.createProjectGraphAsync)();
(0, executor_options_utils_1.forEachExecutorOptionsInGraph)(graph, '@nx/jest:jest', (value, proj, targetName) => {
jestTargets.add(targetName);
});
// Workspace does not use jest?
if (jestTargets.size === 0) {
return;
}
// Use the project graph so targets which are inferred are considered
const projects = graph.nodes;
const projectMap = (0, devkit_1.getProjects)(tree);
const jestDefaults = (nxJson.targetDefaults['@nx/jest:jest'] = {});
// All jest targets have the same name
if (jestTargets.size === 1) {
const targetName = Array.from(jestTargets)[0];
if (nxJson.targetDefaults[targetName]) {
Object.assign(jestDefaults, nxJson.targetDefaults[targetName]);
}
}
jestDefaults.cache ??= true;
const inputs = ['default'];
inputs.push(nxJson.namedInputs?.production ? '^production' : '^default');
if (tree.exists('jest.preset.js')) {
inputs.push('{workspaceRoot}/jest.preset.js');
}
jestDefaults.inputs ??= inputs;
// Remember if there were already defaults so we don't assume the executor default
const passWithNoTestsPreviouslyInDefaults = jestDefaults.options?.passWithNoTests !== undefined;
const ciCiPreviouslyInDefaults = jestDefaults.configurations?.ci?.ci !== undefined;
const ciCodeCoveragePreviouslyInDefaults = jestDefaults.configurations?.ci?.codeCoverage !== undefined;
jestDefaults.options ??= {};
jestDefaults.options.passWithNoTests ??= true;
jestDefaults.configurations ??= {};
jestDefaults.configurations.ci ??= {};
jestDefaults.configurations.ci.ci ??= true;
jestDefaults.configurations.ci.codeCoverage ??= true;
// Cleanup old target defaults
for (const [targetDefaultKey, targetDefault] of Object.entries(nxJson.targetDefaults)) {
if (!isTargetDefaultUsed(targetDefault, nxJson.targetDefaults, projects, projectMap)) {
delete nxJson.targetDefaults[targetDefaultKey];
}
}
(0, devkit_1.updateNxJson)(tree, nxJson);
(0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/jest:jest', (value, proj, targetName, configuration) => {
const projConfig = projectMap.get(proj);
if (!configuration) {
// Options
if (value.passWithNoTests === jestDefaults.options.passWithNoTests) {
delete projConfig.targets[targetName].options.passWithNoTests;
}
else if (!passWithNoTestsPreviouslyInDefaults) {
projConfig.targets[targetName].options.passWithNoTests ??= false;
}
if (Object.keys(projConfig.targets[targetName].options).length === 0) {
delete projConfig.targets[targetName].options;
}
}
else if (configuration === 'ci') {
// CI Config
if (value.ci === jestDefaults.configurations.ci.ci) {
delete projConfig.targets[targetName].configurations.ci.ci;
}
else if (ciCiPreviouslyInDefaults) {
projConfig.targets[targetName].configurations.ci.ci ??= false;
}
if (value.codeCoverage === jestDefaults.configurations.ci.codeCoverage) {
delete projConfig.targets[targetName].configurations.ci.codeCoverage;
}
else if (ciCodeCoveragePreviouslyInDefaults) {
projConfig.targets[targetName].configurations.ci.codeCoverage ??=
false;
}
if (Object.keys(projConfig.targets[targetName].configurations.ci)
.length === 0) {
delete projConfig.targets[targetName].configurations.ci;
}
if (Object.keys(projConfig.targets[targetName].configurations).length ===
0) {
delete projConfig.targets[targetName].configurations;
}
}
(0, devkit_1.updateProjectConfiguration)(tree, proj, projConfig);
});
await (0, devkit_1.formatFiles)(tree);
}
/**
* Checks every target on every project to see if one of them uses the target default
*/
function isTargetDefaultUsed(targetDefault, targetDefaults, projects, projectMap) {
for (const p of Object.values(projects)) {
for (const targetName in p.data?.targets ?? {}) {
if ((0, project_configuration_utils_1.readTargetDefaultsForTarget)(targetName, targetDefaults,
// It might seem like we should use the graph here too but we don't want to pass an executor which was processed in the graph
projectMap.get(p.name)?.targets?.[targetName]?.executor) === targetDefault) {
return true;
}
}
}
return false;
}
;