UNPKG

archunit

Version:

ArchUnit TypeScript is an architecture testing library, to specify and assert architecture rules in your TypeScript app

190 lines 7.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const os = __importStar(require("os")); const path = __importStar(require("path")); const import_kinds_1 = require("../common/util/import-kinds"); const graph_reporter_1 = require("./graph-reporter"); const graph = [ { source: 'src/app/controller.ts', target: 'src/domain/service.ts', external: false, importKinds: [import_kinds_1.ImportKind.NAMED], }, { source: 'src/app/controller.ts', target: 'src/domain/service.ts', external: false, importKinds: [import_kinds_1.ImportKind.TYPE], }, { source: 'src/domain/service.ts', target: 'src/infra/repository.ts', external: false, importKinds: [import_kinds_1.ImportKind.DEFAULT], }, { source: 'src/app/controller.ts', target: 'src/infra/repository.ts', external: false, importKinds: [import_kinds_1.ImportKind.DEFAULT], }, { source: 'src/infra/repository.ts', target: 'src/infra/repository.ts', external: false, importKinds: [], }, { source: 'src/app/controller.ts', target: 'node_modules/react/index.d.ts', external: true, importKinds: [import_kinds_1.ImportKind.DEFAULT], }, ]; describe('GraphReporter', () => { it('aggregates duplicate edges and excludes self/external edges by default', () => { const snapshot = graph_reporter_1.GraphReporter.createSnapshot(graph); expect(snapshot.summary.nodeCount).toBe(3); expect(snapshot.summary.edgeCount).toBe(3); expect(snapshot.summary.rawEdgeCount).toBe(4); expect(snapshot.summary.externalEdgeCount).toBe(0); expect(snapshot.edges).toContainEqual({ source: 'src/app/controller.ts', target: 'src/domain/service.ts', count: 2, external: false, importKinds: ['named', 'type'], }); }); it('can include external dependencies when requested', () => { const snapshot = graph_reporter_1.GraphReporter.createSnapshot(graph, { includeExternalDependencies: true, }); expect(snapshot.summary.externalEdgeCount).toBe(1); expect(snapshot.edges).toContainEqual({ source: 'src/app/controller.ts', target: 'node_modules/react/index.d.ts', count: 1, external: true, importKinds: ['default'], }); }); it('focuses on matching nodes and configurable neighbor depth', () => { const focused = graph_reporter_1.GraphReporter.createSnapshot(graph, { focus: 'src/domain/**', focusDepth: 0, }); expect(focused.nodes.map((node) => node.label)).toEqual([ 'src/domain/service.ts', ]); expect(focused.edges).toEqual([]); const withNeighbors = graph_reporter_1.GraphReporter.createSnapshot(graph, { focus: 'src/domain/**', focusDepth: 1, }); expect(withNeighbors.nodes.map((node) => node.label)).toEqual([ 'src/app/controller.ts', 'src/domain/service.ts', 'src/infra/repository.ts', ]); expect(withNeighbors.summary.edgeCount).toBe(3); }); it('filters to reachable dependencies and dependents', () => { const reachable = graph_reporter_1.GraphReporter.createSnapshot(graph, { reachableFrom: 'src/domain/**', }); expect(reachable.nodes.map((node) => node.label)).toEqual([ 'src/domain/service.ts', 'src/infra/repository.ts', ]); expect(reachable.edges).toHaveLength(1); const dependents = graph_reporter_1.GraphReporter.createSnapshot(graph, { dependentsOf: 'src/infra/**', }); expect(dependents.nodes.map((node) => node.label)).toEqual([ 'src/app/controller.ts', 'src/domain/service.ts', 'src/infra/repository.ts', ]); expect(dependents.summary.edgeCount).toBe(3); }); it('collapses nodes to folder depth before aggregating edges', () => { const snapshot = graph_reporter_1.GraphReporter.createSnapshot(graph, { collapse: { type: 'folder-depth', depth: 2, }, }); expect(snapshot.nodes.map((node) => node.label)).toEqual([ 'src/app', 'src/domain', 'src/infra', ]); expect(snapshot.edges).toContainEqual({ source: 'src/app', target: 'src/domain', count: 2, external: false, importKinds: ['named', 'type'], }); }); it('renders supported text formats', () => { const mermaid = graph_reporter_1.GraphReporter.toMermaid(graph); const dot = graph_reporter_1.GraphReporter.toDOT(graph); const d2 = graph_reporter_1.GraphReporter.toD2(graph); const csv = graph_reporter_1.GraphReporter.toCSV(graph); const json = graph_reporter_1.GraphReporter.toJSON(graph); const html = graph_reporter_1.GraphReporter.toHTML(graph, { title: 'Architecture Report' }); expect(mermaid).toContain('flowchart LR'); expect(mermaid).toContain('|2|'); expect(dot).toContain('digraph dependencies'); expect(dot).toContain('"src/app/controller.ts" -> "src/domain/service.ts"'); expect(d2).toContain('"src/app/controller.ts" -> "src/domain/service.ts"'); expect(csv.split('\n')[0]).toBe('source,target,count,external,importKinds'); expect(JSON.parse(json).summary.edgeCount).toBe(3); expect(html).toContain('<title>Architecture Report</title>'); expect(html).toContain('Generated by ArchUnitTS graph reporting'); }); it('writes reports to disk', async () => { const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'archunit-graph-')); const outputPath = path.join(dir, 'dependencies.mmd'); await graph_reporter_1.GraphReporter.exportAsMermaid(graph, outputPath); expect(fs.readFileSync(outputPath, 'utf8')).toContain('flowchart LR'); }); }); //# sourceMappingURL=graph-reporter.spec.js.map