From 78a85085b2b23a45726d4433ec7cbe06a040d9d6 Mon Sep 17 00:00:00 2001 From: mpsanchis Date: Tue, 11 Jun 2024 10:45:19 +0200 Subject: [PATCH] chore(js): Enhance unit test of topological sorting of project nodes --- .../utils/sort-projects-topologically.spec.ts | 273 ++++++++++++------ 1 file changed, 177 insertions(+), 96 deletions(-) diff --git a/packages/js/src/generators/release-version/utils/sort-projects-topologically.spec.ts b/packages/js/src/generators/release-version/utils/sort-projects-topologically.spec.ts index 7dbcf27cfb36d1..095f58348fd921 100644 --- a/packages/js/src/generators/release-version/utils/sort-projects-topologically.spec.ts +++ b/packages/js/src/generators/release-version/utils/sort-projects-topologically.spec.ts @@ -1,114 +1,195 @@ import { sortProjectsTopologically } from './sort-projects-topologically'; +import { DependencyType, StaticDependency } from '@nx/devkit'; describe('sortProjectsTopologically', () => { - it('should return empty array if no projects are provided', () => { - const projectGraph = { - dependencies: {}, - nodes: {}, - }; - const projectNodes = []; - const result = sortProjectsTopologically(projectGraph, projectNodes); - expect(result).toEqual([]); - }); + describe('edge cases', () => { + it('should return empty array if no projects are provided', () => { + const projectGraph = { + dependencies: {}, + nodes: {}, + }; + const projectNodes = []; + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual([]); + }); - it('should return a single project if only one project is provided', () => { - const projectGraph = { - dependencies: {}, - nodes: { - project1: { - name: 'project1', - data: { - root: '', + it('should return a single project if only one project is provided', () => { + const projectGraph = { + dependencies: {}, + nodes: { + project1: { + name: 'project1', + data: { + root: '', + }, + type: 'app' as const, }, - type: 'app' as const, }, - }, - }; - const projectNodes = [projectGraph.nodes.project1]; - const result = sortProjectsTopologically(projectGraph, projectNodes); - expect(result).toEqual([projectGraph.nodes.project1]); - }); + }; + const projectNodes = [projectGraph.nodes.project1]; + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual([projectGraph.nodes.project1]); + }); - it('should return projects in the correct order', () => { - const projectGraph = { - dependencies: { - project1: [ - { - source: 'project1', - target: 'project2', - type: 'static', - }, - ], - project2: [], - }, - nodes: { - project1: { - name: 'project1', - data: { - root: '', - }, - type: 'app' as const, + it('should return the original list of nodes if a circular dependency is present', () => { + const projectGraph = { + dependencies: { + project1: [ + { + source: 'project1', + target: 'project2', + type: 'static', + }, + ], + project2: [ + { + source: 'project2', + target: 'project1', + type: 'static', + }, + ], }, - project2: { - name: 'project2', - data: { - root: '', + nodes: { + project1: { + name: 'project1', + data: { + root: '', + }, + type: 'app' as const, + }, + project2: { + name: 'project2', + data: { + root: '', + }, + type: 'app' as const, }, - type: 'app' as const, }, - }, - }; - const projectNodes = [ - projectGraph.nodes.project1, - projectGraph.nodes.project2, - ]; - const result = sortProjectsTopologically(projectGraph, projectNodes); - expect(result).toEqual([ - projectGraph.nodes.project2, - projectGraph.nodes.project1, - ]); + }; + const projectNodes = [ + projectGraph.nodes.project1, + projectGraph.nodes.project2, + ]; + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual(projectNodes); + }); }); - it('should return the original list of nodes if a circular dependency is present', () => { - const projectGraph = { - dependencies: { - project1: [ - { - source: 'project1', - target: 'project2', - type: 'static', - }, - ], - project2: [ - { - source: 'project2', - target: 'project1', - type: 'static', + describe('complex sorting cases', () => { + it('should return [B,A] if A depends on B', () => { + const projectGraph = { + dependencies: { + project1: [ + { + source: 'project1', + target: 'project2', + type: 'static', + }, + ], + project2: [], + }, + nodes: { + project1: { + name: 'project1', + data: { + root: '', + }, + type: 'app' as const, }, - ], - }, - nodes: { - project1: { - name: 'project1', - data: { - root: '', + project2: { + name: 'project2', + data: { + root: '', + }, + type: 'app' as const, }, - type: 'app' as const, }, - project2: { - name: 'project2', - data: { - root: '', - }, - type: 'app' as const, + }; + const projectNodes = [ + projectGraph.nodes.project1, + projectGraph.nodes.project2, + ]; + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual([ + projectGraph.nodes.project2, + projectGraph.nodes.project1, + ]); + }); + it('should return [C,B,A] if A depends on B and B depends on C', () => { + const graphNodes = Object.fromEntries( + [1, 2, 3].map((n) => { + return [ + `project${n}`, + { + name: `project${n}`, + data: { root: '' }, + type: 'app' as const, + }, + ]; + }) + ); + const projectGraph = { + dependencies: { + project1: staticDependencies('project1', ['project2']), + project2: staticDependencies('project2', ['project3']), }, - }, - }; - const projectNodes = [ - projectGraph.nodes.project1, - projectGraph.nodes.project2, - ]; - const result = sortProjectsTopologically(projectGraph, projectNodes); - expect(result).toEqual(projectNodes); + nodes: graphNodes, + }; + const projectNodes = [1, 2, 3].map( + (n) => projectGraph.nodes[`project${n}`] + ); + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual( + [3, 2, 1].map((n) => projectGraph.nodes[`project${n}`]) + ); + }); + + it('should return [A,B,C,D] if A has 0 dependencies, B has 1, C has 2, and D has 3', () => { + const graphNodes = Object.fromEntries( + [1, 2, 3, 4].map((n) => { + return [ + `project${n}`, + { + name: `project${n}`, + data: { root: '' }, + type: 'app' as const, + }, + ]; + }) + ); + const projectGraph = { + dependencies: { + project1: [], + project2: staticDependencies('project2', ['project1']), + project3: staticDependencies('project3', ['project1', 'project2']), + project4: staticDependencies('project4', [ + 'project1', + 'project2', + 'project3', + ]), + }, + nodes: graphNodes, + }; + const projectNodes = [1, 2, 3, 4].map( + (n) => projectGraph.nodes[`project${n}`] + ); + const result = sortProjectsTopologically(projectGraph, projectNodes); + expect(result).toEqual( + [1, 2, 3, 4].map((n) => projectGraph.nodes[`project${n}`]) + ); + }); }); }); + +function staticDependencies( + source: string, + targets: string[] +): StaticDependency[] { + return targets.map((target) => { + return { + source, + target, + type: DependencyType.static, + }; + }); +}