Skip to main content
Glama

n8n-workflow-builder-mcp

by ifmelate
n8nIntegration.test.js10 kB
/** * Unit tests for the n8n integration module */ const path = require('path'); const { n8nIntegration, getIntegrationType } = require('../../src/models/n8nIntegration'); // Mock dependencies jest.mock('../../config/default', () => ({ n8n: { apiUrl: 'http://test-n8n-api.local/api/', apiKey: 'test-api-key', workflowsPath: './test-n8n-workflows', integrationType: 'auto' }, storage: { workflowsPath: './test-workflows' } })); jest.mock('fs', () => { const originalModule = jest.requireActual('fs'); return { ...originalModule, promises: { mkdir: jest.fn().mockResolvedValue(undefined), writeFile: jest.fn().mockResolvedValue(undefined), readFile: jest.fn(), readdir: jest.fn(), unlink: jest.fn(), access: jest.fn() } }; }); // Import fs after mocking const fs = require('fs'); jest.mock('node-fetch'); const fetch = require('node-fetch'); // Mock logger to silence output during tests jest.mock('../../src/utils/logger', () => ({ logger: { info: jest.fn(), error: jest.fn(), warn: jest.fn(), debug: jest.fn() } })); // Mock workflowStorage to isolate n8n integration jest.mock('../../src/models/storage', () => ({ workflowStorage: { loadWorkflow: jest.fn() }, DEFAULT_WORKFLOWS_DIR: './test-workflows' })); const { workflowStorage } = require('../../src/models/storage'); describe('n8n Integration', () => { beforeEach(() => { // Reset all mocks jest.clearAllMocks(); }); describe('getIntegrationType', () => { it('should return "api" if API key is configured and integrationType is "auto"', () => { // Using the mocked config with API key const type = getIntegrationType(); expect(type).toBe('api'); }); it('should return "filesystem" if API key is not configured and integrationType is "auto"', () => { // Temporarily modify the mock to test without API key const config = require('../../config/default'); const originalApiKey = config.n8n.apiKey; config.n8n.apiKey = undefined; const type = getIntegrationType(); expect(type).toBe('filesystem'); // Restore the original config config.n8n.apiKey = originalApiKey; }); it('should respect explicitly configured type regardless of API key', () => { const config = require('../../config/default'); const originalType = config.n8n.integrationType; const originalApiKey = config.n8n.apiKey; // Test with filesystem type explicitly configured config.n8n.integrationType = 'filesystem'; config.n8n.apiKey = 'test-api-key'; expect(getIntegrationType()).toBe('filesystem'); // Test with api type explicitly configured config.n8n.integrationType = 'api'; config.n8n.apiKey = undefined; expect(getIntegrationType()).toBe('api'); // Restore original values config.n8n.integrationType = originalType; config.n8n.apiKey = originalApiKey; }); }); describe('deployWorkflow', () => { const testWorkflow = { id: 'test-workflow', name: 'Test Workflow', nodes: [], connections: {} }; beforeEach(() => { workflowStorage.loadWorkflow.mockResolvedValue(testWorkflow); }); it('should deploy workflow via API', async () => { // Mock successful API response fetch.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue({ id: 'n8n-workflow-123' }) }); const result = await n8nIntegration.deployWorkflow('test-workflow'); expect(fetch).toHaveBeenCalledWith('http://test-n8n-api.local/api/workflows', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-N8N-API-KEY': 'test-api-key' }, body: JSON.stringify(testWorkflow) }); expect(result).toEqual({ success: true, id: 'n8n-workflow-123', message: 'Workflow deployed successfully via API', n8nId: 'n8n-workflow-123' }); }); it('should handle API errors during deployment', async () => { // Mock failed API response fetch.mockResolvedValue({ ok: false, status: 401, statusText: 'Unauthorized', json: jest.fn().mockResolvedValue({ message: 'Invalid API key' }) }); await expect(n8nIntegration.deployWorkflow('test-workflow')).rejects.toThrow( 'Failed to deploy workflow: 401 Unauthorized' ); }); it('should deploy workflow via filesystem', async () => { // Test filesystem integration const config = require('../../config/default'); const originalApiKey = config.n8n.apiKey; config.n8n.apiKey = undefined; const result = await n8nIntegration.deployWorkflow('test-workflow'); expect(fs.promises.mkdir).toHaveBeenCalledWith(expect.stringContaining('test-n8n-workflows'), { recursive: true }); expect(fs.promises.writeFile).toHaveBeenCalledWith( expect.stringContaining('test-workflow.json'), JSON.stringify(testWorkflow, null, 2) ); expect(result).toEqual({ success: true, id: 'test-workflow', path: expect.stringContaining('test-workflow.json'), message: 'Workflow deployed successfully via filesystem' }); // Restore original value config.n8n.apiKey = originalApiKey; }); it('should throw error if workflow not found', async () => { workflowStorage.loadWorkflow.mockResolvedValue(null); await expect(n8nIntegration.deployWorkflow('non-existent')).rejects.toThrow( 'Failed to deploy workflow: Workflow with ID/path non-existent not found' ); }); }); describe('activateWorkflow', () => { const testWorkflow = { id: 'test-workflow', name: 'Test Workflow', active: false, nodes: [], connections: {} }; beforeEach(() => { workflowStorage.loadWorkflow.mockResolvedValue({ ...testWorkflow }); }); it('should activate workflow via API', async () => { // Mock successful API response fetch.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue({ id: 'test-workflow', active: true }) }); const result = await n8nIntegration.activateWorkflow('test-workflow', true); expect(fetch).toHaveBeenCalledWith('http://test-n8n-api.local/api/workflows/test-workflow/activate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-N8N-API-KEY': 'test-api-key' }, body: JSON.stringify({ active: true }) }); expect(result).toEqual({ success: true, id: 'test-workflow', active: true, message: 'Workflow activated successfully' }); }); it('should deactivate workflow via API when activate=false', async () => { // Mock successful API response fetch.mockResolvedValue({ ok: true, json: jest.fn().mockResolvedValue({ id: 'test-workflow', active: false }) }); const result = await n8nIntegration.activateWorkflow('test-workflow', false); expect(fetch).toHaveBeenCalledWith('http://test-n8n-api.local/api/workflows/test-workflow/activate', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-N8N-API-KEY': 'test-api-key' }, body: JSON.stringify({ active: false }) }); expect(result).toEqual({ success: true, id: 'test-workflow', active: false, message: 'Workflow deactivated successfully' }); }); it('should activate workflow via filesystem', async () => { // Test filesystem integration const config = require('../../config/default'); const originalApiKey = config.n8n.apiKey; config.n8n.apiKey = undefined; // Mock filesystem access success for n8n workflows path fs.promises.access.mockResolvedValue(undefined); const result = await n8nIntegration.activateWorkflow('test-workflow', true); // Check that it updated both in original location and n8n directory expect(fs.promises.writeFile).toHaveBeenCalledTimes(2); expect(fs.promises.writeFile).toHaveBeenCalledWith( expect.any(String), expect.stringContaining('"active": true') ); expect(result).toEqual({ success: true, id: 'test-workflow', active: true, message: 'Workflow activated successfully' }); // Restore original value config.n8n.apiKey = originalApiKey; }); }); // Additional tests for getWorkflow, checkExecutionStatus, and listWorkflows would follow the same pattern });

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/ifmelate/n8n-workflow-builder-mcp'

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