import { describe, expect, it } from 'bun:test'; import { ABANDONED_THRESHOLD, ABANDONED_WINDOW_MS, type AbandonedOperationRecord, auditAbandonedOperations, } from './abandoned-operations'; const NOW = Date.parse('2026-08-05T12:00:00Z'); const now = () => NOW; function records( moduleId: string, operation: 'deploy' | 'backup', count: number, ageMs = 60_000, ): AbandonedOperationRecord[] { return Array.from({ length: count }, () => ({ moduleId, operation, startedAt: NOW - ageMs, })); } describe('auditAbandonedOperations', () => { it('says nothing about a single abandonment — that is an operator hitting Ctrl-C', () => { const findings = auditAbandonedOperations({ records: records('forgejo', 'backup', ABANDONED_THRESHOLD - 1), now, }); expect(findings).toEqual([]); }); it('flags a module whose same operation keeps dying', () => { const findings = auditAbandonedOperations({ records: records('forgejo', 'backup', 63), now, }); expect(findings).toHaveLength(1); expect(findings[0]?.subject).toBe('forgejo'); expect(findings[0]?.severity).toBe('drift'); expect(findings[0]?.message).toContain('63 backup operations abandoned'); }); // The point of grouping: a module whose backups are being killed and whose // deploys are fine should say exactly that. it('reports each operation kind separately', () => { const findings = auditAbandonedOperations({ records: [...records('forgejo', 'backup', 5), ...records('technitium', 'deploy', 5)], now, }); expect(findings.map((f) => f.subject)).toEqual(['forgejo', 'technitium']); expect(findings[1]?.message).toContain('deploy operations'); }); it('ignores abandonments older than the window, so a fixed module stops being flagged', () => { const findings = auditAbandonedOperations({ records: records('forgejo', 'backup', 60, ABANDONED_WINDOW_MS + 60_000), now, }); expect(findings).toEqual([]); }); it('does not merge two modules into one unactionable count', () => { const findings = auditAbandonedOperations({ records: [...records('forgejo', 'backup', 2), ...records('lunacycle', 'backup', 2)], now, }); expect(findings).toEqual([]); }); });