Skip to main content
Glama

n8n-MCP

by 88-888
test-env.tsβ€’10.6 kB
/** * Test Environment Configuration Loader * * This module handles loading and validating test environment variables * with type safety and default values. */ import * as dotenv from 'dotenv'; import * as path from 'path'; import { existsSync } from 'fs'; // Load test environment variables export function loadTestEnvironment(): void { // CI Debug logging const isCI = process.env.CI === 'true'; // First, load the main .env file (for integration tests that need real credentials) const mainEnvPath = path.resolve(process.cwd(), '.env'); if (existsSync(mainEnvPath)) { dotenv.config({ path: mainEnvPath }); if (isCI) { console.log('[CI-DEBUG] Loaded .env file from:', mainEnvPath); } } // Load base test environment const testEnvPath = path.resolve(process.cwd(), '.env.test'); if (isCI) { console.log('[CI-DEBUG] Looking for .env.test at:', testEnvPath); console.log('[CI-DEBUG] File exists?', existsSync(testEnvPath)); } if (existsSync(testEnvPath)) { // Don't override values from .env const result = dotenv.config({ path: testEnvPath, override: false }); if (isCI && result.error) { console.error('[CI-DEBUG] Failed to load .env.test:', result.error); } else if (isCI && result.parsed) { console.log('[CI-DEBUG] Successfully loaded', Object.keys(result.parsed).length, 'env vars from .env.test'); } } else if (isCI) { console.warn('[CI-DEBUG] .env.test file not found, will use defaults only'); } // Load local test overrides (for sensitive values) const localEnvPath = path.resolve(process.cwd(), '.env.test.local'); if (existsSync(localEnvPath)) { dotenv.config({ path: localEnvPath, override: true }); } // Set test-specific defaults (only if not already set) setTestDefaults(); // Validate required environment variables validateTestEnvironment(); } /** * Set default values for test environment variables */ function setTestDefaults(): void { // Ensure we're in test mode process.env.NODE_ENV = 'test'; process.env.TEST_ENVIRONMENT = 'true'; // Set defaults if not already set const defaults: Record<string, string> = { // Database NODE_DB_PATH: ':memory:', REBUILD_ON_START: 'false', // API N8N_API_URL: 'http://localhost:3001/mock-api', N8N_API_KEY: 'test-api-key-12345', // Server PORT: '3001', HOST: '127.0.0.1', // Logging LOG_LEVEL: 'error', DEBUG: 'false', TEST_LOG_VERBOSE: 'false', // Timeouts TEST_TIMEOUT_UNIT: '5000', TEST_TIMEOUT_INTEGRATION: '15000', TEST_TIMEOUT_E2E: '30000', TEST_TIMEOUT_GLOBAL: '30000', // Reduced from 60s to 30s to catch hangs faster // Test execution TEST_RETRY_ATTEMPTS: '2', TEST_RETRY_DELAY: '1000', TEST_PARALLEL: 'true', TEST_MAX_WORKERS: '4', // Features FEATURE_MOCK_EXTERNAL_APIS: 'true', FEATURE_USE_TEST_CONTAINERS: 'false', MSW_ENABLED: 'true', MSW_API_DELAY: '0', // Paths TEST_FIXTURES_PATH: './tests/fixtures', TEST_DATA_PATH: './tests/data', TEST_SNAPSHOTS_PATH: './tests/__snapshots__', // Performance PERF_THRESHOLD_API_RESPONSE: '100', PERF_THRESHOLD_DB_QUERY: '50', PERF_THRESHOLD_NODE_PARSE: '200', // Caching CACHE_TTL: '0', CACHE_ENABLED: 'false', // Rate limiting RATE_LIMIT_MAX: '0', RATE_LIMIT_WINDOW: '0', // Error handling ERROR_SHOW_STACK: 'true', ERROR_SHOW_DETAILS: 'true', // Cleanup TEST_CLEANUP_ENABLED: 'true', TEST_CLEANUP_ON_FAILURE: 'false', // Database seeding TEST_SEED_DATABASE: 'true', TEST_SEED_TEMPLATES: 'true', // Network NETWORK_TIMEOUT: '5000', NETWORK_RETRY_COUNT: '0', // Memory TEST_MEMORY_LIMIT: '512', // Coverage COVERAGE_DIR: './coverage', COVERAGE_REPORTER: 'lcov,html,text-summary' }; for (const [key, value] of Object.entries(defaults)) { if (!process.env[key]) { process.env[key] = value; } } } /** * Validate that required environment variables are set */ function validateTestEnvironment(): void { const required = [ 'NODE_ENV', 'NODE_DB_PATH', 'N8N_API_URL', 'N8N_API_KEY' ]; const missing = required.filter(key => !process.env[key]); if (missing.length > 0) { throw new Error( `Missing required test environment variables: ${missing.join(', ')}\n` + 'Please ensure .env.test is properly configured.' ); } // Validate NODE_ENV is set to test if (process.env.NODE_ENV !== 'test') { throw new Error( 'NODE_ENV must be set to "test" when running tests.\n' + 'This prevents accidental execution against production systems.' ); } } /** * Get typed test environment configuration */ export function getTestConfig() { // Ensure defaults are set before accessing if (!process.env.N8N_API_URL) { setTestDefaults(); } return { // Environment nodeEnv: process.env.NODE_ENV || 'test', isTest: process.env.TEST_ENVIRONMENT === 'true', // Database database: { path: process.env.NODE_DB_PATH || ':memory:', rebuildOnStart: process.env.REBUILD_ON_START === 'true', seedData: process.env.TEST_SEED_DATABASE === 'true', seedTemplates: process.env.TEST_SEED_TEMPLATES === 'true' }, // API api: { url: process.env.N8N_API_URL || 'http://localhost:3001/mock-api', key: process.env.N8N_API_KEY || 'test-api-key-12345', webhookBaseUrl: process.env.N8N_WEBHOOK_BASE_URL, webhookTestUrl: process.env.N8N_WEBHOOK_TEST_URL }, // Server server: { port: parseInt(process.env.PORT || '3001', 10), host: process.env.HOST || '127.0.0.1', corsOrigin: process.env.CORS_ORIGIN?.split(',') || [] }, // Authentication auth: { token: process.env.AUTH_TOKEN, mcpToken: process.env.MCP_AUTH_TOKEN }, // Logging logging: { level: process.env.LOG_LEVEL || 'error', debug: process.env.DEBUG === 'true', verbose: process.env.TEST_LOG_VERBOSE === 'true', showStack: process.env.ERROR_SHOW_STACK === 'true', showDetails: process.env.ERROR_SHOW_DETAILS === 'true' }, // Test execution execution: { timeouts: { unit: parseInt(process.env.TEST_TIMEOUT_UNIT || '5000', 10), integration: parseInt(process.env.TEST_TIMEOUT_INTEGRATION || '15000', 10), e2e: parseInt(process.env.TEST_TIMEOUT_E2E || '30000', 10), global: parseInt(process.env.TEST_TIMEOUT_GLOBAL || '60000', 10) }, retry: { attempts: parseInt(process.env.TEST_RETRY_ATTEMPTS || '2', 10), delay: parseInt(process.env.TEST_RETRY_DELAY || '1000', 10) }, parallel: process.env.TEST_PARALLEL === 'true', maxWorkers: parseInt(process.env.TEST_MAX_WORKERS || '4', 10) }, // Features features: { coverage: process.env.FEATURE_TEST_COVERAGE === 'true', screenshots: process.env.FEATURE_TEST_SCREENSHOTS === 'true', videos: process.env.FEATURE_TEST_VIDEOS === 'true', trace: process.env.FEATURE_TEST_TRACE === 'true', mockExternalApis: process.env.FEATURE_MOCK_EXTERNAL_APIS === 'true', useTestContainers: process.env.FEATURE_USE_TEST_CONTAINERS === 'true' }, // Mocking mocking: { msw: { enabled: process.env.MSW_ENABLED === 'true', apiDelay: parseInt(process.env.MSW_API_DELAY || '0', 10) }, redis: { enabled: process.env.REDIS_MOCK_ENABLED === 'true', port: parseInt(process.env.REDIS_MOCK_PORT || '6380', 10) }, elasticsearch: { enabled: process.env.ELASTICSEARCH_MOCK_ENABLED === 'true', port: parseInt(process.env.ELASTICSEARCH_MOCK_PORT || '9201', 10) } }, // Paths paths: { fixtures: process.env.TEST_FIXTURES_PATH || './tests/fixtures', data: process.env.TEST_DATA_PATH || './tests/data', snapshots: process.env.TEST_SNAPSHOTS_PATH || './tests/__snapshots__' }, // Performance performance: { thresholds: { apiResponse: parseInt(process.env.PERF_THRESHOLD_API_RESPONSE || '100', 10), dbQuery: parseInt(process.env.PERF_THRESHOLD_DB_QUERY || '50', 10), nodeParse: parseInt(process.env.PERF_THRESHOLD_NODE_PARSE || '200', 10) } }, // Rate limiting rateLimiting: { max: parseInt(process.env.RATE_LIMIT_MAX || '0', 10), window: parseInt(process.env.RATE_LIMIT_WINDOW || '0', 10) }, // Caching cache: { enabled: process.env.CACHE_ENABLED === 'true', ttl: parseInt(process.env.CACHE_TTL || '0', 10) }, // Cleanup cleanup: { enabled: process.env.TEST_CLEANUP_ENABLED === 'true', onFailure: process.env.TEST_CLEANUP_ON_FAILURE === 'true' }, // Network network: { timeout: parseInt(process.env.NETWORK_TIMEOUT || '5000', 10), retryCount: parseInt(process.env.NETWORK_RETRY_COUNT || '0', 10) }, // Memory memory: { limit: parseInt(process.env.TEST_MEMORY_LIMIT || '512', 10) }, // Coverage coverage: { dir: process.env.COVERAGE_DIR || './coverage', reporters: (process.env.COVERAGE_REPORTER || 'lcov,html,text-summary').split(',') } }; } // Export type for the test configuration export type TestConfig = ReturnType<typeof getTestConfig>; /** * Helper to check if we're in test mode */ export function isTestMode(): boolean { return process.env.NODE_ENV === 'test' || process.env.TEST_ENVIRONMENT === 'true'; } /** * Helper to get timeout for specific test type */ export function getTestTimeout(type: 'unit' | 'integration' | 'e2e' | 'global' = 'unit'): number { const config = getTestConfig(); return config.execution.timeouts[type]; } /** * Helper to check if a feature is enabled */ export function isFeatureEnabled(feature: keyof TestConfig['features']): boolean { const config = getTestConfig(); return config.features[feature]; } /** * Reset environment to defaults (useful for test isolation) */ export function resetTestEnvironment(): void { // Clear all test-specific environment variables const testKeys = Object.keys(process.env).filter(key => key.startsWith('TEST_') || key.startsWith('FEATURE_') || key.startsWith('MSW_') || key.startsWith('PERF_') ); testKeys.forEach(key => { delete process.env[key]; }); // Reload defaults loadTestEnvironment(); }

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/88-888/n8n-mcp'

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