Skip to main content
Glama
noelserdna

CV Recruitment Assistant

by noelserdna
run-tests.js11.8 kB
#!/usr/bin/env node /** * Test Runner para CV MCP Tools * Ejecuta todos los tests de manera ordenada y genera reportes */ const fs = require('fs'); const path = require('path'); // Colors para la consola const colors = { reset: '\x1b[0m', bright: '\x1b[1m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m' }; function colorize(text, color) { return `${colors[color]}${text}${colors.reset}`; } function printHeader() { console.log(colorize('=' * 60, 'cyan')); console.log(colorize('🧪 CV MCP TOOLS - BATERÍA DE TESTS', 'cyan')); console.log(colorize(' Sistema de Reclutamiento para Brayan Smith Cordova Tasayco', 'blue')); console.log(colorize('=' * 60, 'cyan')); console.log(); } function printSeparator(title) { console.log(colorize(`\n${'─'.repeat(40)}`, 'yellow')); console.log(colorize(`${title}`, 'yellow')); console.log(colorize(`${'─'.repeat(40)}`, 'yellow')); } async function validateDataFiles() { printSeparator('📁 VALIDANDO ARCHIVOS DE DATOS'); const requiredFiles = [ 'src/candidate-data.json', 'src/index.ts' ]; let allFilesExist = true; for (const file of requiredFiles) { const filePath = path.join(process.cwd(), file); if (fs.existsSync(filePath)) { console.log(colorize(`✅ ${file}`, 'green')); } else { console.log(colorize(`❌ ${file} - ARCHIVO NO ENCONTRADO`, 'red')); allFilesExist = false; } } // Validar JSON try { const candidateDataPath = path.join(process.cwd(), 'src/candidate-data.json'); if (fs.existsSync(candidateDataPath)) { const data = JSON.parse(fs.readFileSync(candidateDataPath, 'utf8')); // Validar estructura básica const requiredSections = ['personal', 'workExperience', 'education', 'certifications', 'skills']; let validStructure = true; for (const section of requiredSections) { if (!data[section]) { console.log(colorize(`❌ Sección faltante en JSON: ${section}`, 'red')); validStructure = false; } } if (validStructure) { console.log(colorize('✅ Estructura JSON válida', 'green')); } else { allFilesExist = false; } } } catch (error) { console.log(colorize(`❌ Error validando JSON: ${error.message}`, 'red')); allFilesExist = false; } return allFilesExist; } async function runMCPTests() { printSeparator('🔧 EJECUTANDO TESTS MCP'); try { // Importar y ejecutar los tests principales const { runTests } = require('./mcp-tools.test.js'); await runTests(); return true; } catch (error) { console.log(colorize(`❌ Error ejecutando tests MCP: ${error.message}`, 'red')); return false; } } async function runCryptoTests() { printSeparator('🔐 TESTS DE FIRMA DIGITAL'); console.log(colorize('🔑 Validando sistema de firmas digitales...', 'blue')); try { const { TestMCPAgent } = require('./mcp-tools.test.js'); const agent = new TestMCPAgent(); await agent.init(); console.log('\n📝 Verificando que todas las respuestas estén firmadas...'); // Lista de todas las herramientas que deben devolver respuestas firmadas const tools = [ 'get_candidate_profile', 'get_work_experience', 'get_education_background', 'get_certifications', 'get_technical_skills', 'get_soft_skills', 'get_languages_interests', 'get_portfolio_website', 'get_github_profile', 'get_social_networks' ]; let allToolsSigned = true; for (const toolName of tools) { try { const response = await agent.server.callTool(toolName); const responseText = response.content[0].text; const parsedResponse = JSON.parse(responseText); // Verificar que tenga todos los campos de firma digital const requiredFields = ['data', 'hash', 'signature', 'timestamp', 'publicKey', 'serverId', 'version']; const hasAllFields = requiredFields.every(field => Object.hasOwn(parsedResponse, field)); if (hasAllFields) { console.log(` ✅ ${toolName}: Respuesta firmada correctamente`); } else { console.log(` ❌ ${toolName}: Faltan campos de firma digital`); allToolsSigned = false; } } catch (error) { console.log(` ❌ ${toolName}: Error - ${error.message}`); allToolsSigned = false; } } // Test de verificación de firma console.log('\n🔍 Probando herramienta de verificación...'); const profileResponse = await agent.server.callTool('get_candidate_profile'); const verifyResponse = await agent.server.callTool('verify_response_signature', { signedResponse: profileResponse.content[0].text }); const verifyData = JSON.parse(verifyResponse.content[0].text); if (verifyData.data.verificationStatus === 'VALID') { console.log(' ✅ Herramienta de verificación funciona correctamente'); } else { console.log(' ❌ Herramienta de verificación falló'); allToolsSigned = false; } if (allToolsSigned) { console.log(colorize('\n🔐 Sistema de firma digital validado exitosamente', 'green')); } else { console.log(colorize('\n❌ Fallos en el sistema de firma digital', 'red')); } return allToolsSigned; } catch (error) { console.log(colorize(`❌ Error en tests de criptografía: ${error.message}`, 'red')); return false; } } async function runIntegrationTests() { printSeparator('🌐 TESTS DE INTEGRACIÓN'); console.log(colorize('📋 Simulando escenarios reales de reclutamiento...', 'blue')); try { const { TestMCPAgent } = require('./mcp-tools.test.js'); const agent = new TestMCPAgent(); await agent.init(); // Escenario 1: Reclutador busca desarrollador React console.log('\n🎯 Escenario 1: Evaluación para puesto Frontend React Developer'); const reactEval = await agent.server.callTool('match_job_requirements', { jobTitle: 'React Frontend Developer', requiredSkills: ['React', 'JavaScript', 'HTML', 'CSS'], preferredSkills: ['TypeScript', 'Next.js', 'Tailwind CSS'] }); const reactData = JSON.parse(reactEval.content[0].text); console.log(` 💯 Compatibilidad: ${reactData.matchAnalysis.requiredSkillsMatch}`); console.log(` 🎨 Skills preferidos: ${reactData.matchAnalysis.preferredSkillsMatch}`); console.log(` 📊 Fit general: ${reactData.matchAnalysis.overallFit}`); // Escenario 2: Búsqueda de experiencia específica console.log('\n🎯 Escenario 2: Verificación de experiencia en liderazgo'); const leadershipEval = await agent.server.callTool('assess_leadership_experience'); const leadershipData = JSON.parse(leadershipEval.content[0].text); console.log(` 👥 Tiene experiencia de liderazgo: ${leadershipData.hasLeadershipExperience ? 'Sí' : 'No'}`); console.log(` ⏱️ Duración: ${leadershipData.leadershipDuration}`); // Escenario 3: Tech stack específico console.log('\n🎯 Escenario 3: Evaluación tech stack para startup moderna'); const techEval = await agent.server.callTool('evaluate_tech_stack', { requiredTechnologies: ['React', 'Node.js', 'MongoDB', 'Docker', 'AWS'] }); const techData = JSON.parse(techEval.content[0].text); console.log(` 🔧 Score de compatibilidad: ${techData.compatibilityScore}`); console.log(` ✅ Tecnologías que domina: ${techData.matchingTechnologies.join(', ')}`); console.log(` ❌ Tecnologías por aprender: ${techData.missingTechnologies.join(', ')}`); console.log(colorize('\n✨ Tests de integración completados exitosamente', 'green')); return true; } catch (error) { console.log(colorize(`❌ Error en tests de integración: ${error.message}`, 'red')); return false; } } async function generateReport(results) { printSeparator('📊 GENERANDO REPORTE'); const reportData = { timestamp: new Date().toISOString(), results: results, summary: { allPassed: results.validation && results.mcpTests && results.cryptoTests && results.integration, totalSteps: 4, passedSteps: Object.values(results).filter(Boolean).length } }; // Generar reporte en archivo const reportPath = path.join(__dirname, 'test-report.json'); fs.writeFileSync(reportPath, JSON.stringify(reportData, null, 2)); console.log(colorize(`📄 Reporte guardado en: ${reportPath}`, 'blue')); // Mostrar resumen final console.log(colorize('\n🏁 RESUMEN FINAL', 'magenta')); console.log(`📁 Validación de archivos: ${results.validation ? '✅' : '❌'}`); console.log(`🔧 Tests MCP: ${results.mcpTests ? '✅' : '❌'}`); console.log(`🔐 Tests firma digital: ${results.cryptoTests ? '✅' : '❌'}`); console.log(`🌐 Tests integración: ${results.integration ? '✅' : '❌'}`); if (reportData.summary.allPassed) { console.log(colorize('\n🎉 ¡TODOS LOS TESTS PASARON!', 'green')); console.log(colorize('✨ El sistema CV MCP está listo para producción', 'green')); } else { console.log(colorize(`\n⚠️ ${4 - reportData.summary.passedSteps} etapa(s) fallaron`, 'yellow')); console.log(colorize('🔧 Revisa los errores anteriores', 'yellow')); } return reportData.summary.allPassed; } async function main() { console.clear(); printHeader(); const startTime = Date.now(); const results = {}; try { // Paso 1: Validar archivos results.validation = await validateDataFiles(); if (!results.validation) { console.log(colorize('\n❌ Validación de archivos falló. Abortando tests.', 'red')); process.exit(1); } // Paso 2: Ejecutar tests MCP results.mcpTests = await runMCPTests(); // Paso 3: Tests de firma digital results.cryptoTests = await runCryptoTests(); // Paso 4: Tests de integración results.integration = await runIntegrationTests(); // Generar reporte final const success = await generateReport(results); const duration = ((Date.now() - startTime) / 1000).toFixed(2); console.log(colorize(`\n⏱️ Duración total: ${duration}s`, 'cyan')); process.exit(success ? 0 : 1); } catch (error) { console.error(colorize(`\n💥 Error inesperado: ${error.message}`, 'red')); console.error(error.stack); process.exit(1); } } // Ejecutar si se llama directamente if (require.main === module) { main(); } module.exports = { main };

Latest Blog Posts

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/noelserdna/cv-dinamic-mcp'

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