client.test.ts.bak•11.8 kB
/**
 * N8nApiClient unit tests
 */
import '@jest/globals';
import axios from 'axios';
import { N8nApiClient } from '../../../src/api/client.js';
import { EnvConfig } from '../../../src/config/environment.js';
import { N8nApiError } from '../../../src/errors/index.js';
import { createMockAxiosInstance, createMockAxiosResponse } from '../../mocks/axios-mock.js';
import { mockApiResponses } from '../../mocks/n8n-fixtures.js';
// Mock axios
jest.mock('axios', () => ({
  create: jest.fn(),
}));
describe('N8nApiClient', () => {
  // Mock configuration
  const mockConfig: EnvConfig = {
    n8nApiUrl: 'https://n8n.example.com/api/v1',
    n8nApiKey: 'test-api-key',
    debug: false,
  };
  
  // Mock axios instance
  let mockAxios;
  
  beforeEach(() => {
    mockAxios = createMockAxiosInstance();
    (axios.create as jest.Mock).mockReturnValue(mockAxios);
  });
  
  afterEach(() => {
    jest.clearAllMocks();
    mockAxios.reset();
  });
  
  describe('constructor', () => {
    it('should create an axios instance with correct config', () => {
      // Execute
      new N8nApiClient(mockConfig);
      
      // Assert
      expect(axios.create).toHaveBeenCalledWith({
        baseURL: mockConfig.n8nApiUrl,
        headers: {
          'X-N8N-API-KEY': mockConfig.n8nApiKey,
          'Accept': 'application/json',
        },
        timeout: 10000,
      });
    });
    
    it('should set up debug interceptors when debug is true', () => {
      // Setup
      const debugConfig = { ...mockConfig, debug: true };
      
      // Execute
      new N8nApiClient(debugConfig);
      
      // Assert
      expect(mockAxios.interceptors.request.use).toHaveBeenCalled();
      expect(mockAxios.interceptors.response.use).toHaveBeenCalled();
    });
    
    it('should not set up debug interceptors when debug is false', () => {
      // Execute
      new N8nApiClient(mockConfig);
      
      // Assert
      expect(mockAxios.interceptors.request.use).not.toHaveBeenCalled();
      expect(mockAxios.interceptors.response.use).not.toHaveBeenCalled();
    });
  });
  
  describe('checkConnectivity', () => {
    it('should resolve when connectivity check succeeds', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      mockAxios.addMockResponse('get', '/workflows', {
        status: 200,
        data: { data: [] },
      });
      
      // Execute & Assert
      await expect(client.checkConnectivity()).resolves.not.toThrow();
    });
    
    it('should throw an error when response status is not 200', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      mockAxios.addMockResponse('get', '/workflows', {
        status: 500,
        data: { message: 'Server error' },
      });
      
      // Execute & Assert
      await expect(client.checkConnectivity()).rejects.toThrow(N8nApiError);
    });
    
    it('should throw an error when request fails', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      mockAxios.addMockResponse('get', '/workflows', new Error('Network error'));
      
      // Execute & Assert
      await expect(client.checkConnectivity()).rejects.toThrow();
    });
  });
  
  describe('getWorkflows', () => {
    it('should return workflows array on success', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const mockWorkflows = mockApiResponses.workflows.list;
      mockAxios.addMockResponse('get', '/workflows', {
        status: 200,
        data: mockWorkflows,
      });
      
      // Execute
      const result = await client.getWorkflows();
      
      // Assert
      expect(result).toEqual(mockWorkflows.data);
      expect(mockAxios.get).toHaveBeenCalledWith('/workflows');
    });
    
    it('should handle empty response', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      mockAxios.addMockResponse('get', '/workflows', {
        status: 200,
        data: {},
      });
      
      // Execute
      const result = await client.getWorkflows();
      
      // Assert
      expect(result).toEqual([]);
    });
    
    it('should throw an error when request fails', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      mockAxios.addMockResponse('get', '/workflows', new Error('Network error'));
      
      // Execute & Assert
      await expect(client.getWorkflows()).rejects.toThrow();
    });
  });
  
  describe('getWorkflow', () => {
    it('should return a workflow on success', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const mockWorkflow = mockApiResponses.workflows.single(workflowId);
      mockAxios.addMockResponse('get', `/workflows/${workflowId}`, {
        status: 200,
        data: mockWorkflow,
      });
      
      // Execute
      const result = await client.getWorkflow(workflowId);
      
      // Assert
      expect(result).toEqual(mockWorkflow);
      expect(mockAxios.get).toHaveBeenCalledWith(`/workflows/${workflowId}`);
    });
    
    it('should throw an error when request fails', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      mockAxios.addMockResponse('get', `/workflows/${workflowId}`, new Error('Network error'));
      
      // Execute & Assert
      await expect(client.getWorkflow(workflowId)).rejects.toThrow();
    });
  });
  
  // Additional tests for other API client methods
  describe('executeWorkflow', () => {
    it('should execute a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const mockData = { inputs: { value: 'test' } };
      const mockResponse = { executionId: 'exec-123', success: true };
      
      mockAxios.addMockResponse('post', `/workflows/${workflowId}/execute`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.executeWorkflow(workflowId, mockData);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.post).toHaveBeenCalledWith(`/workflows/${workflowId}/execute`, mockData);
    });
  });
  
  describe('createWorkflow', () => {
    it('should create a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const newWorkflow = { name: 'New Workflow', nodes: [], connections: {} };
      const mockResponse = mockApiResponses.workflows.create(newWorkflow);
      
      mockAxios.addMockResponse('post', '/workflows', {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.createWorkflow(newWorkflow);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.post).toHaveBeenCalledWith('/workflows', newWorkflow);
    });
  });
  
  describe('updateWorkflow', () => {
    it('should update a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const updatedWorkflow = { name: 'Updated Workflow', nodes: [], connections: {} };
      const mockResponse = mockApiResponses.workflows.update(workflowId, updatedWorkflow);
      
      mockAxios.addMockResponse('put', `/workflows/${workflowId}`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.updateWorkflow(workflowId, updatedWorkflow);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.put).toHaveBeenCalledWith(`/workflows/${workflowId}`, updatedWorkflow);
    });
  });
  
  describe('deleteWorkflow', () => {
    it('should delete a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const mockResponse = mockApiResponses.workflows.delete;
      
      mockAxios.addMockResponse('delete', `/workflows/${workflowId}`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.deleteWorkflow(workflowId);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.delete).toHaveBeenCalledWith(`/workflows/${workflowId}`);
    });
  });
  
  describe('activateWorkflow', () => {
    it('should activate a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const mockResponse = mockApiResponses.workflows.activate(workflowId);
      
      mockAxios.addMockResponse('post', `/workflows/${workflowId}/activate`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.activateWorkflow(workflowId);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.post).toHaveBeenCalledWith(`/workflows/${workflowId}/activate`);
    });
  });
  
  describe('deactivateWorkflow', () => {
    it('should deactivate a workflow successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const workflowId = 'test-workflow-1';
      const mockResponse = mockApiResponses.workflows.deactivate(workflowId);
      
      mockAxios.addMockResponse('post', `/workflows/${workflowId}/deactivate`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.deactivateWorkflow(workflowId);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.post).toHaveBeenCalledWith(`/workflows/${workflowId}/deactivate`);
    });
  });
  
  describe('getExecutions', () => {
    it('should return executions array on success', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const mockExecutions = mockApiResponses.executions.list;
      mockAxios.addMockResponse('get', '/executions', {
        status: 200,
        data: mockExecutions,
      });
      
      // Execute
      const result = await client.getExecutions();
      
      // Assert
      expect(result).toEqual(mockExecutions.data);
      expect(mockAxios.get).toHaveBeenCalledWith('/executions');
    });
  });
  
  describe('getExecution', () => {
    it('should return an execution on success', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const executionId = 'test-execution-1';
      const mockExecution = mockApiResponses.executions.single(executionId);
      mockAxios.addMockResponse('get', `/executions/${executionId}`, {
        status: 200,
        data: mockExecution,
      });
      
      // Execute
      const result = await client.getExecution(executionId);
      
      // Assert
      expect(result).toEqual(mockExecution);
      expect(mockAxios.get).toHaveBeenCalledWith(`/executions/${executionId}`);
    });
  });
  
  describe('deleteExecution', () => {
    it('should delete an execution successfully', async () => {
      // Setup
      const client = new N8nApiClient(mockConfig);
      const executionId = 'test-execution-1';
      const mockResponse = mockApiResponses.executions.delete;
      
      mockAxios.addMockResponse('delete', `/executions/${executionId}`, {
        status: 200,
        data: mockResponse,
      });
      
      // Execute
      const result = await client.deleteExecution(executionId);
      
      // Assert
      expect(result).toEqual(mockResponse);
      expect(mockAxios.delete).toHaveBeenCalledWith(`/executions/${executionId}`);
    });
  });
});