UNPKG

n8n-mcp

Version:

Integration between n8n workflow automation and Model Context Protocol (MCP)

340 lines • 12.9 kB
#!/usr/bin/env npx tsx "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const workflow_validator_1 = require("../services/workflow-validator"); const node_repository_1 = require("../database/node-repository"); const database_adapter_1 = require("../database/database-adapter"); const enhanced_config_validator_1 = require("../services/enhanced-config-validator"); const logger_1 = require("../utils/logger"); const path_1 = __importDefault(require("path")); const logger = new logger_1.Logger({ prefix: '[Test Error Handling]' }); const testWorkflows = [ { name: 'Deprecated continueOnFail', workflow: { name: 'Test Deprecated Error Handling', nodes: [ { id: '1', name: 'Webhook', type: 'n8n-nodes-base.webhook', position: [100, 100], parameters: { path: 'test-webhook', httpMethod: 'POST' }, continueOnFail: true }, { id: '2', name: 'HTTP Request', type: 'n8n-nodes-base.httpRequest', position: [300, 100], parameters: { url: 'https://api.example.com/data', method: 'GET' }, continueOnFail: true } ], connections: { 'Webhook': { main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]] } } } }, { name: 'Modern onError property', workflow: { name: 'Test Modern Error Handling', nodes: [ { id: '1', name: 'Webhook', type: 'n8n-nodes-base.webhook', position: [100, 100], parameters: { path: 'test-webhook', httpMethod: 'POST' }, onError: 'continueRegularOutput', alwaysOutputData: true }, { id: '2', name: 'HTTP Request', type: 'n8n-nodes-base.httpRequest', position: [300, 100], parameters: { url: 'https://api.example.com/data', method: 'POST', sendBody: true, contentType: 'json', jsonBody: '{"test": "data"}' }, onError: 'continueRegularOutput', retryOnFail: true, maxTries: 3, waitBetweenTries: 2000, alwaysOutputData: true } ], connections: { 'Webhook': { main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]] } } } }, { name: 'Missing error handling', workflow: { name: 'Test Missing Error Handling', nodes: [ { id: '1', name: 'Webhook', type: 'n8n-nodes-base.webhook', position: [100, 100], parameters: { path: 'test-webhook', httpMethod: 'POST' } }, { id: '2', name: 'HTTP Request', type: 'n8n-nodes-base.httpRequest', position: [300, 100], parameters: { url: 'https://api.example.com/data', method: 'GET' } }, { id: '3', name: 'Postgres', type: 'n8n-nodes-base.postgres', position: [500, 100], parameters: { operation: 'insert', table: 'users', columns: 'name,email' } } ], connections: { 'Webhook': { main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]] }, 'HTTP Request': { main: [[{ node: 'Postgres', type: 'main', index: 0 }]] } } } }, { name: 'Mixed error handling', workflow: { name: 'Test Mixed Error Handling', nodes: [ { id: '1', name: 'Manual Trigger', type: 'n8n-nodes-base.manualTrigger', position: [100, 100], parameters: {} }, { id: '2', name: 'OpenAI', type: 'n8n-nodes-base.openAi', position: [300, 100], parameters: { resource: 'chat', operation: 'create', model: 'gpt-3.5-turbo', messages: { values: [ { role: 'user', content: 'Hello' } ] } }, onError: 'continueRegularOutput', retryOnFail: true, maxTries: 5, waitBetweenTries: 5000 }, { id: '3', name: 'Slack', type: 'n8n-nodes-base.slack', position: [500, 100], parameters: { resource: 'message', operation: 'post', channel: '#general', text: 'AI response: {{ $json.message }}' }, continueOnFail: true } ], connections: { 'Manual Trigger': { main: [[{ node: 'OpenAI', type: 'main', index: 0 }]] }, 'OpenAI': { main: [[{ node: 'Slack', type: 'main', index: 0 }]] } } } }, { name: 'Error output routing', workflow: { name: 'Test Error Output Routing', nodes: [ { id: '1', name: 'Manual Trigger', type: 'n8n-nodes-base.manualTrigger', position: [100, 200], parameters: {} }, { id: '2', name: 'HTTP Request', type: 'n8n-nodes-base.httpRequest', position: [300, 200], parameters: { url: 'https://api.example.com/data', method: 'GET' }, onError: 'continueErrorOutput', retryOnFail: true, maxTries: 2, alwaysOutputData: true }, { id: '3', name: 'Success Handler', type: 'n8n-nodes-base.set', position: [500, 100], parameters: { mode: 'manual', assignments: { assignments: [ { id: '1', name: 'status', value: 'success', type: 'string' } ] } } }, { id: '4', name: 'Error Handler', type: 'n8n-nodes-base.set', position: [500, 300], parameters: { mode: 'manual', assignments: { assignments: [ { id: '1', name: 'status', value: 'error', type: 'string' } ] } } } ], connections: { 'Manual Trigger': { main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]] }, 'HTTP Request': { main: [[{ node: 'Success Handler', type: 'main', index: 0 }]], error: [[{ node: 'Error Handler', type: 'main', index: 0 }]] } } } } ]; async function testErrorHandlingValidation() { try { const dbPath = path_1.default.join(process.cwd(), 'nodes.db'); const dbAdapter = await (0, database_adapter_1.createDatabaseAdapter)(dbPath); const nodeRepository = new node_repository_1.NodeRepository(dbAdapter); const validator = new workflow_validator_1.WorkflowValidator(nodeRepository, enhanced_config_validator_1.EnhancedConfigValidator); logger.info('Testing error handling validation...\n'); for (const test of testWorkflows) { logger.info(`\n${'='.repeat(80)}`); logger.info(`Test: ${test.name}`); logger.info('='.repeat(80)); const result = await validator.validateWorkflow(test.workflow, { validateNodes: true, validateConnections: true, validateExpressions: false, profile: 'strict' }); logger.info(`\nValidation result: ${result.valid ? 'āœ… VALID' : 'āŒ INVALID'}`); if (result.errors.length > 0) { logger.error('\nErrors:'); result.errors.forEach((error, index) => { logger.error(` ${index + 1}. ${error.nodeName ? `[${error.nodeName}] ` : ''}${error.message}`); if (error.details) { logger.error(` Details: ${JSON.stringify(error.details)}`); } }); } if (result.warnings.length > 0) { logger.warn('\nWarnings:'); result.warnings.forEach((warning, index) => { logger.warn(` ${index + 1}. ${warning.nodeName ? `[${warning.nodeName}] ` : ''}${warning.message}`); }); } if (result.suggestions.length > 0) { logger.info('\nSuggestions:'); result.suggestions.forEach((suggestion, index) => { logger.info(` ${index + 1}. ${suggestion}`); }); } const errorHandlingWarnings = result.warnings.filter((w) => w.message.includes('error handling') || w.message.includes('continueOnFail') || w.message.includes('onError')); if (errorHandlingWarnings.length > 0) { logger.info('\nšŸ“‹ Error Handling Specific Issues:'); errorHandlingWarnings.forEach((warning) => { logger.info(` - [${warning.nodeName}] ${warning.message}`); }); } logger.info('\nStatistics:'); logger.info(` Total nodes: ${result.statistics.totalNodes}`); logger.info(` Enabled nodes: ${result.statistics.enabledNodes}`); logger.info(` Valid connections: ${result.statistics.validConnections}`); } logger.info('\nāœ… Error handling validation tests completed!'); } catch (error) { logger.error('Test failed:', error); process.exit(1); } } testErrorHandlingValidation().catch(error => { logger.error('Fatal error:', error); process.exit(1); }); //# sourceMappingURL=test-error-handling-validation.js.map