Sync DNS2 production changes - removed obsolete test suite and refactored structure

This commit is contained in:
Krystie
2026-03-23 10:47:15 +01:00
parent 1ac50918ab
commit d76644d948
288 changed files with 8965 additions and 15731 deletions

View File

@@ -1,361 +0,0 @@
// health-checker.js exports a singleton that reads config/history from disk on construction.
// The jest.setup.js suppresses console and the files don't exist in test env, so it falls back to defaults.
const healthChecker = require('../health-checker');
beforeEach(() => {
// Reset singleton state between tests
healthChecker.currentStatus = new Map();
healthChecker.incidents = [];
healthChecker.history = {};
healthChecker.config = { services: {} };
healthChecker.checking = false;
if (healthChecker.checkInterval) {
clearInterval(healthChecker.checkInterval);
healthChecker.checkInterval = null;
}
});
afterAll(() => {
healthChecker.stop();
});
describe('evaluateHealth', () => {
test('returns true for status code in expectedStatusCodes', () => {
expect(healthChecker.evaluateHealth(200, '', { expectedStatusCodes: [200, 201] })).toBe(true);
});
test('returns false for status code not in expectedStatusCodes', () => {
expect(healthChecker.evaluateHealth(500, '', { expectedStatusCodes: [200] })).toBe(false);
});
test('uses default expected codes when not configured', () => {
expect(healthChecker.evaluateHealth(200, '', {})).toBe(true);
expect(healthChecker.evaluateHealth(301, '', {})).toBe(true);
expect(healthChecker.evaluateHealth(500, '', {})).toBe(false);
});
test('returns false when expectedBodyPattern regex does not match', () => {
expect(healthChecker.evaluateHealth(200, 'error occurred', {
expectedBodyPattern: 'ok|healthy',
})).toBe(false);
});
test('returns true when expectedBodyPattern regex matches', () => {
expect(healthChecker.evaluateHealth(200, 'status: healthy', {
expectedBodyPattern: 'healthy',
})).toBe(true);
});
test('returns false when expectedBodyContains text is missing', () => {
expect(healthChecker.evaluateHealth(200, 'some response', {
expectedBodyContains: 'healthy',
})).toBe(false);
});
test('returns true when expectedBodyContains text is present', () => {
expect(healthChecker.evaluateHealth(200, 'service is healthy', {
expectedBodyContains: 'healthy',
})).toBe(true);
});
test('checks all conditions: status code AND body pattern AND body contains', () => {
// All pass
expect(healthChecker.evaluateHealth(200, 'healthy ok', {
expectedStatusCodes: [200],
expectedBodyPattern: 'healthy',
expectedBodyContains: 'ok',
})).toBe(true);
// Status fails
expect(healthChecker.evaluateHealth(500, 'healthy ok', {
expectedStatusCodes: [200],
expectedBodyPattern: 'healthy',
expectedBodyContains: 'ok',
})).toBe(false);
// Body pattern fails
expect(healthChecker.evaluateHealth(200, 'error', {
expectedStatusCodes: [200],
expectedBodyPattern: 'healthy',
expectedBodyContains: 'error',
})).toBe(false);
});
});
describe('calculateSeverity', () => {
test('returns critical for outage', () => {
expect(healthChecker.calculateSeverity('outage')).toBe('critical');
});
test('returns high for sla-violation', () => {
expect(healthChecker.calculateSeverity('sla-violation')).toBe('high');
});
test('returns medium for slow-response', () => {
expect(healthChecker.calculateSeverity('slow-response')).toBe('medium');
});
test('returns low for unknown type', () => {
expect(healthChecker.calculateSeverity('unknown')).toBe('low');
});
});
describe('calculateUptime', () => {
test('returns 100 when no history', () => {
expect(healthChecker.calculateUptime('svc1')).toBe(100);
});
test('returns 100 when all checks are up', () => {
const now = new Date().toISOString();
healthChecker.history['svc1'] = [
{ status: 'up', timestamp: now },
{ status: 'up', timestamp: now },
{ status: 'up', timestamp: now },
];
expect(healthChecker.calculateUptime('svc1')).toBe(100);
});
test('returns 0 when all checks are down', () => {
const now = new Date().toISOString();
healthChecker.history['svc1'] = [
{ status: 'down', timestamp: now },
{ status: 'down', timestamp: now },
];
expect(healthChecker.calculateUptime('svc1')).toBe(0);
});
test('returns 50 when half are up', () => {
const now = new Date().toISOString();
healthChecker.history['svc1'] = [
{ status: 'up', timestamp: now },
{ status: 'down', timestamp: now },
];
expect(healthChecker.calculateUptime('svc1')).toBe(50);
});
});
describe('calculateAverageResponseTime', () => {
test('returns 0 when no history', () => {
expect(healthChecker.calculateAverageResponseTime('svc1')).toBe(0);
});
test('calculates correct average', () => {
const now = new Date().toISOString();
healthChecker.history['svc1'] = [
{ responseTime: 100, timestamp: now },
{ responseTime: 200, timestamp: now },
{ responseTime: 300, timestamp: now },
];
expect(healthChecker.calculateAverageResponseTime('svc1')).toBe(200);
});
});
describe('calculatePercentile', () => {
test('returns p95 correctly', () => {
const values = Array.from({ length: 100 }, (_, i) => i + 1);
expect(healthChecker.calculatePercentile(values, 95)).toBe(95);
});
test('returns p99 correctly', () => {
const values = Array.from({ length: 100 }, (_, i) => i + 1);
expect(healthChecker.calculatePercentile(values, 99)).toBe(99);
});
test('returns 0 for empty array', () => {
expect(healthChecker.calculatePercentile([], 95)).toBe(0);
});
test('handles single-element array', () => {
expect(healthChecker.calculatePercentile([42], 95)).toBe(42);
});
test('sorts values before calculating', () => {
const unsorted = [50, 10, 90, 30, 70, 20, 80, 40, 60, 100];
expect(healthChecker.calculatePercentile(unsorted, 50)).toBe(50);
});
});
describe('recordStatus', () => {
test('adds status to currentStatus map', () => {
const status = { serviceId: 'svc1', status: 'up', timestamp: new Date().toISOString() };
healthChecker.recordStatus('svc1', status);
expect(healthChecker.currentStatus.get('svc1')).toEqual(status);
});
test('creates history array for new serviceId', () => {
const status = { serviceId: 'new-svc', status: 'up', timestamp: new Date().toISOString() };
healthChecker.recordStatus('new-svc', status);
expect(healthChecker.history['new-svc']).toHaveLength(1);
});
test('appends to existing history', () => {
healthChecker.history['svc1'] = [{ status: 'up', timestamp: new Date().toISOString() }];
const status = { status: 'down', timestamp: new Date().toISOString() };
healthChecker.recordStatus('svc1', status);
expect(healthChecker.history['svc1']).toHaveLength(2);
});
test('emits status-check event', () => {
const handler = jest.fn();
healthChecker.on('status-check', handler);
healthChecker.recordStatus('svc1', { status: 'up', timestamp: new Date().toISOString() });
expect(handler).toHaveBeenCalled();
healthChecker.removeListener('status-check', handler);
});
});
describe('createIncident', () => {
test('creates incident with correct structure', () => {
const status = { timestamp: new Date().toISOString() };
healthChecker.createIncident('svc1', 'outage', 'Service down', status);
expect(healthChecker.incidents).toHaveLength(1);
expect(healthChecker.incidents[0].serviceId).toBe('svc1');
expect(healthChecker.incidents[0].type).toBe('outage');
expect(healthChecker.incidents[0].status).toBe('open');
expect(healthChecker.incidents[0].severity).toBe('critical');
expect(healthChecker.incidents[0].occurrences).toBe(1);
});
test('emits incident-created event', () => {
const handler = jest.fn();
healthChecker.on('incident-created', handler);
healthChecker.createIncident('svc1', 'outage', 'Down', { timestamp: new Date().toISOString() });
expect(handler).toHaveBeenCalledWith(expect.objectContaining({ serviceId: 'svc1' }));
healthChecker.removeListener('incident-created', handler);
});
test('does not duplicate open incidents of same type', () => {
const status = { timestamp: new Date().toISOString() };
healthChecker.createIncident('svc1', 'outage', 'Down', status);
healthChecker.createIncident('svc1', 'outage', 'Still down', status);
expect(healthChecker.incidents).toHaveLength(1);
});
test('increments occurrences on existing open incident', () => {
const status = { timestamp: new Date().toISOString() };
healthChecker.createIncident('svc1', 'outage', 'Down', status);
healthChecker.createIncident('svc1', 'outage', 'Still down', status);
expect(healthChecker.incidents[0].occurrences).toBe(2);
});
});
describe('resolveIncident', () => {
test('marks incident as resolved with duration', () => {
const created = new Date(Date.now() - 60000).toISOString();
const resolved = new Date().toISOString();
healthChecker.createIncident('svc1', 'outage', 'Down', { timestamp: created });
healthChecker.resolveIncident('svc1', 'outage', { timestamp: resolved });
expect(healthChecker.incidents[0].status).toBe('resolved');
expect(healthChecker.incidents[0].resolvedAt).toBe(resolved);
expect(healthChecker.incidents[0].duration).toBeGreaterThan(0);
});
test('emits incident-resolved event', () => {
const handler = jest.fn();
healthChecker.on('incident-resolved', handler);
const ts = new Date().toISOString();
healthChecker.createIncident('svc1', 'outage', 'Down', { timestamp: ts });
healthChecker.resolveIncident('svc1', 'outage', { timestamp: ts });
expect(handler).toHaveBeenCalled();
healthChecker.removeListener('incident-resolved', handler);
});
test('handles no matching incident gracefully', () => {
// Should not throw
healthChecker.resolveIncident('nonexistent', 'outage', { timestamp: new Date().toISOString() });
expect(healthChecker.incidents).toHaveLength(0);
});
});
describe('configureService / removeService', () => {
test('adds service config with defaults', () => {
healthChecker.configureService('svc1', { url: 'http://localhost:3000', name: 'Test' });
expect(healthChecker.config.services['svc1']).toBeDefined();
expect(healthChecker.config.services['svc1'].method).toBe('GET');
expect(healthChecker.config.services['svc1'].timeout).toBe(10000);
});
test('removes service and cleans up', () => {
healthChecker.configureService('svc1', { url: 'http://localhost:3000' });
healthChecker.currentStatus.set('svc1', { status: 'up' });
healthChecker.history['svc1'] = [{ status: 'up' }];
healthChecker.removeService('svc1');
expect(healthChecker.config.services['svc1']).toBeUndefined();
expect(healthChecker.currentStatus.has('svc1')).toBe(false);
expect(healthChecker.history['svc1']).toBeUndefined();
});
});
describe('getOpenIncidents / getIncidentHistory', () => {
test('getOpenIncidents returns only open incidents', () => {
const ts = new Date().toISOString();
healthChecker.createIncident('svc1', 'outage', 'Down', { timestamp: ts });
healthChecker.createIncident('svc2', 'slow-response', 'Slow', { timestamp: ts });
healthChecker.resolveIncident('svc1', 'outage', { timestamp: ts });
expect(healthChecker.getOpenIncidents()).toHaveLength(1);
expect(healthChecker.getOpenIncidents()[0].serviceId).toBe('svc2');
});
test('getIncidentHistory returns reverse chronological order', () => {
const ts = new Date().toISOString();
healthChecker.createIncident('svc1', 'outage', 'First', { timestamp: ts });
healthChecker.createIncident('svc2', 'outage', 'Second', { timestamp: ts });
const history = healthChecker.getIncidentHistory();
expect(history[0].serviceId).toBe('svc2');
});
});
describe('getServiceStats', () => {
test('returns null for service with no history', () => {
expect(healthChecker.getServiceStats('nonexistent')).toBeNull();
});
test('returns correct stats structure', () => {
const now = new Date().toISOString();
healthChecker.history['svc1'] = [
{ status: 'up', responseTime: 100, timestamp: now },
{ status: 'up', responseTime: 200, timestamp: now },
{ status: 'down', responseTime: 0, timestamp: now },
];
const stats = healthChecker.getServiceStats('svc1');
expect(stats.totalChecks).toBe(3);
expect(stats.upChecks).toBe(2);
expect(stats.downChecks).toBe(1);
expect(stats.responseTime.avg).toBe(100);
expect(stats.responseTime.min).toBe(0);
expect(stats.responseTime.max).toBe(200);
expect(stats.responseTime).toHaveProperty('p95');
expect(stats.responseTime).toHaveProperty('p99');
});
});
describe('start / stop', () => {
test('start sets checking flag', () => {
jest.useFakeTimers();
healthChecker.start();
expect(healthChecker.checking).toBe(true);
healthChecker.stop();
jest.useRealTimers();
});
test('stop clears interval and checking flag', () => {
jest.useFakeTimers();
healthChecker.start();
healthChecker.stop();
expect(healthChecker.checking).toBe(false);
expect(healthChecker.checkInterval).toBeNull();
jest.useRealTimers();
});
test('start is idempotent', () => {
jest.useFakeTimers();
healthChecker.start();
const firstInterval = healthChecker.checkInterval;
healthChecker.start();
expect(healthChecker.checkInterval).toBe(firstInterval);
healthChecker.stop();
jest.useRealTimers();
});
});