core tests
This commit is contained in:
145
core/health/use-cases/CheckApiHealthUseCase.test.ts
Normal file
145
core/health/use-cases/CheckApiHealthUseCase.test.ts
Normal file
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* 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, CheckApiHealthUseCasePorts } 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');
|
||||
});
|
||||
});
|
||||
});
|
||||
54
core/health/use-cases/GetConnectionStatusUseCase.test.ts
Normal file
54
core/health/use-cases/GetConnectionStatusUseCase.test.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { GetConnectionStatusUseCase, GetConnectionStatusUseCasePorts } from './GetConnectionStatusUseCase';
|
||||
import { HealthCheckQuery, ConnectionHealth } from '../ports/HealthCheckQuery';
|
||||
|
||||
describe('GetConnectionStatusUseCase', () => {
|
||||
it('should return connection status and metrics from the health check adapter', async () => {
|
||||
// Arrange
|
||||
const mockHealth: ConnectionHealth = {
|
||||
status: 'connected',
|
||||
lastCheck: new Date('2024-01-01T10:00:00Z'),
|
||||
lastSuccess: new Date('2024-01-01T10:00:00Z'),
|
||||
lastFailure: null,
|
||||
consecutiveFailures: 0,
|
||||
totalRequests: 100,
|
||||
successfulRequests: 99,
|
||||
failedRequests: 1,
|
||||
averageResponseTime: 150,
|
||||
};
|
||||
const mockReliability = 0.99;
|
||||
|
||||
const mockHealthCheckAdapter = {
|
||||
getHealth: vi.fn().mockReturnValue(mockHealth),
|
||||
getReliability: vi.fn().mockReturnValue(mockReliability),
|
||||
performHealthCheck: vi.fn(),
|
||||
getStatus: vi.fn(),
|
||||
isAvailable: vi.fn(),
|
||||
} as unknown as HealthCheckQuery;
|
||||
|
||||
const ports: GetConnectionStatusUseCasePorts = {
|
||||
healthCheckAdapter: mockHealthCheckAdapter,
|
||||
};
|
||||
|
||||
const useCase = new GetConnectionStatusUseCase(ports);
|
||||
|
||||
// Act
|
||||
const result = await useCase.execute();
|
||||
|
||||
// Assert
|
||||
expect(mockHealthCheckAdapter.getHealth).toHaveBeenCalled();
|
||||
expect(mockHealthCheckAdapter.getReliability).toHaveBeenCalled();
|
||||
expect(result).toEqual({
|
||||
status: 'connected',
|
||||
reliability: 0.99,
|
||||
totalRequests: 100,
|
||||
successfulRequests: 99,
|
||||
failedRequests: 1,
|
||||
consecutiveFailures: 0,
|
||||
averageResponseTime: 150,
|
||||
lastCheck: mockHealth.lastCheck,
|
||||
lastSuccess: mockHealth.lastSuccess,
|
||||
lastFailure: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user