mirror of
https://github.com/dcarrillo/atalaya.git
synced 2026-04-18 02:24:05 +00:00
156 lines
4.3 KiB
TypeScript
156 lines
4.3 KiB
TypeScript
import { describe, it, expect, vi } from 'vitest';
|
|
import { getMonitorStates, writeCheckResults, updateMonitorStates, recordAlert } from './db.js';
|
|
|
|
function createMockDatabase() {
|
|
const mockRun = vi.fn().mockResolvedValue({});
|
|
const mockAll = vi.fn().mockResolvedValue({ results: [] });
|
|
const mockBind = vi.fn().mockReturnThis();
|
|
|
|
const mockStmt = {
|
|
bind: mockBind,
|
|
run: mockRun,
|
|
all: mockAll,
|
|
};
|
|
|
|
const mockPrepare = vi.fn().mockReturnValue(mockStmt);
|
|
const mockBatch = vi.fn().mockResolvedValue([]);
|
|
|
|
type MockDb = D1Database & {
|
|
_mockStmt: typeof mockStmt;
|
|
_mockBind: typeof mockBind;
|
|
_mockAll: typeof mockAll;
|
|
_mockRun: typeof mockRun;
|
|
};
|
|
|
|
return {
|
|
prepare: mockPrepare,
|
|
batch: mockBatch,
|
|
_mockStmt: mockStmt,
|
|
_mockBind: mockBind,
|
|
_mockAll: mockAll,
|
|
_mockRun: mockRun,
|
|
} as unknown as MockDb;
|
|
}
|
|
|
|
describe('getMonitorStates', () => {
|
|
it('returns empty array when no states exist', async () => {
|
|
const db = createMockDatabase();
|
|
const result = await getMonitorStates(db);
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('returns monitor states from database', async () => {
|
|
const db = createMockDatabase();
|
|
const mockStates = [
|
|
{
|
|
monitor_name: 'test-monitor',
|
|
current_status: 'up',
|
|
consecutive_failures: 0,
|
|
last_status_change: 1_700_000_000,
|
|
last_checked: 1_700_001_000,
|
|
},
|
|
];
|
|
db._mockAll.mockResolvedValue({ results: mockStates });
|
|
|
|
const result = await getMonitorStates(db);
|
|
expect(result).toEqual(mockStates);
|
|
expect(db.prepare).toHaveBeenCalledWith(expect.stringContaining('SELECT'));
|
|
});
|
|
});
|
|
|
|
describe('writeCheckResults', () => {
|
|
it('does nothing when writes array is empty', async () => {
|
|
const db = createMockDatabase();
|
|
await writeCheckResults(db, []);
|
|
expect(db.batch).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('batches writes to database', async () => {
|
|
const db = createMockDatabase();
|
|
const writes = [
|
|
{
|
|
monitorName: 'test-monitor',
|
|
checkedAt: 1_700_000_000,
|
|
status: 'up',
|
|
responseTimeMs: 150,
|
|
errorMessage: '',
|
|
attempts: 1,
|
|
},
|
|
{
|
|
monitorName: 'test-monitor-2',
|
|
checkedAt: 1_700_000_000,
|
|
status: 'down',
|
|
responseTimeMs: 5000,
|
|
errorMessage: 'Timeout',
|
|
attempts: 3,
|
|
},
|
|
];
|
|
|
|
await writeCheckResults(db, writes);
|
|
expect(db.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO check_results'));
|
|
expect(db.batch).toHaveBeenCalledTimes(1);
|
|
expect(db._mockBind).toHaveBeenCalledTimes(2);
|
|
});
|
|
});
|
|
|
|
describe('updateMonitorStates', () => {
|
|
it('does nothing when updates array is empty', async () => {
|
|
const db = createMockDatabase();
|
|
await updateMonitorStates(db, []);
|
|
expect(db.batch).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('batches state updates to database', async () => {
|
|
const db = createMockDatabase();
|
|
const updates = [
|
|
{
|
|
monitorName: 'test-monitor',
|
|
currentStatus: 'down',
|
|
consecutiveFailures: 3,
|
|
lastStatusChange: 1_700_000_000,
|
|
lastChecked: 1_700_001_000,
|
|
},
|
|
];
|
|
|
|
await updateMonitorStates(db, updates);
|
|
expect(db.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO monitor_state'));
|
|
expect(db.prepare).toHaveBeenCalledWith(expect.stringContaining('ON CONFLICT'));
|
|
expect(db.batch).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('recordAlert', () => {
|
|
it('inserts alert record', async () => {
|
|
const db = createMockDatabase();
|
|
vi.useFakeTimers();
|
|
vi.setSystemTime(new Date('2024-01-15T12:00:00Z'));
|
|
|
|
await recordAlert(db, 'test-monitor', 'down', 'slack', true);
|
|
|
|
expect(db.prepare).toHaveBeenCalledWith(expect.stringContaining('INSERT INTO alerts'));
|
|
expect(db._mockBind).toHaveBeenCalledWith(
|
|
'test-monitor',
|
|
'down',
|
|
expect.any(Number),
|
|
'slack',
|
|
1
|
|
);
|
|
expect(db._mockRun).toHaveBeenCalled();
|
|
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('records failure correctly', async () => {
|
|
const db = createMockDatabase();
|
|
await recordAlert(db, 'test-monitor', 'recovery', 'discord', false);
|
|
|
|
expect(db._mockBind).toHaveBeenCalledWith(
|
|
'test-monitor',
|
|
'recovery',
|
|
expect.any(Number),
|
|
'discord',
|
|
0
|
|
);
|
|
});
|
|
});
|