/** * CheckApiHealthUseCase Test * * Tests for the health check use case that orchestrates health checks and emits events. */ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { CheckApiHealthUseCase } from './CheckApiHealthUseCase'; import { HealthCheckQuery, HealthCheckResult } from '../ports/HealthCheckQuery'; import { HealthEventPublisher } from '../ports/HealthEventPublisher'; describe('CheckApiHealthUseCase', () => { let mockHealthCheckAdapter: HealthCheckQuery; let mockEventPublisher: HealthEventPublisher; let useCase: CheckApiHealthUseCase; beforeEach(() => { mockHealthCheckAdapter = { performHealthCheck: vi.fn(), getStatus: vi.fn(), getHealth: vi.fn(), getReliability: vi.fn(), isAvailable: vi.fn(), }; mockEventPublisher = { publishHealthCheckCompleted: vi.fn(), publishHealthCheckFailed: vi.fn(), publishHealthCheckTimeout: vi.fn(), publishConnected: vi.fn(), publishDisconnected: vi.fn(), publishDegraded: vi.fn(), publishChecking: vi.fn(), }; useCase = new CheckApiHealthUseCase({ healthCheckAdapter: mockHealthCheckAdapter, eventPublisher: mockEventPublisher, }); }); describe('execute', () => { it('should perform health check and publish completed event when healthy', async () => { const mockResult: HealthCheckResult = { healthy: true, responseTime: 100, timestamp: new Date('2024-01-01T00:00:00Z'), }; mockHealthCheckAdapter.performHealthCheck.mockResolvedValue(mockResult); const result = await useCase.execute(); expect(mockHealthCheckAdapter.performHealthCheck).toHaveBeenCalledTimes(1); expect(mockEventPublisher.publishHealthCheckCompleted).toHaveBeenCalledWith({ healthy: true, responseTime: 100, timestamp: mockResult.timestamp, }); expect(mockEventPublisher.publishHealthCheckFailed).not.toHaveBeenCalled(); expect(result).toEqual(mockResult); }); it('should perform health check and publish failed event when unhealthy', async () => { const mockResult: HealthCheckResult = { healthy: false, responseTime: 200, error: 'Connection timeout', timestamp: new Date('2024-01-01T00:00:00Z'), }; mockHealthCheckAdapter.performHealthCheck.mockResolvedValue(mockResult); const result = await useCase.execute(); expect(mockHealthCheckAdapter.performHealthCheck).toHaveBeenCalledTimes(1); expect(mockEventPublisher.publishHealthCheckFailed).toHaveBeenCalledWith({ error: 'Connection timeout', timestamp: mockResult.timestamp, }); expect(mockEventPublisher.publishHealthCheckCompleted).not.toHaveBeenCalled(); expect(result).toEqual(mockResult); }); it('should handle errors during health check and publish failed event', async () => { const errorMessage = 'Network error'; mockHealthCheckAdapter.performHealthCheck.mockRejectedValue(new Error(errorMessage)); const result = await useCase.execute(); expect(mockHealthCheckAdapter.performHealthCheck).toHaveBeenCalledTimes(1); expect(mockEventPublisher.publishHealthCheckFailed).toHaveBeenCalledWith({ error: errorMessage, timestamp: expect.any(Date), }); expect(mockEventPublisher.publishHealthCheckCompleted).not.toHaveBeenCalled(); expect(result.healthy).toBe(false); expect(result.responseTime).toBe(0); expect(result.error).toBe(errorMessage); expect(result.timestamp).toBeInstanceOf(Date); }); it('should handle non-Error objects during health check', async () => { mockHealthCheckAdapter.performHealthCheck.mockRejectedValue('String error'); const result = await useCase.execute(); expect(mockEventPublisher.publishHealthCheckFailed).toHaveBeenCalledWith({ error: 'String error', timestamp: expect.any(Date), }); expect(result.error).toBe('String error'); }); it('should handle unknown errors during health check', async () => { mockHealthCheckAdapter.performHealthCheck.mockRejectedValue(null); const result = await useCase.execute(); expect(mockEventPublisher.publishHealthCheckFailed).toHaveBeenCalledWith({ error: 'Unknown error', timestamp: expect.any(Date), }); expect(result.error).toBe('Unknown error'); }); it('should use default error message when result has no error', async () => { const mockResult: HealthCheckResult = { healthy: false, responseTime: 150, timestamp: new Date('2024-01-01T00:00:00Z'), }; mockHealthCheckAdapter.performHealthCheck.mockResolvedValue(mockResult); const result = await useCase.execute(); expect(mockEventPublisher.publishHealthCheckFailed).toHaveBeenCalledWith({ error: 'Unknown error', timestamp: mockResult.timestamp, }); expect(result.error).toBe('Unknown error'); }); }); });