import { describe, it, expect } from 'vitest'; import { extractEndpoints, auditDocs, auditServices, parseUrl, runAudit } from '../../lib/infra/audit.js'; // Doc-drift sanity check: pull every LAN endpoint referenced in the wiki and // confirm it's actually live. Catches stale IPs/ports (e.g. a CT that moved // off 192.168.1.13 but is still documented there). Pure logic, injected probe. describe('extractEndpoints', () => { it('pulls host:port and host-only LAN refs, deduped', () => { const eps = extractEndpoints('see http://192.168.1.27:8080 and 192.168.1.27:8080 plus 192.168.1.99 alone'); expect(eps).toContainEqual({ host: '192.168.1.27', port: 8080 }); expect(eps).toContainEqual({ host: '192.168.1.99', port: null }); // deduped: the repeated .27:8080 appears once expect(eps.filter(e => e.host === '192.168.1.27' && e.port === 8080)).toHaveLength(1); }); it('ignores non-LAN addresses and bare version-like numbers', () => { const eps = extractEndpoints('cloudflare 49.185.140.110:8006 and version 7.0.2 and 10.0.0.1'); expect(eps).toHaveLength(0); }); it('does not treat a CIDR mask as a port', () => { const eps = extractEndpoints('192.168.1.230/24 is the host'); expect(eps).toContainEqual({ host: '192.168.1.230', port: null }); }); }); describe('auditDocs', () => { const pages = [ { title: 'Network map', body_md: 'magicmirror 192.168.1.13:8080' }, { title: 'Overview', body_md: 'magicmirror 192.168.1.13:8080 and ollama 192.168.1.185:11434' }, { title: 'Host', body_md: 'gramps 192.168.1.99 alone' } ]; it('flags doc-referenced endpoints that are unreachable, grouped by citing page', async () => { const probe = async (host, port) => !(host === '192.168.1.13' && port === 8080); // .13:8080 is dead const report = await auditDocs({ pages, probe }); expect(report.summary.probed).toBe(2); // .13:8080 and .185:11434 (host-only .99 not probed) expect(report.summary.unreachable).toBe(1); const dead = report.unreachable.find(u => u.host === '192.168.1.13' && u.port === 8080); expect(dead).toBeTruthy(); expect(dead.pages.sort()).toEqual(['Network map', 'Overview']); }); it('reports a clean bill when everything resolves', async () => { const report = await auditDocs({ pages, probe: async () => true }); expect(report.summary.unreachable).toBe(0); expect(report.unreachable).toEqual([]); expect(report.ok).toBe(true); }); it('lists host-only references separately as not-probed', async () => { const report = await auditDocs({ pages, probe: async () => true }); expect(report.unprobed).toContainEqual( expect.objectContaining({ host: '192.168.1.99', port: null }) ); }); }); describe('parseUrl', () => { it('extracts host + explicit port', () => { expect(parseUrl('http://192.168.1.225:8384')).toEqual({ host: '192.168.1.225', port: 8384 }); }); it('defaults port by scheme', () => { expect(parseUrl('https://gramps.hynesy.com')).toEqual({ host: 'gramps.hynesy.com', port: 443 }); expect(parseUrl('http://192.168.1.99')).toEqual({ host: '192.168.1.99', port: 80 }); }); it('returns null for junk', () => { expect(parseUrl('not a url')).toBeNull(); }); }); describe('auditServices', () => { const services = [ { id: 'gitea', url: 'http://192.168.1.223:3000' }, { id: 'magicmirror', url: 'http://192.168.1.27:8080' } // moved away — should be unreachable ]; it('flags services whose url does not answer', async () => { const probe = async (host) => host !== '192.168.1.27'; const r = await auditServices({ services, probe }); expect(r.summary.probed).toBe(2); expect(r.ok).toBe(false); expect(r.unreachable).toEqual([ expect.objectContaining({ id: 'magicmirror', host: '192.168.1.27', port: 8080 }) ]); }); }); describe('runAudit', () => { it('is ok only when both docs and services are clean', async () => { const r = await runAudit({ pages: [{ title: 'P', body_md: '192.168.1.223:3000' }], services: [{ id: 'gitea', url: 'http://192.168.1.223:3000' }], probe: async () => true }); expect(r.ok).toBe(true); expect(r.docs.ok).toBe(true); expect(r.services.ok).toBe(true); }); });