import { test } from 'node:test'; import assert from 'node:assert/strict'; import { existsSync, mkdtempSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { readJsonl, readJson, readHead } from '../src/telemetry/telemetry.reader.js'; import { APP_ROOT, PATHS, isStale, metricsAgeSeconds } from '../src/common/app-root.js'; import { TelemetryService } from '../src/telemetry/telemetry.service.js'; test('readJsonl parses valid lines and skips malformed', () => { const d = mkdtempSync(join(tmpdir(), 'cp-')); const f = join(d, 'x.jsonl'); writeFileSync(f, '{"a":1}\n\nnot-json\n{"a":2}\n'); const rows = readJsonl<{ a: number }>(f); assert.equal(rows.length, 2); assert.equal(rows[0].a, 1); assert.equal(rows[1].a, 2); }); test('readJsonl/readJson tolerate missing files (no throw)', () => { assert.deepEqual(readJsonl('/no/such/file.jsonl'), []); assert.equal(readJson('/no/such/file.json'), null); assert.equal(readHead('/no/such/head.txt'), null); }); test('APP_ROOT resolves to the CASAN app root (has a harness marker)', () => { const marker = existsSync(join(APP_ROOT, 'packages', 'casan-harness')) || existsSync(join(APP_ROOT, '.specify')); assert.ok(marker, `APP_ROOT=${APP_ROOT} should contain .specify or packages/casan-harness`); }); test('overview() returns real aggregated shape, never throws on the repo state', () => { const svc = new TelemetryService(); const o = svc.overview() as any; assert.ok(o.totals && typeof o.totals.runs === 'number'); assert.ok(o.harness_signals && o.harness_signals['H5-governance']); assert.ok(o.audit_chain && typeof o.audit_chain.records === 'number'); assert.ok('stale' in o && 'stale_after_s' in o); // real data: metrics + audit feeds exist in this repo, so counts are non-negative assert.ok(o.totals.runs >= 0); assert.ok(o.audit_chain.records >= 0); }); test('security()/governance()/cost() return objects with expected keys', () => { const svc = new TelemetryService(); assert.ok(typeof (svc.security() as any).by_status === 'object'); assert.ok(typeof (svc.governance() as any).by_decision === 'object'); assert.ok('provider_tokens' in (svc.cost() as any)); }); test('commandCenter() returns evidence-backed widget contract', () => { const svc = new TelemetryService(); const command = svc.commandCenter() as any; const ids = Object.keys(command.widgets); assert.deepEqual(ids.sort(), [ 'certification', 'finops', 'hitl', 'kill_switch', 'maturity', 'security', 'self_improve', 'traceability', ]); for (const w of Object.values(command.widgets) as any[]) { assert.ok(w.id && w.title && w.status); assert.ok(w.envelope && typeof w.envelope.artifact_path === 'string'); assert.ok(['verified', 'present_unverified', 'missing'].includes(w.envelope.status)); assert.equal(typeof w.envelope.verified, 'boolean'); } assert.ok(Array.isArray(command.briefing)); assert.ok(Array.isArray(command.ticker)); }); test('freshness helpers behave (age is number|null, isStale is boolean)', () => { const age = metricsAgeSeconds(); assert.ok(age === null || typeof age === 'number'); assert.equal(typeof isStale(), 'boolean'); }); test('missing metrics feed => stale (fail-loud)', () => { const prev = process.env.CASAN_DASHBOARD_METRICS; process.env.CASAN_DASHBOARD_METRICS = '/no/such/metrics.jsonl'; // re-import is not trivial (module caches PATHS); assert the reader-level contract instead: assert.deepEqual(readJsonl('/no/such/metrics.jsonl'), []); if (prev === undefined) delete process.env.CASAN_DASHBOARD_METRICS; else process.env.CASAN_DASHBOARD_METRICS = prev; void PATHS; });