Files
bare-operating-system/packages/bare-os-coreutils/test/irc-tui-sdk.test.mjs
T
2026-08-18 18:11:34 -04:00

162 lines
4.7 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))
async function load() {
const parts = await Promise.all([
readFile(join(__dirname, '../lib/irc/irc-parse.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-isupport.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-sasl.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-state.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-config.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-client.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-dial.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-commands.js'), 'utf8'),
readFile(join(__dirname, '../lib/irc/irc-tui.js'), 'utf8')
])
const hook = {}
new Function(
'exports',
parts.join('\n') +
'\nexports.bareIrcCreateClient = bareIrcCreateClient;\nexports.bareIrcCreateTuiApp = bareIrcCreateTuiApp;\n'
)(hook)
return hook
}
function makeStream(isTTY) {
return {
isTTY: !!isTTY,
columns: 80,
rows: 24,
write() {},
setRawMode() {},
resume() {},
pause() {},
on() {},
removeListener() {}
}
}
function makeCtx() {
const ctx = {
env: {},
console: { error() {}, log() {} },
replStdin: makeStream(true),
replStdout: makeStream(true),
suspendReplForSubprocess() {},
resumeReplAfterSubprocess() {}
}
attachBareOsTuiSdk(ctx)
return ctx
}
test('irc TUI paints a fixed-height frame', async (t) => {
const h = await load()
const ctx = makeCtx()
const client = h.bareIrcCreateClient({ nick: 'alice', network: 'libera' })
client.state.connection = 'registered'
client.state.registered = true
client.state.nick = 'alice'
client.handleMessage({
tags: {},
source: 'bob!b@h',
nick: 'bob',
user: 'b',
host: 'h',
command: 'PRIVMSG',
params: ['#bareos', 'hello from test']
})
const chan = Object.values(client.state.buffers).find(
(b) => b.kind === 'channel'
)
t.ok(chan)
client.state.currentId = chan.id
const app = h.bareIrcCreateTuiApp(ctx, client)
app.width = 80
app.height = 24
app._sync()
const view = ctx.tui.style.stripAnsi(app.view())
t.is(view.split('\n').length, 24)
t.ok(
view.includes('libera') ||
view.includes('#bareos') ||
view.includes('alice')
)
t.ok(view.includes('hello from test'))
})
test('irc TUI keeps nicks in a right-hand column', async (t) => {
const h = await load()
const ctx = makeCtx()
const client = h.bareIrcCreateClient({ nick: 'alice', network: 'libera' })
client.state.registered = true
client.handleMessage({
command: 'JOIN',
nick: 'alice',
params: ['#ubuntu']
})
client.handleMessage({
command: '353',
params: ['alice', '=', '#ubuntu', '@op +voice nickonly']
})
client.handleMessage({
command: 'PRIVMSG',
nick: 'op',
source: 'op!a@b',
params: ['#ubuntu', 'hello room']
})
const app = h.bareIrcCreateTuiApp(ctx, client)
app.width = 120
app.height = 24
app.roomsOpen = false
app._sync()
const view = ctx.tui.style.stripAnsi(app.view())
const lines = view.split('\n')
t.ok(view.includes('hello room'))
t.ok(view.includes('@op') || view.includes('op'))
const chatLine = lines.find((l) => l.includes('hello room'))
t.ok(chatLine)
const bar = chatLine.lastIndexOf('\u2502')
t.ok(bar > chatLine.indexOf('hello room'))
const nickLine = lines.find((l) => l.includes('\u2502') && /@op/.test(l))
t.ok(nickLine)
t.ok(nickLine.lastIndexOf('\u2502') < nickLine.indexOf('@op'))
})
test('irc TUI rooms browser lists featured channels', async (t) => {
const h = await load()
const ctx = makeCtx()
const client = h.bareIrcCreateClient({ nick: 'alice' })
const app = h.bareIrcCreateTuiApp(ctx, client)
app.width = 80
app.height = 24
app._openRooms('')
app._sync()
const view = ctx.tui.style.stripAnsi(app.view())
t.ok(app.roomsOpen)
t.ok(view.includes('#libera'))
})
test('irc TUI help overlay', async (t) => {
const h = await load()
const ctx = makeCtx()
const client = h.bareIrcCreateClient({ nick: 'alice' })
const app = h.bareIrcCreateTuiApp(ctx, client)
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('Libera'))
})
test('kernel irc bin includes TEA factory after build', async (t) => {
const bin = await readFile(join(__dirname, '../../../kernel/bin/irc'), 'utf8')
t.ok(bin.includes('bareIrcCreateTuiApp'))
t.ok(bin.includes('ctx.tui.run'))
t.ok(bin.includes('irc.libera.chat'))
})