157 lines
4.4 KiB
JavaScript
157 lines
4.4 KiB
JavaScript
import test from 'brittle'
|
|
import { readFile } from 'node:fs/promises'
|
|
import { dirname, join } from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
import { attachBareOsTuiSdk } from '../../bare-os-booter/lib/services/bare-os-tui-sdk.js'
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
const lib = (name) => join(__dirname, '../lib', name)
|
|
|
|
async function loadBaretopTui() {
|
|
const parts = await Promise.all([
|
|
readFile(lib('edit-ansi.js'), 'utf8'),
|
|
readFile(lib('baretop-snapshot.js'), 'utf8'),
|
|
readFile(lib('baretop-ui-helpers.js'), 'utf8'),
|
|
readFile(lib('baretop-tui.js'), 'utf8')
|
|
])
|
|
const hook = {}
|
|
new Function(
|
|
'exports',
|
|
parts.join('\n') +
|
|
'\nexports.bareTopCreateTuiApp = bareTopCreateTuiApp;\nexports.bareTopTabNames = bareTopTabNames;\nexports.bareTopTuiRunOpts = bareTopTuiRunOpts;\n'
|
|
)(hook)
|
|
return hook
|
|
}
|
|
|
|
function makeStream(isTTY, writes) {
|
|
return {
|
|
isTTY: !!isTTY,
|
|
raw: false,
|
|
columns: 80,
|
|
rows: 24,
|
|
write(s) {
|
|
writes.push(String(s))
|
|
},
|
|
setRawMode(v) {
|
|
this.raw = !!v
|
|
},
|
|
resume() {},
|
|
pause() {},
|
|
on() {},
|
|
removeListener() {}
|
|
}
|
|
}
|
|
|
|
function makeCtx() {
|
|
const writes = []
|
|
const ctx = {
|
|
env: { BARE_TOP_INTERVAL_MS: '1000' },
|
|
console: { error() {}, log() {} },
|
|
replStdin: makeStream(true, writes),
|
|
replStdout: makeStream(true, writes),
|
|
b4a: {
|
|
from(s) {
|
|
return Buffer.from(String(s))
|
|
}
|
|
},
|
|
vfs: {
|
|
async writeFile() {}
|
|
},
|
|
suspendReplForSubprocess() {},
|
|
resumeReplAfterSubprocess() {}
|
|
}
|
|
attachBareOsTuiSdk(ctx)
|
|
return ctx
|
|
}
|
|
|
|
function sampleSnap() {
|
|
return {
|
|
atMs: 1,
|
|
metricsLive: {
|
|
peers: 2,
|
|
session: {
|
|
execLineCount: 4,
|
|
pipelineBytesTotal: 100,
|
|
execLineWallMsTotal: 10
|
|
}
|
|
},
|
|
extra: {
|
|
processTable: {
|
|
processes: [
|
|
{ pid: 1, name: 'bare-os-kernel', state: 'running', startedAtMs: 1 },
|
|
{ pid: 2, name: 'fish', state: 'sleeping', startedAtMs: 2 }
|
|
]
|
|
},
|
|
swarm: { peers: 2 },
|
|
replication: { ok: true }
|
|
},
|
|
features: { tuiSdk: true, chat: true },
|
|
netSummary: { interfaces: [{ name: 'tun0', rxBytes: 10, txBytes: 4 }] },
|
|
initdGraph: { nodes: ['sshd', 'cron'] },
|
|
hostOs: { os: 'darwin' },
|
|
cpuCoreCount: 4,
|
|
cpuLine: 'test-cpu',
|
|
meminfoLine: 'MemTotal: 1024',
|
|
diskstatsLine: 'sda',
|
|
fileTexts: { version: 'bare-os 0.1' },
|
|
healthScore: 80,
|
|
healthBreakdown: ''
|
|
}
|
|
}
|
|
|
|
test('baretop source prefers ctx.tui.run TEA dashboard', async (t) => {
|
|
const src = await readFile(lib('baretop-tui.js'), 'utf8')
|
|
t.ok(src.includes('ctx.tui.run'))
|
|
t.ok(src.includes("buffer: 'cell'"))
|
|
t.ok(src.includes('bareTopCreateTuiApp'))
|
|
})
|
|
|
|
test('baretop TEA app paints a fixed-height frame and switches tabs', async (t) => {
|
|
const hook = await loadBaretopTui()
|
|
const ctx = makeCtx()
|
|
const app = hook.bareTopCreateTuiApp(ctx, ctx.env)
|
|
app.width = 80
|
|
app.height = 24
|
|
app.update({ type: 'baretop.snap', snap: sampleSnap() })
|
|
const view = ctx.tui.style.stripAnsi(app.view())
|
|
const lines = view.split('\n')
|
|
t.is(lines.length, 24, 'view is exactly terminal height (no scroll)')
|
|
t.ok(view.includes('baretop'), 'title')
|
|
t.ok(view.includes('[overview]'), 'active tab')
|
|
t.ok(view.includes('Activity') || view.includes('Session'), 'overview body')
|
|
|
|
app.update(ctx.tui.decode('2')[0])
|
|
t.is(app._tabName(), 'processes')
|
|
const proc = ctx.tui.style.stripAnsi(app.view())
|
|
t.ok(proc.includes('bare-os-kernel') || proc.includes('PID'), 'process table')
|
|
|
|
const q = app.update(ctx.tui.decode('q')[0])
|
|
t.is(typeof q[1], 'function')
|
|
t.is(q[1]().type, 'quit')
|
|
})
|
|
|
|
test('baretop TEA app help overlay and pause', async (t) => {
|
|
const hook = await loadBaretopTui()
|
|
const ctx = makeCtx()
|
|
const app = hook.bareTopCreateTuiApp(ctx, ctx.env)
|
|
app.update({ type: 'baretop.snap', snap: sampleSnap() })
|
|
app.update(ctx.tui.decode('?')[0])
|
|
t.ok(app.help)
|
|
const ov = app.overlay({ width: 80, height: 24 })
|
|
t.ok(ov && ctx.tui.style.stripAnsi(ov.text).includes('help'))
|
|
app.update(ctx.tui.decode('x')[0])
|
|
t.absent(app.help)
|
|
app.update(ctx.tui.decode(' ')[0])
|
|
t.ok(app.paused)
|
|
})
|
|
|
|
test('kernel baretop bin includes TEA factory after build', async (t) => {
|
|
const bin = await readFile(
|
|
join(__dirname, '../../../kernel/bin/baretop'),
|
|
'utf8'
|
|
)
|
|
t.ok(bin.includes('bareTopCreateTuiApp'))
|
|
t.ok(bin.includes('ctx.tui.run'))
|
|
})
|