import { describe, it, expect, beforeEach, afterEach } from 'vitest' import { mkdtempSync, mkdirSync, rmSync, readFileSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { stateFilePath, readState, recordSuccess } from '../../bin/portal-index-push.mjs' // Test-only cross-tree import. The two modules are in different plugins and // never import each other in production; this file is the contract between // them, and it exists because the last thing that went wrong on this feature // was two halves that each passed their own tests and did not connect. import { auditPortalIndex, formatPortalIndexAudit, } from '../../../scheduling/mcp/src/lib/portal-index-audit.js' let root: string let platformRoot: string beforeEach(() => { root = mkdtempSync(join(tmpdir(), 'portal-state-')) platformRoot = join(root, 'platform') mkdirSync(platformRoot, { recursive: true }) mkdirSync(join(root, 'data'), { recursive: true }) }) afterEach(() => rmSync(root, { recursive: true, force: true })) describe('the push writes exactly what the audit reads', () => { it('puts the state where the heartbeat looks for it', () => { // The audit resolves /../data/portal-index-state.json // independently. If these two ever disagree the audit reports every healthy // account as never-ran, which is a false alarm pointing at the wrong thing. expect(stateFilePath(platformRoot)).toBe(join(root, 'data', 'portal-index-state.json')) }) it('round-trips an entry the audit reads as healthy', () => { recordSuccess(platformRoot, 'acc-a', { lastPushMs: Date.now(), rows: 41, exposed: ['output', 'quotes'], }) const onDisk = JSON.parse(readFileSync(stateFilePath(platformRoot), 'utf8')) const result = auditPortalIndex(['acc-a'], onDisk, Date.now(), 3_600_000) expect(result.neverRan).toBe(0) expect(result.stale).toBe(0) expect(result.accounts[0].rows).toBe(41) expect(result.accounts[0].exposed).toEqual(['output', 'quotes']) expect(formatPortalIndexAudit(result)).toEqual([ '[portal-index] op=audit accounts=1 stale=0 never-ran=0', ]) }) it('an account the push never recorded reads as never-ran', () => { recordSuccess(platformRoot, 'acc-a', { lastPushMs: Date.now(), rows: 1, exposed: ['output'] }) const onDisk = JSON.parse(readFileSync(stateFilePath(platformRoot), 'utf8')) const result = auditPortalIndex(['acc-a', 'acc-b'], onDisk, Date.now(), 3_600_000) expect(result.neverRan).toBe(1) expect(formatPortalIndexAudit(result)[0]).toContain('account=acc-b') expect(formatPortalIndexAudit(result)[0]).toContain('result=never-ran') }) it('recording one account does not erase another', () => { recordSuccess(platformRoot, 'acc-a', { lastPushMs: 1, rows: 1, exposed: ['output'] }) recordSuccess(platformRoot, 'acc-b', { lastPushMs: 2, rows: 2, exposed: ['quotes'] }) const state = readState(platformRoot) expect(Object.keys(state).sort()).toEqual(['acc-a', 'acc-b']) }) it('an absent state file reads as an empty object, not a throw', () => { expect(readState(platformRoot)).toEqual({}) // …and an absent file with portals enrolled is the never-ran signal, which // is the state a device sits in before the very first push. expect(auditPortalIndex(['acc-a'], readState(platformRoot), Date.now(), 3_600_000).neverRan).toBe(1) }) })