import { describe, expect, test } from 'bun:test'; import type { ModuleManifest } from '../../manifest/schema'; import { auditDetectWithoutConverge } from './detect-without-converge'; function mod( id: string, manifest: Partial, state = 'INSTALLED', ): { id: string; state: string; manifest: ModuleManifest } { return { id, state, manifest: manifest as ModuleManifest }; } const HOOK = { script: 'scripts/x.ts' }; describe('auditDetectWithoutConverge', () => { test('a convergence hook no subscription fires is drift', () => { // celilo#934's shape: the module has the correcting code and nothing runs // it, so drift is computed every health check and corrected never. const findings = auditDetectWithoutConverge({ modules: [mod('wireguard', { hooks: { reconcile_peers: HOOK } })], }); expect(findings).toHaveLength(1); expect(findings[0]?.code).toBe('converge_hook_never_fires'); expect(findings[0]?.message).toContain('reconcile_peers'); expect(findings[0]?.subject).toBe('wireguard'); }); test('the same module WIRED UP is not reported', () => { // This is `wireguard` after celilo#968. const findings = auditDetectWithoutConverge({ modules: [ mod('wireguard', { hooks: { reconcile_peers: HOOK }, subscriptions: [ { name: 'wireguard-peer-converge', pattern: 'timer.tick.15m', hook: 'reconcile_peers' }, ], } as Partial), ], }); expect(findings).toEqual([]); }); test('a subscription firing a DIFFERENT hook does not count', () => { const findings = auditDetectWithoutConverge({ modules: [ mod('m', { hooks: { reconcile_peers: HOOK, reconcile_routes: HOOK }, subscriptions: [{ name: 's', pattern: 'timer.tick.15m', hook: 'reconcile_routes' }], } as Partial), ], }); expect(findings).toHaveLength(1); expect(findings[0]?.message).toContain('reconcile_peers'); expect(findings[0]?.message).not.toContain('reconcile_routes'); }); test('a module with no convergence hook at all is not reported', () => { // A module that detects drift and declares no correcting hook is a missing // feature, not dead wiring. Guessing at it from `health_check` alone would // flag most of the fleet. expect( auditDetectWithoutConverge({ modules: [mod('caddy', { hooks: { health_check: { script: 'x.ts' } } })], }), ).toEqual([]); }); test('`list_peers` is detection, not convergence, and is not required to fire', () => { expect( auditDetectWithoutConverge({ modules: [mod('wireguard', { hooks: { list_peers: HOOK } })] }), ).toEqual([]); }); test('an undeployed module is not reported', () => { expect( auditDetectWithoutConverge({ modules: [mod('m', { hooks: { reconcile_peers: HOOK } }, 'IMPORTED')], }), ).toEqual([]); }); test('the remediation is prose, and is NOT marked actionable', () => { // The fix is an edit to a module's manifest. Marking it actionable would // put a Remediate button on a modal that cannot do anything. const findings = auditDetectWithoutConverge({ modules: [mod('wireguard', { hooks: { reconcile_peers: HOOK } })], }); expect(findings[0]?.actionable).toBe(false); expect(findings[0]?.remediation).toContain('manifest.yml'); }); });