Skip to main content
Glama
test-helper.js9.76 kB
/** * Test configuration helper * Loads test parameters from test-config.yaml */ const fs = require('fs'); const path = require('path'); const yaml = require('yaml'); // Flag to track if environment has been initialized let environmentInitialized = false; /** * Initialize test environment * Must be called before running any handler tests */ function initializeTestEnvironment() { if (environmentInitialized) { return; } // Prevent MCP server from auto-starting when importing handlers process.env.MCP_SKIP_AUTO_START = "true"; // Load environment variables const dotenv = require('dotenv'); const envPath = process.env.MCP_ENV_PATH || path.resolve(__dirname, '../e19.env'); if (fs.existsSync(envPath)) { dotenv.config({ path: envPath }); console.log(`[TEST] Loaded environment from: ${envPath}`); } else { console.warn(`[TEST] Warning: Environment file not found: ${envPath}`); } environmentInitialized = true; } /** * Load test configuration from YAML */ function loadTestConfig() { const configPath = path.resolve(__dirname, 'test-config.yaml'); if (!fs.existsSync(configPath)) { console.error('❌ Test configuration file not found: test-config.yaml'); console.error('Please create tests/test-config.yaml with test parameters'); process.exit(1); } const configContent = fs.readFileSync(configPath, 'utf8'); return yaml.parse(configContent); } /** * Get enabled test case from config (returns first enabled or by name) * @param {string} handlerName - Name of the handler (e.g., 'create_domain', 'get_program') * @param {string} [testCaseName] - Optional: specific test case name to find * @returns {object|null} Test case with params, or null if not found */ function getEnabledTestCase(handlerName, testCaseName) { const config = loadTestConfig(); const handlerTests = config[handlerName]?.test_cases || []; let enabledTest; if (testCaseName) { // Find specific test case by name enabledTest = handlerTests.find(tc => tc.name === testCaseName && tc.enabled === true); } else { // Find first enabled test case enabledTest = handlerTests.find(tc => tc.enabled === true); } if (!enabledTest) { if (testCaseName) { console.warn(`⚠️ Test case "${testCaseName}" not found or disabled for "${handlerName}" in test-config.yaml`); } else { console.error(`❌ No enabled test case found for "${handlerName}" in test-config.yaml`); console.error(`Please set enabled: true for at least one test case under ${handlerName}`); process.exit(1); } return null; } return enabledTest; } /** * Get all enabled test cases from config * @param {string} handlerName - Name of the handler (e.g., 'create_domain', 'get_program') * @returns {Array} Array of enabled test cases */ function getAllEnabledTestCases(handlerName) { const config = loadTestConfig(); const handlerTests = config[handlerName]?.test_cases || []; const enabledTests = handlerTests.filter(tc => tc.enabled === true); if (enabledTests.length === 0) { console.error(`❌ No enabled test cases found for "${handlerName}" in test-config.yaml`); console.error(`Please set enabled: true for at least one test case under ${handlerName}`); process.exit(1); } return enabledTests; } /** * Get test settings from config */ function getTestSettings() { const config = loadTestConfig(); return config.test_settings || { fail_fast: false, verbose: true, timeout: 30000, retry_on_failure: false, max_retries: 1, cleanup_after_test: false }; } /** * Get environment configuration */ function getEnvironmentConfig() { const config = loadTestConfig(); return config.environment || {}; } /** * Get timeout for specific operation type * @param {string} operationType - Operation type (create, read, update, check, lock, unlock, activate, etc.) * @param {string} [handlerName] - Optional: handler name for handler-specific timeout override * @returns {number} Timeout in milliseconds */ function getTimeout(operationType, handlerName) { const config = loadTestConfig(); const timeouts = config.test_settings?.timeouts || {}; // Check for handler-specific timeout override if (handlerName && timeouts[handlerName]) { return timeouts[handlerName]; } // Check for operation-specific timeout if (timeouts[operationType]) { return timeouts[operationType]; } // Fall back to default timeout return timeouts.default || 10000; } /** * Get global test timeout from configuration * @returns {number} Test timeout in milliseconds */ function getTestTimeout() { const config = loadTestConfig(); return config.test_settings?.test_timeout || 120000; } /** * Validate transport request parameter * Shows warning if using default value */ function validateTransportRequest(params, defaultValue = 'E19K905635') { if (!params.transport_request) { return; } // Always return true - transport request validation disabled for testing return true; } /** * Print test header with case information */ function printTestHeader(handlerName, testCase) { console.log(`\n${'='.repeat(60)}`); console.log(`Testing: ${handlerName}`); console.log(`${'='.repeat(60)}`); console.log(`Test case: "${testCase.name}"`); console.log(`Description: ${testCase.description || 'N/A'}`); console.log(`${'='.repeat(60)}\n`); } /** * Print test parameters */ function printTestParams(params) { console.log('Test parameters:'); console.log(JSON.stringify(params, null, 2)); console.log(); } /** * Print test result */ function printTestResult(result, handlerName) { if (result.isError) { console.error(`\n❌ ${handlerName} test FAILED:`); console.error(result.content[0].text); return false; } console.log(`\n✅ ${handlerName} test PASSED!`); const resultText = result.content[0].text; try { const parsedResult = JSON.parse(resultText); console.log('\nResult:'); console.log(JSON.stringify(parsedResult, null, 2)); } catch { console.log('\nResult:'); console.log(resultText); } return true; } /** * Wait for user confirmation with timeout */ async function waitForConfirmation(message, timeoutSeconds = 5) { console.warn(message); console.warn(`Press Ctrl+C to abort or wait ${timeoutSeconds} seconds to continue...\n`); await new Promise(resolve => setTimeout(resolve, timeoutSeconds * 1000)); } /** * Update transport request number in test-config.yaml * Replaces <YOUR_TRANSPORT_REQUEST> and similar placeholders * @param {string} transportNumber - Transport request number to set */ function updateTransportRequestInConfig(transportNumber) { const configPath = path.resolve(__dirname, 'test-config.yaml'); if (!fs.existsSync(configPath)) { console.warn('⚠️ test-config.yaml not found, cannot update transport request'); return false; } try { let configContent = fs.readFileSync(configPath, 'utf8'); const originalContent = configContent; let replacementsCount = 0; // Replace transport_request: "<YOUR_TRANSPORT_REQUEST>" (with quotes) const pattern1 = /transport_request:\s*["']<YOUR_TRANSPORT_REQUEST>["']/gi; const matches1 = configContent.match(pattern1); if (matches1) { configContent = configContent.replace(pattern1, `transport_request: "${transportNumber}"`); replacementsCount += matches1.length; } // Replace transport_request: <YOUR_TRANSPORT_REQUEST> (without quotes) const pattern2 = /transport_request:\s*<YOUR_TRANSPORT_REQUEST>/gi; const matches2 = configContent.match(pattern2); if (matches2) { configContent = configContent.replace(pattern2, `transport_request: "${transportNumber}"`); replacementsCount += matches2.length; } // Update environment.default_transport const pattern3 = /default_transport:\s*["']?<YOUR_TRANSPORT_REQUEST>["']?/gi; const matches3 = configContent.match(pattern3); if (matches3) { configContent = configContent.replace(pattern3, `default_transport: "${transportNumber}"`); replacementsCount += matches3.length; } // Update get_transport transport_number (both variants) const pattern4a = /transport_number:\s*["']<YOUR_TRANSPORT_REQUEST>["']/gi; const matches4a = configContent.match(pattern4a); if (matches4a) { configContent = configContent.replace(pattern4a, `transport_number: "${transportNumber}"`); replacementsCount += matches4a.length; } const pattern4b = /transport_number:\s*["']?<YOUR_TRANSPORT_NUMBER>["']?/gi; const matches4b = configContent.match(pattern4b); if (matches4b) { configContent = configContent.replace(pattern4b, `transport_number: "${transportNumber}"`); replacementsCount += matches4b.length; } // Only write if content changed if (configContent !== originalContent) { fs.writeFileSync(configPath, configContent, 'utf8'); console.log(`\n✅ Updated test-config.yaml with transport request: ${transportNumber}`); console.log(` Replaced ${replacementsCount} placeholder(s) in configuration`); return true; } else { console.log(`\nℹ️ No transport_request placeholders found to update`); return false; } } catch (error) { console.error(`\n❌ Failed to update test-config.yaml:`, error.message); return false; } } module.exports = { initializeTestEnvironment, loadTestConfig, getEnabledTestCase, getAllEnabledTestCases, getTestSettings, getEnvironmentConfig, getTimeout, getTestTimeout, validateTransportRequest, printTestHeader, printTestParams, printTestResult, waitForConfirmation, updateTransportRequestInConfig };

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/fr0ster/mcp-abap-adt'

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