From 62b6b8cbf2bbafcd0e359a5c13c8042124cf759e Mon Sep 17 00:00:00 2001 From: Emily Xiong Date: Sun, 22 Sep 2024 20:08:26 -0400 Subject: [PATCH] fix(core): fix output text for multiple targets --- .../life-cycles/formatting-utils.spec.ts | 339 +++++++++++++++++- .../life-cycles/formatting-utils.ts | 55 +-- 2 files changed, 372 insertions(+), 22 deletions(-) diff --git a/packages/nx/src/tasks-runner/life-cycles/formatting-utils.spec.ts b/packages/nx/src/tasks-runner/life-cycles/formatting-utils.spec.ts index cf66eaf7f08ca..8b706a63c6a9d 100644 --- a/packages/nx/src/tasks-runner/life-cycles/formatting-utils.spec.ts +++ b/packages/nx/src/tasks-runner/life-cycles/formatting-utils.spec.ts @@ -1,4 +1,5 @@ -import { formatFlags } from './formatting-utils'; +import { output } from '../../utils/output'; +import { formatFlags, formatTargetsAndProjects } from './formatting-utils'; describe('formatFlags', () => { it('should properly show string values', () => { @@ -42,3 +43,339 @@ describe('formatFlags', () => { ); }); }); + +describe('formatTargetsAndProjects', () => { + it('should handle single project and target', () => { + expect( + formatTargetsAndProjects( + ['myproject'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:build', + target: { + project: 'myproject', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('build')} for project myproject`); + + expect( + formatTargetsAndProjects( + ['myproject'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('lint')} for project myproject`); + }); + + it('should handle single project and multiple targets', () => { + expect( + formatTargetsAndProjects( + ['myproject'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:build', + target: { + project: 'myproject', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject:test', + target: { + project: 'myproject', + target: 'test', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual( + `targets ${output.bold('build')}, ${output.bold( + 'test' + )} for project myproject` + ); + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('lint')} for project myproject`); + + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject2:lint', + target: { + project: 'myproject2', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('lint')} for project myproject2`); + }); + + it('should handle multiple projects and targets', () => { + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:build', + target: { + project: 'myproject', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject2:build', + target: { + project: 'myproject2', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('build')} for 2 projects`); + + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject2:lint', + target: { + project: 'myproject2', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual(`target ${output.bold('lint')} for 2 projects`); + + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject2:build', + target: { + project: 'myproject2', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual( + `targets ${output.bold('lint')}, ${output.bold('build')} for 2 projects` + ); + }); + + it('should handle dependent tasks', () => { + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:build', + target: { + project: 'myproject', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject3:build', + target: { + project: 'myproject3', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual( + `target ${output.bold('build')} for project myproject and ${output.bold( + 1 + )} task it depends on` + ); + + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject2:lint', + target: { + project: 'myproject2', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject3:lint', + target: { + project: 'myproject3', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual( + `target ${output.bold('lint')} for 2 projects and ${output.bold( + 1 + )} task they depend on` + ); + + expect( + formatTargetsAndProjects( + ['myproject', 'myproject2'], + ['lint', 'build', 'test'], + [ + { + id: 'myproject:lint', + target: { + project: 'myproject', + target: 'lint', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject2:build', + target: { + project: 'myproject2', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject3:build', + target: { + project: 'myproject3', + target: 'build', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + { + id: 'myproject3:bundle', + target: { + project: 'myproject3', + target: 'bundle', + }, + overrides: {}, + parallelism: false, + outputs: [], + }, + ] + ) + ).toEqual( + `targets ${output.bold('lint')}, ${output.bold( + 'build' + )} for 2 projects and ${output.bold(2)} tasks they depend on` + ); + }); +}); diff --git a/packages/nx/src/tasks-runner/life-cycles/formatting-utils.ts b/packages/nx/src/tasks-runner/life-cycles/formatting-utils.ts index 9a0465fadc7aa..b488a9d52a8f8 100644 --- a/packages/nx/src/tasks-runner/life-cycles/formatting-utils.ts +++ b/packages/nx/src/tasks-runner/life-cycles/formatting-utils.ts @@ -26,32 +26,45 @@ export function formatTargetsAndProjects( targets: string[], tasks: Task[] ) { - if (tasks.length === 1) - return `target ${targets[0]} for project ${projectNames[0]}`; - - let text; - const project = - projectNames.length === 1 - ? `project ${projectNames[0]}` - : `${projectNames.length} projects`; + let targetsText = ''; + let projectsText = ''; + let dependentTasksText = ''; + + const tasksTargets = new Set(); + const tasksProjects = new Set(); + const dependentTasks = new Set(); + + tasks.forEach((task) => { + tasksTargets.add(task.target.target); + tasksProjects.add(task.target.project); + if ( + !projectNames.includes(task.target.project) || + !targets.includes(task.target.target) + ) { + dependentTasks.add(task); + } + }); + + targets = targets.filter((t) => tasksTargets.has(t)); // filter out targets that don't exist + projectNames = projectNames.filter((p) => tasksProjects.has(p)); // filter out projects that don't exist + if (targets.length === 1) { - text = `target ${output.bold(targets[0])} for ${project}`; + targetsText = `target ${output.bold(targets[0])}`; } else { - text = `targets ${targets - .map((t) => output.bold(t)) - .join(', ')} for ${project}`; + targetsText = `targets ${targets.map((t) => output.bold(t)).join(', ')}`; } - const dependentTasks = tasks.filter( - (t) => - projectNames.indexOf(t.target.project) === -1 || - targets.indexOf(t.target.target) === -1 - ).length; + if (projectNames.length === 1) { + projectsText = `project ${projectNames[0]}`; + } else { + projectsText = `${projectNames.length} projects`; + } - if (dependentTasks > 0) { - text += ` and ${output.bold(dependentTasks)} ${ - dependentTasks === 1 ? 'task' : 'tasks' + if (dependentTasks.size > 0) { + dependentTasksText = ` and ${output.bold(dependentTasks.size)} ${ + dependentTasks.size === 1 ? 'task' : 'tasks' } ${projectNames.length === 1 ? 'it depends on' : 'they depend on'}`; } - return text; + + return `${targetsText} for ${projectsText}${dependentTasksText}`; }