mirror of
https://github.com/dcarrillo/atalaya.git
synced 2026-04-18 10:34:06 +00:00
155
src/db.test.ts
Normal file
155
src/db.test.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
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
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user