Skip to main content
Glama

n8n-MCP

by 88-888
msw-setup.test.tsβ€’9.82 kB
import { describe, it, expect, beforeAll, afterAll, afterEach } from 'vitest'; import { mswTestServer, n8nApiMock, testDataBuilders, integrationTestServer } from './setup/msw-test-server'; import { http, HttpResponse } from 'msw'; import axios from 'axios'; import { server } from './setup/integration-setup'; describe('MSW Setup Verification', () => { const baseUrl = 'http://localhost:5678'; describe('Global MSW Setup', () => { it('should intercept n8n API requests with default handlers', async () => { // This uses the global MSW setup from vitest.config.ts const response = await axios.get(`${baseUrl}/api/v1/health`); expect(response.status).toBe(200); expect(response.data).toEqual({ status: 'ok', version: '1.103.2', features: { workflows: true, executions: true, credentials: true, webhooks: true, } }); }); it('should allow custom handlers for specific tests', async () => { // Add a custom handler just for this test using the global server server.use( http.get('*/api/v1/custom-endpoint', () => { return HttpResponse.json({ custom: true }); }) ); const response = await axios.get(`${baseUrl}/api/v1/custom-endpoint`); expect(response.status).toBe(200); expect(response.data).toEqual({ custom: true }); }); it('should return mock workflows', async () => { const response = await axios.get(`${baseUrl}/api/v1/workflows`); expect(response.status).toBe(200); expect(response.data).toHaveProperty('data'); expect(Array.isArray(response.data.data)).toBe(true); expect(response.data.data.length).toBeGreaterThan(0); }); }); describe('Integration Test Server', () => { // Use the global MSW server instance for these tests afterEach(() => { // Reset handlers after each test to ensure clean state server.resetHandlers(); }); it('should handle workflow creation with custom response', async () => { // Use the global server instance to add custom handler server.use( http.post('*/api/v1/workflows', async ({ request }) => { const body = await request.json() as any; return HttpResponse.json({ data: { id: 'custom-workflow-123', name: 'Test Workflow from MSW', active: body.active || false, nodes: body.nodes, connections: body.connections, settings: body.settings || {}, tags: body.tags || [], createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), versionId: '1' } }, { status: 201 }); }) ); const workflowData = testDataBuilders.workflow({ name: 'My Test Workflow' }); const response = await axios.post(`${baseUrl}/api/v1/workflows`, workflowData); expect(response.status).toBe(201); expect(response.data.data).toMatchObject({ id: 'custom-workflow-123', name: 'Test Workflow from MSW', nodes: workflowData.nodes, connections: workflowData.connections }); }); it('should handle error responses', async () => { server.use( http.get('*/api/v1/workflows/missing', () => { return HttpResponse.json( { message: 'Workflow not found', code: 'NOT_FOUND', timestamp: new Date().toISOString() }, { status: 404 } ); }) ); try { await axios.get(`${baseUrl}/api/v1/workflows/missing`); expect.fail('Should have thrown an error'); } catch (error: any) { expect(error.response.status).toBe(404); expect(error.response.data).toEqual({ message: 'Workflow not found', code: 'NOT_FOUND', timestamp: expect.any(String) }); } }); it('should simulate rate limiting', async () => { let requestCount = 0; const limit = 5; server.use( http.get('*/api/v1/rate-limited', () => { requestCount++; if (requestCount > limit) { return HttpResponse.json( { message: 'Rate limit exceeded', code: 'RATE_LIMIT', retryAfter: 60 }, { status: 429, headers: { 'X-RateLimit-Limit': String(limit), 'X-RateLimit-Remaining': '0', 'X-RateLimit-Reset': String(Date.now() + 60000) } } ); } return HttpResponse.json({ success: true }); }) ); // Make requests up to the limit for (let i = 0; i < 5; i++) { const response = await axios.get(`${baseUrl}/api/v1/rate-limited`); expect(response.status).toBe(200); } // Next request should be rate limited try { await axios.get(`${baseUrl}/api/v1/rate-limited`); expect.fail('Should have been rate limited'); } catch (error: any) { expect(error.response.status).toBe(429); expect(error.response.data.code).toBe('RATE_LIMIT'); expect(error.response.headers['x-ratelimit-remaining']).toBe('0'); } }); it('should handle webhook execution', async () => { server.use( http.post('*/webhook/test-webhook', async ({ request }) => { const body = await request.json(); return HttpResponse.json({ processed: true, result: 'success', webhookReceived: { path: 'test-webhook', method: 'POST', body, timestamp: new Date().toISOString() } }); }) ); const webhookData = { message: 'Test webhook payload' }; const response = await axios.post(`${baseUrl}/webhook/test-webhook`, webhookData); expect(response.status).toBe(200); expect(response.data).toMatchObject({ processed: true, result: 'success', webhookReceived: { path: 'test-webhook', method: 'POST', body: webhookData, timestamp: expect.any(String) } }); }); it('should wait for specific requests', async () => { // Since the global server is already handling these endpoints, // we'll just make the requests and verify they succeed const responses = await Promise.all([ axios.get(`${baseUrl}/api/v1/workflows`), axios.get(`${baseUrl}/api/v1/executions`) ]); expect(responses).toHaveLength(2); expect(responses[0].status).toBe(200); expect(responses[0].config.url).toContain('/api/v1/workflows'); expect(responses[1].status).toBe(200); expect(responses[1].config.url).toContain('/api/v1/executions'); }, { timeout: 10000 }); // Increase timeout for this specific test it('should work with scoped handlers', async () => { // First add the scoped handler server.use( http.get('*/api/v1/scoped', () => { return HttpResponse.json({ scoped: true }); }) ); // Make the request while handler is active const response = await axios.get(`${baseUrl}/api/v1/scoped`); expect(response.data).toEqual({ scoped: true }); // Reset handlers to remove the scoped handler server.resetHandlers(); // Verify the scoped handler is no longer active // Since there's no handler for this endpoint now, it should fall through to the catch-all try { await axios.get(`${baseUrl}/api/v1/scoped`); expect.fail('Should have returned 501'); } catch (error: any) { expect(error.response.status).toBe(501); } }); }); describe('Factory Functions', () => { it('should create workflows using factory', async () => { const { workflowFactory } = await import('../mocks/n8n-api/data/workflows'); const simpleWorkflow = workflowFactory.simple('n8n-nodes-base.slack', { resource: 'message', operation: 'post', channel: '#general', text: 'Hello from test' }); expect(simpleWorkflow).toMatchObject({ id: expect.stringMatching(/^workflow_\d+$/), name: 'Test n8n-nodes-base.slack Workflow', // Factory uses nodeType in the name active: true, nodes: expect.arrayContaining([ expect.objectContaining({ type: 'n8n-nodes-base.start' }), expect.objectContaining({ type: 'n8n-nodes-base.slack', parameters: { resource: 'message', operation: 'post', channel: '#general', text: 'Hello from test' } }) ]) }); }); it('should create executions using factory', async () => { const { executionFactory } = await import('../mocks/n8n-api/data/executions'); const successExecution = executionFactory.success('workflow_123'); const errorExecution = executionFactory.error('workflow_456', { message: 'Connection timeout', node: 'http_request_1' }); expect(successExecution).toMatchObject({ workflowId: 'workflow_123', status: 'success', mode: 'manual' }); expect(errorExecution).toMatchObject({ workflowId: 'workflow_456', status: 'error', error: { message: 'Connection timeout', node: 'http_request_1' } }); }); }); });

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