import { describe, it, expect, vi, beforeEach } from 'vitest'; import axios from 'axios'; import { ApiService } from './api'; // Mock axios vi.mock('axios'); const mockedAxios = vi.mocked(axios); describe('ApiService', () => { let apiService: ApiService; beforeEach(() => { apiService = new ApiService(); vi.clearAllMocks(); }); describe('getWorkflowRuns', () => { it('should fetch workflow runs successfully', async () => { const mockRuns = [ { id: 1, name: 'Test Workflow', display_title: 'Test Run', status: 'completed', conclusion: 'success', created_at: '2024-01-01T10:00:00Z', repository: { id: 1, name: 'test-repo', full_name: 'test/test-repo', owner: { login: 'test-owner', avatar_url: 'https://github.com/test-owner.png' } }, actor: { login: 'test-actor', avatar_url: 'https://github.com/test-actor.png' } } ]; mockedAxios.get.mockResolvedValueOnce({ data: mockRuns }); const result = await apiService.getWorkflowRuns(); expect(mockedAxios.get).toHaveBeenCalledWith('/api/workflow-runs'); expect(result).toEqual(mockRuns); }); it('should handle API errors', async () => { const errorMessage = 'Network Error'; mockedAxios.get.mockRejectedValueOnce(new Error(errorMessage)); await expect(apiService.getWorkflowRuns()).rejects.toThrow(errorMessage); }); }); describe('getRepositoryWorkflowRuns', () => { it('should fetch repository-specific workflow runs', async () => { const mockRuns = [ { id: 1, name: 'Test Workflow', display_title: 'Test Run', status: 'completed', conclusion: 'success', created_at: '2024-01-01T10:00:00Z' } ]; mockedAxios.get.mockResolvedValueOnce({ data: mockRuns }); const result = await apiService.getRepositoryWorkflowRuns('test-owner', 'test-repo'); expect(mockedAxios.get).toHaveBeenCalledWith('/api/repository/test-owner/test-repo/workflow-runs', { params: { limit: 10 } }); expect(result).toEqual(mockRuns); }); it('should handle repository not found', async () => { mockedAxios.get.mockRejectedValueOnce({ response: { status: 404 } }); await expect(apiService.getRepositoryWorkflowRuns('invalid', 'repo')).rejects.toMatchObject({ response: { status: 404 } }); }); }); describe('getConfig', () => { it('should fetch configuration successfully', async () => { const mockConfig = { repositories: [ { owner: 'test-owner', name: 'test-repo', full_name: 'test-owner/test-repo' } ] }; mockedAxios.get.mockResolvedValueOnce({ data: mockConfig }); const result = await apiService.getConfig(); expect(mockedAxios.get).toHaveBeenCalledWith('/api/config'); expect(result).toEqual(mockConfig); }); }); describe('getRateLimit', () => { it('should fetch rate limit information', async () => { const mockRateLimit = { limit: 5000, remaining: 4999, resetTime: 1640995200000, used: 1, resetTimeFormatted: '2022-01-01T00:00:00.000Z', timeUntilReset: 3600000 }; mockedAxios.get.mockResolvedValueOnce({ data: mockRateLimit }); const result = await apiService.getRateLimitInfo(); expect(mockedAxios.get).toHaveBeenCalledWith('/api/rate-limit'); expect(result).toEqual(mockRateLimit); }); }); describe('getCacheStats', () => { it('should fetch cache statistics', async () => { const mockStats = { size: 10, entries: ['key1', 'key2', 'key3'] }; mockedAxios.get.mockResolvedValueOnce({ data: mockStats }); const result = await apiService.getCacheStats(); expect(mockedAxios.get).toHaveBeenCalledWith('/api/cache/stats'); expect(result).toEqual(mockStats); }); }); describe('clearCache', () => { it('should clear cache successfully', async () => { const mockResponse = { message: 'Cache cleared successfully' }; mockedAxios.delete.mockResolvedValueOnce({ data: mockResponse }); const result = await apiService.clearCache(); expect(mockedAxios.delete).toHaveBeenCalledWith('/api/cache'); expect(result).toEqual(mockResponse); }); }); describe('error handling', () => { it('should handle network errors', async () => { mockedAxios.get.mockRejectedValueOnce(new Error('Network Error')); await expect(apiService.getWorkflowRuns()).rejects.toThrow('Network Error'); }); it('should handle HTTP errors', async () => { mockedAxios.get.mockRejectedValueOnce({ response: { status: 500, data: { error: 'Internal Server Error' } } }); await expect(apiService.getWorkflowRuns()).rejects.toMatchObject({ response: { status: 500, data: { error: 'Internal Server Error' } } }); }); }); });