UNPKG

archunit

Version:

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

239 lines 11.4 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const path_1 = __importDefault(require("path")); const __1 = require("../.."); describe('Count metrics integration test', () => { const mockProjectPath = path_1.default.join(__dirname, 'mock-project', 'tsconfig.json'); describe('Class-level count metrics', () => { it('should count methods in classes correctly', async () => { const violations = await (0, __1.metrics)(mockProjectPath) .forClassesMatching(/.*Base.*/) .count() .methodCount() .shouldBeBelow(10) .check(); expect(violations.length).toBe(0); }); it('should count fields in classes correctly', async () => { const rule = (0, __1.metrics)(mockProjectPath) .forClassesMatching(/.*Data.*/) .count() .fieldCount() .shouldBe(3); await expect(rule).toPassAsync(); }); it('should validate method count with different comparison operators', async () => { // Test shouldBeAbove const aboveViolations = await (0, __1.metrics)(mockProjectPath) .count() .methodCount() .shouldBeAbove(0) // All classes should have at least 1 method .check(); expect(aboveViolations).toBeDefined(); // Test shouldBe (equal) const exactViolations = await (0, __1.metrics)(mockProjectPath) .count() .methodCount() .shouldBe(5) // Look for classes with exactly 5 methods .check(); expect(exactViolations).toBeDefined(); // Test shouldBeAboveOrEqual const aboveOrEqualViolations = await (0, __1.metrics)(mockProjectPath) .count() .methodCount() .shouldBeAboveOrEqual(1) // All classes should have at least 1 method .check(); expect(aboveOrEqualViolations).toBeDefined(); }); }); describe('File-level count metrics', () => { it('should count lines of code per file correctly', async () => { // Test that files don't exceed reasonable line counts const violations = await (0, __1.metrics)(mockProjectPath) .count() .linesOfCode() .shouldBeBelow(200) // Files shouldn't be too large .check(); expect(violations).toBeDefined(); }); it('should count statements per file correctly', async () => { // Test that files have reasonable statement counts const violations = await (0, __1.metrics)(mockProjectPath) .count() .statements() .shouldBeBelow(100) // Files shouldn't have too many statements .check(); expect(violations).toBeDefined(); }); it('should count imports per file correctly', async () => { // Test that files don't import too many modules const violations = await (0, __1.metrics)(mockProjectPath) .count() .imports() .shouldBeBelow(20) // Files shouldn't import too many modules .check(); expect(violations).toBeDefined(); }); it('should count classes per file correctly', async () => { // Test single class per file principle const violations = await (0, __1.metrics)(mockProjectPath) .count() .classes() .shouldBeBelowOrEqual(1) // Each file should have at most 1 class .check(); expect(violations).toBeDefined(); }); it('should count interfaces per file correctly', async () => { // Test interface count per file const violations = await (0, __1.metrics)(mockProjectPath) .count() .interfaces() .shouldBeBelow(5) // Files shouldn't have too many interfaces .check(); expect(violations).toBeDefined(); }); it('should count functions per file correctly', async () => { // Test function count per file const violations = await (0, __1.metrics)(mockProjectPath) .count() .functions() .shouldBeBelow(10) // Files shouldn't have too many top-level functions .check(); expect(violations).toBeDefined(); }); it('should validate file metrics with different comparison operators', async () => { // Test shouldBeBelowOrEqual const belowOrEqualViolations = await (0, __1.metrics)(mockProjectPath) .count() .linesOfCode() .shouldBeBelowOrEqual(300) // Files should have at most 300 lines .check(); expect(belowOrEqualViolations).toBeDefined(); // Test shouldBeAbove for lines of code const aboveViolations = await (0, __1.metrics)(mockProjectPath) .count() .linesOfCode() .shouldBeAbove(5) // Files should have more than 5 lines .check(); expect(aboveViolations).toBeDefined(); }); }); // Just smoke tests! describe('Project-wide count metrics summary', () => { it('should calculate comprehensive project metrics', async () => { // Get comprehensive project summary const summary = await (0, __1.metrics)(mockProjectPath).count().summary(); // Verify we have valid project metrics expect(summary).toBeDefined(); expect(summary.totalFiles).toBeGreaterThan(0); expect(summary.totalClasses).toBeGreaterThanOrEqual(0); expect(summary.averageMethodsPerClass).toBeGreaterThanOrEqual(0); expect(summary.averageFieldsPerClass).toBeGreaterThanOrEqual(0); expect(summary.averageLinesOfCodePerFile).toBeGreaterThan(0); expect(summary.averageStatementsPerFile).toBeGreaterThanOrEqual(0); expect(summary.averageImportsPerFile).toBeGreaterThanOrEqual(0); // Verify largest file/class tracking expect(summary.largestFile).toBeDefined(); expect(summary.largestFile.path).toBeDefined(); expect(summary.largestFile.lines).toBeGreaterThan(0); expect(summary.largestClass).toBeDefined(); expect(summary.largestClass.name).toBeDefined(); expect(summary.largestClass.methods).toBeGreaterThanOrEqual(0); console.log('Count Metrics Summary:', { totalFiles: summary.totalFiles, totalClasses: summary.totalClasses, averageMethodsPerClass: summary.averageMethodsPerClass.toFixed(2), averageFieldsPerClass: summary.averageFieldsPerClass.toFixed(2), averageLinesOfCodePerFile: summary.averageLinesOfCodePerFile.toFixed(2), largestFile: `${summary.largestFile.path} (${summary.largestFile.lines} lines)`, largestClass: `${summary.largestClass.name} (${summary.largestClass.methods} methods)`, }); }); }); describe('Count metrics with filtering', () => { it('should apply file folder filtering correctly', async () => { // Test folder-based filtering (though our mock project is flat) const violations = await (0, __1.metrics)(mockProjectPath) .inFolder('.') .count() .linesOfCode() .shouldBeBelow(500) .check(); expect(violations).toBeDefined(); }); it('should apply class pattern filtering correctly', async () => { // Test class pattern filtering const serviceViolations = await (0, __1.metrics)(mockProjectPath) .forClassesMatching(/.*Service.*/) .count() .methodCount() .shouldBeBelow(20) .check(); expect(serviceViolations).toBeDefined(); // Test negative pattern filtering (exclude certain classes) const nonDataViolations = await (0, __1.metrics)(mockProjectPath) .forClassesMatching(/^(?!.*Data).*$/) // Exclude classes with 'Data' in name .count() .fieldCount() .shouldBeBelow(10) .check(); expect(nonDataViolations).toBeDefined(); }); }); describe('Count metrics error handling', () => { it('should handle missing threshold gracefully', async () => { // This should throw an error because no threshold is set const builder = (0, __1.metrics)(mockProjectPath).count().methodCount(); await expect(builder.check()).rejects.toThrow('Threshold and comparison must be set before checking'); }); it('should handle invalid file paths gracefully', async () => { // Test with non-existent tsconfig const invalidPath = path_1.default.join(__dirname, 'non-existent', 'tsconfig.json'); await expect(async () => { await (0, __1.metrics)(invalidPath) .count() .linesOfCode() .shouldBeBelow(100) .check(); }).rejects.toThrow(); }); }); describe('Count metrics violation messages', () => { it('should generate meaningful violation messages', async () => { // Force some violations by setting very low thresholds const violations = await (0, __1.metrics)(mockProjectPath) .count() .linesOfCode() .shouldBeBelow(1) // This should generate violations .check(); expect(violations.length).toBeGreaterThan(0); // if (violations.length > 0) { // // Check that violation messages are meaningful // violations.forEach((violation) => { // expect(violation.toString()).toContain('LinesOfCode'); // expect(violation.toString()).toContain('should be below'); // expect(violation.toString()).toMatch(/\d+/); // Should contain numbers // }); // } }); }); // it('should not have huge files', async () => { // const rule = metrics().count().linesOfCode().shouldBeBelow(2000); // // is expected to fail // //await expect(rule).toPassAsync(); // const violations = await rule.check(); // expect(violations).toHaveLength(1); // }); it('should limit methods per component class', async () => { const rule = (0, __1.metrics)(mockProjectPath) .withName('*.file.ts') .count() .methodCount() .shouldBeBelow(15); await expect(rule).toPassAsync(); }); }); //# sourceMappingURL=count-integration.spec.js.map