import { AGENTS, LOG_ERROR_LINES, LOG_TOTAL_LINES, RUN_LOG, TRIGGER, agentById, eventDrivenAgents, networkStats, taskDrivenAgents, } from '@/lib/agentNetwork'; /** * The agent table behind the Agents page. * * It is a hand-maintained snapshot, not a feed — AI_engine exposes no endpoint * this console can reach. That makes these tests load-bearing in an unusual * way: they are the only thing standing between a typo in the table and a * status board that states something untrue with total confidence. */ describe('the swarm as recorded', () => { it('is nine agents — JARVIS and eight specialised', () => { expect(AGENTS).toHaveLength(9); expect(AGENTS.map((a) => a.id)).toContain('JARVIS'); }); it('gives every agent a unique id', () => { const ids = AGENTS.map((a) => a.id); expect(new Set(ids).size).toBe(ids.length); }); it('gives every agent a trigger the page can label', () => { // A trigger with no entry in TRIGGER renders as `undefined` on the card — // silently, because React prints nothing for it. AGENTS.forEach((a) => { expect(Object.keys(TRIGGER)).toContain(a.trigger); }); }); it('gives every agent the fields the detail panel reads', () => { AGENTS.forEach((a) => { expect(typeof a.detail).toBe('string'); expect(a.detail.length).toBeGreaterThan(20); expect(typeof a.publishes).toBe('string'); expect(typeof a.api).toBe('string'); expect(typeof a.autonomy).toBe('string'); expect(typeof a.lastSeen).toBe('string'); expect(Array.isArray(a.subscribes)).toBe(true); }); }); it('uses only the four states the page can colour', () => { // An unknown status falls through TONE to `undefined`, and the card then // renders with no dot, no badge and no bar — invisible breakage. AGENTS.forEach((a) => { expect(['active', 'running', 'degraded', 'idle']).toContain(a.status); }); }); }); describe('the split that the page is really about', () => { it('three agents subscribe to the bus themselves', () => { expect(eventDrivenAgents().map((a) => a.id)).toEqual([ 'DISPATCH_AGENT', 'EXCEPTION_AGENT', 'EXPRESS_DISPATCH_AGENT', ]); }); it('five only run when JARVIS hands them work', () => { expect(taskDrivenAgents()).toHaveLength(5); }); it('every event-driven agent names at least one subject', () => { // The pipeline chip prints `subscribes[0]`. An empty array there renders a // blank line where a NATS subject should be. eventDrivenAgents().forEach((a) => { expect(a.subscribes.length).toBeGreaterThan(0); }); }); it('no task-driven agent claims to subscribe to anything', () => { // The whole point of the second group: they cannot be woken by an event. taskDrivenAgents().forEach((a) => { expect(a.subscribes).toEqual([]); }); }); }); describe('the headline numbers are derived, never written down', () => { it('counts what the cards underneath actually show', () => { // A dashboard that says "3 active" over three grey dots is the failure // this guards. Every stat comes off the same table the grid renders. const s = networkStats(); expect(s.total).toBe(AGENTS.length); expect(s.working).toBe(AGENTS.filter((a) => a.status === 'active').length); expect(s.degraded).toBe(AGENTS.filter((a) => a.status === 'degraded').length); expect(s.working + s.degraded + s.idle + 1).toBe(s.total); // +1 for JARVIS, which is `running` }); it('reports exactly one agent doing real work', () => { expect(networkStats().working).toBe(1); }); it('reports no autonomy gate switched on', () => { // Stated on the page as a promise: the swarm observes and alerts, and does // not write to the system. If a gate is ever turned on, this fails and the // page's own subtitle has to change with it. const s = networkStats(); expect(s.autonomyOn).toBe(0); expect(s.gated).toBe(3); }); it('recomputes for a different set rather than returning constants', () => { const two = networkStats([ { status: 'active', events: 5, gated: true }, { status: 'idle', events: 0, gated: false }, ]); expect(two.total).toBe(2); expect(two.working).toBe(1); expect(two.events).toBe(5); expect(two.gated).toBe(1); }); }); describe('agentById', () => { it('finds an agent', () => { expect(agentById('EXCEPTION_AGENT').name).toBe('Exception'); }); it('falls back to the first rather than returning undefined', () => { // The page reads `.status` off the result straight away; undefined here is // a blank panel at best and a crash at worst. expect(agentById('NOPE')).toBe(AGENTS[0]); }); }); describe('the run log', () => { it('uses only tones the page can colour', () => { RUN_LOG.forEach((l) => { expect(['info', 'warn', 'error']).toContain(l.tone); }); }); it("the two repeated errors account for the log's stated error total", () => { // 2 x 8,594 = 17,188, which is the number in the panel header. If the // table and the header ever disagree, one of them is lying. const repeated = RUN_LOG.filter((l) => l.tone === 'error').reduce((n, l) => n + (l.count || 0), 0); expect(repeated).toBe(LOG_ERROR_LINES); expect(LOG_ERROR_LINES).toBeLessThan(LOG_TOTAL_LINES); }); });