Skip to main content
Glama

CTS MCP Server

by EricA1019
integration.test.ts9.28 kB
/** * Cleanup Tool Integration Tests * * Tests for MCP wrapper, strategy execution, and safety integration. */ import { describe, it, expect, beforeEach, afterEach } from '@jest/globals'; import { createCleanupHandler, cleanupTool } from '../index'; import { mkdir, writeFile, rm } from 'fs/promises'; import { join } from 'path'; import { existsSync } from 'fs'; const TEST_PROJECT = '/tmp/cleanup-integration-test'; describe('Cleanup Tool Integration', () => { beforeEach(async () => { // Clean up test directory if (existsSync(TEST_PROJECT)) { await rm(TEST_PROJECT, { recursive: true, force: true }); } await mkdir(TEST_PROJECT, { recursive: true }); }); afterEach(async () => { // Clean up after tests if (existsSync(TEST_PROJECT)) { await rm(TEST_PROJECT, { recursive: true, force: true }); } }); describe('Tool Definition', () => { it('should have valid tool definition', () => { expect(cleanupTool.name).toBe('CTS_Cleanup'); expect(cleanupTool.description).toBeTruthy(); expect(cleanupTool.inputSchema.type).toBe('object'); expect(cleanupTool.inputSchema.properties.projectPath).toBeDefined(); }); it('should list all parameters', () => { const props = cleanupTool.inputSchema.properties; expect(props.projectPath).toBeDefined(); expect(props.strategies).toBeDefined(); expect(props.dryRun).toBeDefined(); expect(props.requireCleanGit).toBeDefined(); expect(props.exclusions).toBeDefined(); expect(props.maxActions).toBeDefined(); }); it('should have correct required fields', () => { const required = cleanupTool.inputSchema.required; expect(required).toContain('projectPath'); }); }); describe('Parameter Validation', () => { it('should reject empty project path', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: '' }); expect(result.success).toBe(false); expect(result.error?.code).toBe(-32602); }); it('should accept valid parameters', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, dryRun: true, requireCleanGit: false, }); expect(result.success).toBe(true); }); it('should use default values', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, requireCleanGit: false, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.mode).toBe('preview'); // dryRun defaults to true }); it('should validate strategy names', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['dead_code', 'duplicates'], requireCleanGit: false, }); expect(result.success).toBe(true); }); }); describe('Safety Integration', () => { it('should include safety report in output', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.safetyReport).toBeTruthy(); expect(res.safetyReport).toContain('Safety Pre-Flight Checks'); }); it('should run in dry-run mode by default', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, requireCleanGit: false, }); const res: any = result.result; expect(res.mode).toBe('preview'); expect(res.safetyReport).toContain('DRY RUN'); }); }); describe('Dead Code Strategy', () => { it('should detect unused imports', async () => { const handler = createCleanupHandler(); // Create file with unused import const gdFile = join(TEST_PROJECT, 'test.gd'); await writeFile( gdFile, `const UnusedClass = preload("res://unused.gd") extends Node func _ready(): print("hello") ` ); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['dead_code'], requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.actions.length).toBeGreaterThan(0); expect(res.actions[0].type).toBe('remove_unused_imports'); }); it('should not flag used imports', async () => { const handler = createCleanupHandler(); // Create file with used import const gdFile = join(TEST_PROJECT, 'test.gd'); await writeFile( gdFile, `const MyClass = preload("res://my_class.gd") extends Node func _ready(): var instance = MyClass.new() ` ); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['dead_code'], requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.actions.length).toBe(0); }); }); describe('Duplicate Strategy', () => { it('should detect duplicate files', async () => { const handler = createCleanupHandler(); // Create identical files const file1 = join(TEST_PROJECT, 'file1.txt'); const file2 = join(TEST_PROJECT, 'file2.txt'); await writeFile(file1, 'identical content'); await writeFile(file2, 'identical content'); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['duplicates'], requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.actions.length).toBeGreaterThan(0); expect(res.actions[0].type).toBe('duplicate_files'); expect(res.actions[0].files?.length).toBe(2); }); it('should not flag unique files', async () => { const handler = createCleanupHandler(); // Create different files const file1 = join(TEST_PROJECT, 'file1.txt'); const file2 = join(TEST_PROJECT, 'file2.txt'); await writeFile(file1, 'content A'); await writeFile(file2, 'content B'); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['duplicates'], requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.actions.length).toBe(0); }); }); describe('Summary Statistics', () => { it('should include action summary', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.summary).toBeDefined(); expect(res.summary.totalActions).toBeDefined(); expect(res.summary.byType).toBeDefined(); }); it('should respect maxActions limit', async () => { const handler = createCleanupHandler(); // Create many duplicate files (all identical) for (let i = 0; i < 10; i++) { await writeFile(join(TEST_PROJECT, `dup${i}.txt`), 'duplicate'); } const result = await handler({ projectPath: TEST_PROJECT, strategies: ['duplicates'], maxActions: 1, // Limit to 1 action requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.actions.length).toBe(1); // Should be limited expect(res.summary.returnedActions).toBe(1); }); it('should track performance metrics', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, requireCleanGit: false, dryRun: true, }); expect(result.success).toBe(true); const res: any = result.result; expect(res.performanceMs).toBeDefined(); expect(typeof res.performanceMs).toBe('number'); expect(res.performanceMs).toBeGreaterThanOrEqual(0); }); }); describe('Error Handling', () => { it('should handle invalid strategy names gracefully', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: TEST_PROJECT, strategies: ['dead_code'], requireCleanGit: false, }); // Should succeed even if some strategies don't exist expect(result.success).toBe(true); }); it('should handle nonexistent project path', async () => { const handler = createCleanupHandler(); const result = await handler({ projectPath: '/nonexistent/path/12345', requireCleanGit: false, dryRun: true, }); // Should fail during safety validation or execution expect(result.success).toBeDefined(); }); }); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/EricA1019/CTS_MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server