import test from 'brittle' import { readFile } from 'node:fs/promises' import { dirname, join } from 'node:path' import { fileURLToPath } from 'node:url' import { createContext, runInContext } from 'node:vm' const __dirname = dirname(fileURLToPath(import.meta.url)) const helpersPath = join(__dirname, '../lib/baretop/baretop-ui-helpers.js') const composePath = join(__dirname, '../lib/baretop/baretop-compose.js') const fixturePath = join(__dirname, 'fixtures/baretop-process-table.json') test('bareTopComposeSmokeTestFrame golden lines', async (t) => { const helpers = await readFile(helpersPath, 'utf8') const compose = await readFile(composePath, 'utf8') const ctx = createContext({}) runInContext(helpers, ctx) runInContext(compose, ctx) const raw = await readFile(fixturePath, 'utf8') const pt = JSON.parse(raw) const snap = { extra: { processTable: pt } } const fr = ctx.bareTopComposeSmokeTestFrame(snap, 80) t.ok(Array.isArray(fr.lines)) t.is(fr.lines[0], 'baretop-compose-smoke cols=80') t.ok(fr.lines.some((l) => l.startsWith('process_rows='))) t.ok(fr.meta && fr.meta.layoutVersion) }) test('bareTopEmitFrame skips hashing on tiny frames', async (t) => { const helpers = await readFile(helpersPath, 'utf8') const compose = await readFile(composePath, 'utf8') const ctx = createContext({}) runInContext(helpers, ctx) runInContext(compose, ctx) const out = 'a\r\nb\r\nc' const prev = ['x', 'y', 'z'] const em = ctx.bareTopEmitFrame( {}, { write() {} }, out, { prevLines: prev, rows: 4, cols: 80, incrementalFrameDiff: true, useLineHash: true, fullscreenPanel: false, cup: (r, c) => `\\x1b[${r};${c}H` } ) t.ok(em.consideredPatch) }) test('bareTopEmitFrame enters hysteresis after near-full patch miss', async (t) => { const helpers = await readFile(helpersPath, 'utf8') const compose = await readFile(composePath, 'utf8') const ctx = createContext({}) runInContext(helpers, ctx) runInContext(compose, ctx) const prev = Array.from({ length: 20 }, (_, i) => 'L' + i) const next = Array.from({ length: 20 }, (_, i) => 'X' + i).join('\r\n') const first = ctx.bareTopEmitFrame( {}, { write() {} }, next, { prevLines: prev, rows: 24, cols: 80, incrementalFrameDiff: true, useLineHash: false, fullscreenPanel: false, cup: (r, c) => `\\x1b[${r};${c}H` } ) t.ok(!first.wrotePatch) const second = ctx.bareTopEmitFrame( {}, { write() {} }, next, { prevLines: prev, rows: 24, cols: 80, incrementalFrameDiff: true, useLineHash: false, fullscreenPanel: false, cup: (r, c) => `\\x1b[${r};${c}H` } ) t.is(second.fallbackReason, 'patch_hysteresis_full') })