Skip to main content
Glama

Claude Desktop Commander MCP

run-all-tests.js8.59 kB
/** * Main test runner script * Runs all test modules and provides comprehensive summary */ import { spawn } from 'child_process'; import path from 'path'; import fs from 'fs/promises'; import { fileURLToPath } from 'url'; // Get directory name const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Colors for console output const colors = { reset: '\x1b[0m', green: '\x1b[32m', red: '\x1b[31m', yellow: '\x1b[33m', blue: '\x1b[34m', cyan: '\x1b[36m', magenta: '\x1b[35m', bold: '\x1b[1m' }; /** * Run a command and return its output */ function runCommand(command, args, cwd = __dirname) { return new Promise((resolve, reject) => { console.log(`${colors.blue}Running command: ${command} ${args.join(' ')}${colors.reset}`); const proc = spawn(command, args, { cwd, stdio: 'inherit', shell: true }); proc.on('close', (code) => { if (code === 0) { resolve(); } else { reject(new Error(`Command failed with exit code ${code}`)); } }); proc.on('error', (err) => { reject(err); }); }); } /** * Run a single Node.js test file as a subprocess */ function runTestFile(testFile) { return new Promise((resolve) => { console.log(`\n${colors.cyan}Running test module: ${testFile}${colors.reset}`); const startTime = Date.now(); const proc = spawn('node', [testFile], { cwd: __dirname, stdio: 'inherit', shell: false }); proc.on('close', (code) => { const duration = Date.now() - startTime; if (code === 0) { console.log(`${colors.green}✓ Test passed: ${testFile} (${duration}ms)${colors.reset}`); resolve({ success: true, file: testFile, duration, exitCode: code }); } else { console.error(`${colors.red}✗ Test failed: ${testFile} (${duration}ms) - Exit code: ${code}${colors.reset}`); resolve({ success: false, file: testFile, duration, exitCode: code }); } }); proc.on('error', (err) => { const duration = Date.now() - startTime; console.error(`${colors.red}✗ Error running ${testFile}: ${err.message}${colors.reset}`); resolve({ success: false, file: testFile, duration, error: err.message }); }); }); } /** * Build the project */ async function buildProject() { console.log(`\n${colors.cyan}===== Building project =====${colors.reset}\n`); await runCommand('npm', ['run', 'build']); } /** * Discover and run all test modules */ async function runTestModules() { console.log(`\n${colors.cyan}===== Running tests =====${colors.reset}\n`); // Discover all test files let testFiles = []; try { const files = await fs.readdir(__dirname); // Get all test files, starting with 'test' and ending with '.js' const discoveredTests = files .filter(file => file.startsWith('test') && file.endsWith('.js') && file !== 'run-all-tests.js') .sort(); // Sort for consistent order // Ensure main test.js runs first if it exists if (discoveredTests.includes('test.js')) { testFiles.push('./test.js'); discoveredTests.splice(discoveredTests.indexOf('test.js'), 1); } // Add remaining tests testFiles.push(...discoveredTests.map(file => `./${file}`)); } catch (error) { console.error(`${colors.red}Error: Could not scan test directory: ${error.message}${colors.reset}`); process.exit(1); } if (testFiles.length === 0) { console.warn(`${colors.yellow}Warning: No test files found${colors.reset}`); return { success: true, results: [] }; } console.log(`${colors.blue}Found ${testFiles.length} test files:${colors.reset}`); testFiles.forEach(file => console.log(` - ${file}`)); console.log(''); // Results tracking const results = []; let totalDuration = 0; // Run each test file for (const testFile of testFiles) { const result = await runTestFile(testFile); results.push(result); totalDuration += result.duration || 0; } // Calculate summary statistics const passed = results.filter(r => r.success).length; const failed = results.filter(r => !r.success).length; const failedTests = results.filter(r => !r.success); // Print detailed summary console.log(`\n${colors.bold}${colors.cyan}===== TEST SUMMARY =====${colors.reset}\n`); // Overall stats console.log(`${colors.bold}Overall Results:${colors.reset}`); console.log(` Total tests: ${passed + failed}`); console.log(` ${colors.green}✓ Passed: ${passed}${colors.reset}`); console.log(` ${failed > 0 ? colors.red : colors.green}✗ Failed: ${failed}${colors.reset}`); console.log(` Total duration: ${totalDuration}ms (${(totalDuration / 1000).toFixed(1)}s)`); // Failed tests details if (failed > 0) { console.log(`\n${colors.red}${colors.bold}Failed Tests:${colors.reset}`); failedTests.forEach(test => { console.log(` ${colors.red}✗ ${test.file}${colors.reset}`); if (test.exitCode !== undefined) { console.log(` Exit code: ${test.exitCode}`); } if (test.error) { console.log(` Error: ${test.error}`); } }); } // Test performance summary if (results.length > 0) { console.log(`\n${colors.bold}Performance Summary:${colors.reset}`); const avgDuration = totalDuration / results.length; const slowestTest = results.reduce((prev, current) => (current.duration || 0) > (prev.duration || 0) ? current : prev ); const fastestTest = results.reduce((prev, current) => (current.duration || 0) < (prev.duration || 0) ? current : prev ); console.log(` Average test duration: ${avgDuration.toFixed(0)}ms`); console.log(` Fastest test: ${fastestTest.file} (${fastestTest.duration || 0}ms)`); console.log(` Slowest test: ${slowestTest.file} (${slowestTest.duration || 0}ms)`); } // Final status if (failed === 0) { console.log(`\n${colors.green}${colors.bold}🎉 ALL TESTS PASSED! 🎉${colors.reset}`); console.log(`${colors.green}All ${passed} tests completed successfully.${colors.reset}`); } else { console.log(`\n${colors.red}${colors.bold}❌ TESTS FAILED ❌${colors.reset}`); console.log(`${colors.red}${failed} out of ${passed + failed} tests failed.${colors.reset}`); } console.log(`\n${colors.cyan}===== Test run completed =====${colors.reset}\n`); return { success: failed === 0, results, summary: { total: passed + failed, passed, failed, duration: totalDuration } }; } /** * Main function */ async function main() { const overallStartTime = Date.now(); try { console.log(`${colors.bold}${colors.cyan}===== DESKTOP COMMANDER TEST RUNNER =====${colors.reset}`); console.log(`${colors.blue}Starting test execution at ${new Date().toISOString()}${colors.reset}\n`); // Build the project first await buildProject(); // Run all test modules const testResult = await runTestModules(); // Final timing const overallDuration = Date.now() - overallStartTime; console.log(`${colors.blue}Total execution time: ${overallDuration}ms (${(overallDuration / 1000).toFixed(1)}s)${colors.reset}`); // Exit with appropriate code process.exit(testResult.success ? 0 : 1); } catch (error) { console.error(`\n${colors.red}${colors.bold}FATAL ERROR:${colors.reset}`); console.error(`${colors.red}${error.message}${colors.reset}`); if (error.stack) { console.error(`${colors.red}${error.stack}${colors.reset}`); } process.exit(1); } } // Handle uncaught errors gracefully process.on('uncaughtException', (error) => { console.error(`\n${colors.red}${colors.bold}UNCAUGHT EXCEPTION:${colors.reset}`); console.error(`${colors.red}${error.message}${colors.reset}`); if (error.stack) { console.error(`${colors.red}${error.stack}${colors.reset}`); } process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { console.error(`\n${colors.red}${colors.bold}UNHANDLED REJECTION:${colors.reset}`); console.error(`${colors.red}${reason}${colors.reset}`); process.exit(1); }); // Run the main function main().catch(error => { console.error(`\n${colors.red}${colors.bold}MAIN FUNCTION ERROR:${colors.reset}`); console.error(`${colors.red}${error.message}${colors.reset}`); if (error.stack) { console.error(`${colors.red}${error.stack}${colors.reset}`); } process.exit(1); });

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/wonderwhy-er/DesktopCommanderMCP'

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