ruvector/tests/run-tests.js
copilot-swe-agent[bot] 7e3802e43e Add test validation and comprehensive test runner
Co-authored-by: ruvnet <2934394+ruvnet@users.noreply.github.com>
2026-01-29 15:59:55 +00:00

234 lines
6.7 KiB
JavaScript
Executable file
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* MCP Test Suite Runner
*
* Runs all MCP-related tests and provides a comprehensive report
* This can run without the MCP server for validation purposes
*/
const fs = require('fs');
const path = require('path');
// ANSI color codes
const colors = {
reset: '\x1b[0m',
green: '\x1b[32m',
red: '\x1b[31m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
cyan: '\x1b[36m',
gray: '\x1b[90m'
};
function log(msg, color = 'reset') {
console.log(colors[color] + msg + colors.reset);
}
function header(msg) {
console.log('\n' + '='.repeat(70));
log(msg, 'cyan');
console.log('='.repeat(70));
}
function section(msg) {
console.log('\n' + '-'.repeat(70));
log(msg, 'blue');
console.log('-'.repeat(70));
}
async function runTests() {
header('🧪 RuVector MCP Test Suite');
const results = {
passed: 0,
failed: 0,
skipped: 0,
warnings: 0
};
// Test 1: File existence
section('Test 1: File Structure Validation');
const requiredFiles = {
'tests/mcp-demo.js': 'Full MCP demo script',
'tests/mcp-simple-test.js': 'Simple MCP test script',
'tests/MCP_TESTS.md': 'MCP tests documentation',
'tests/QUICKSTART.md': 'Quick start guide',
'tests/validate-tests.js': 'Test validation script'
};
for (const [file, desc] of Object.entries(requiredFiles)) {
const exists = fs.existsSync(file);
if (exists) {
const stats = fs.statSync(file);
log(`${file} - ${desc} (${Math.round(stats.size / 1024)}KB)`, 'green');
results.passed++;
} else {
log(`${file} - NOT FOUND`, 'red');
results.failed++;
}
}
// Test 2: Module loading
section('Test 2: Module Loading');
try {
const { SimpleMCPClient, generateEmbedding } = require(path.join(__dirname, 'mcp-simple-test.js'));
log(' ✅ mcp-simple-test.js module loads correctly', 'green');
results.passed++;
// Test embedding generation
const embedding = generateEmbedding(128, 1);
if (embedding.length === 128) {
log(' ✅ generateEmbedding() produces correct dimensions', 'green');
results.passed++;
} else {
log(' ❌ generateEmbedding() dimension mismatch', 'red');
results.failed++;
}
// Test embedding normalization
const magnitude = Math.sqrt(embedding.reduce((sum, v) => sum + v * v, 0));
if (Math.abs(magnitude - 1.0) < 0.0001) {
log(' ✅ Embeddings are properly normalized', 'green');
results.passed++;
} else {
log(` ⚠️ Embedding normalization: ${magnitude.toFixed(4)} (expected 1.0)`, 'yellow');
results.warnings++;
}
} catch (error) {
log(` ❌ Module loading failed: ${error.message}`, 'red');
results.failed++;
}
// Test 3: MCP SDK availability
section('Test 3: Dependencies Check');
try {
require('@modelcontextprotocol/sdk/client/index.js');
log(' ✅ @modelcontextprotocol/sdk is installed', 'green');
results.passed++;
} catch (error) {
log(' ⚠️ @modelcontextprotocol/sdk not installed (optional for simple test)', 'yellow');
log(' Install with: npm install @modelcontextprotocol/sdk', 'gray');
results.warnings++;
}
// Test 4: MCP server binary
section('Test 4: MCP Server Binary Check');
const serverPaths = [
'./target/release/ruvector-mcp',
'./target/debug/ruvector-mcp'
];
let serverFound = false;
for (const serverPath of serverPaths) {
if (fs.existsSync(serverPath)) {
const stats = fs.statSync(serverPath);
log(` ✅ MCP server found: ${serverPath} (${Math.round(stats.size / 1024 / 1024)}MB)`, 'green');
serverFound = true;
results.passed++;
break;
}
}
if (!serverFound) {
log(' ⚠️ MCP server binary not found', 'yellow');
log(' Build with: cargo build --release -p ruvector-cli --bin ruvector-mcp', 'gray');
results.warnings++;
}
// Test 5: Documentation quality
section('Test 5: Documentation Quality');
const docs = ['tests/MCP_TESTS.md', 'tests/QUICKSTART.md'];
for (const doc of docs) {
try {
const content = fs.readFileSync(doc, 'utf8');
const checks = [
{ name: 'Has code examples', test: () => content.includes('```') },
{ name: 'Has usage section', test: () => content.toLowerCase().includes('usage') },
{ name: 'Mentions MCP', test: () => content.toLowerCase().includes('mcp') },
{ name: 'Has links', test: () => content.includes('[') && content.includes(']') }
];
let docPassed = true;
for (const check of checks) {
if (!check.test()) {
log(` ⚠️ ${doc}: Missing ${check.name}`, 'yellow');
results.warnings++;
docPassed = false;
}
}
if (docPassed) {
log(`${doc} - Complete documentation`, 'green');
results.passed++;
}
} catch (error) {
log(`${doc}: Error reading file`, 'red');
results.failed++;
}
}
// Test 6: Script executability
section('Test 6: Script Permissions');
const scripts = ['tests/mcp-demo.js', 'tests/mcp-simple-test.js', 'tests/validate-tests.js'];
for (const script of scripts) {
try {
fs.accessSync(script, fs.constants.X_OK);
log(`${script} - Executable`, 'green');
results.passed++;
} catch (error) {
log(` ⚠️ ${script} - Not executable (chmod +x ${script})`, 'yellow');
results.warnings++;
}
}
// Summary
header('📊 Test Summary');
const total = results.passed + results.failed + results.skipped;
const passRate = total > 0 ? ((results.passed / total) * 100).toFixed(1) : 0;
console.log('');
log(` Total Tests: ${total}`, 'cyan');
log(` ✅ Passed: ${results.passed}`, 'green');
log(` ❌ Failed: ${results.failed}`, 'red');
log(` ⏭️ Skipped: ${results.skipped}`, 'gray');
log(` ⚠️ Warnings: ${results.warnings}`, 'yellow');
log(` 📈 Pass Rate: ${passRate}%`, passRate >= 80 ? 'green' : 'yellow');
console.log('');
console.log('='.repeat(70));
if (results.failed === 0) {
log('\n✅ All tests passed!', 'green');
console.log('');
log('Next steps:', 'cyan');
console.log(' 1. Build MCP server: cargo build --release -p ruvector-cli --bin ruvector-mcp');
console.log(' 2. Run simple test: node tests/mcp-simple-test.js');
console.log(' 3. Run full demo: node tests/mcp-demo.js');
console.log('');
return 0;
} else {
log('\n⚠ Some tests failed. Please review the output above.', 'yellow');
console.log('');
return 1;
}
}
// Run tests
if (require.main === module) {
runTests().then(code => {
process.exit(code);
}).catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});
}
module.exports = { runTests };