Files
bare-operating-system/packages/bare-os-coreutils/test/whois-rdap.test.mjs
T
2026-04-24 08:26:33 -04:00

188 lines
5.3 KiB
JavaScript

import { readFile } from 'node:fs/promises'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import test from 'brittle'
import b4a from 'b4a'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor
async function loadWhoisBin() {
const runtime = await readFile(path.join(__dirname, '../lib/runtime.js'), 'utf8')
const body = await readFile(path.join(__dirname, '../src/whois.js'), 'utf8')
return new AsyncFunction(
'ctx',
'argv',
`${runtime}\n${body}\nif (typeof run === 'function') return await run(ctx, argv)\n`
)
}
function createCtx() {
const logs = []
const errs = []
return {
b4a,
exitCode: 0,
vfs: { env: {} },
console: {
log: (m) => logs.push(String(m)),
error: (m) => errs.push(String(m))
},
_logs: logs,
_errs: errs
}
}
function responseJson(body, status = 200) {
return new Response(JSON.stringify(body), {
status,
headers: { 'Content-Type': 'application/rdap+json' }
})
}
async function withPatchedFetch(stub, fn) {
const oldFetch = globalThis.fetch
globalThis.fetch = stub
try {
return await fn()
} finally {
globalThis.fetch = oldFetch
}
}
test('/bin/whois domain lookup prints summary', async (t) => {
const run = await loadWhoisBin()
const ctx = createCtx()
const calls = []
await withPatchedFetch(async (url) => {
calls.push(String(url))
if (String(url).includes('/rdap/dns.json')) {
return responseJson({
services: [[['com'], ['https://rdap.test/']]]
})
}
return responseJson({
objectClassName: 'domain',
ldhName: 'example.com',
handle: 'EXAMPLE1',
status: ['active'],
nameservers: [{ ldhName: 'ns1.example.com' }],
entities: [
{
roles: ['registrar'],
vcardArray: ['vcard', [['fn', {}, 'text', 'Test Registrar']]]
}
]
})
}, async () => {
await run(ctx, ['whois', 'example.com'])
})
t.is(ctx.exitCode, 0)
t.alike(calls, [
'https://data.iana.org/rdap/dns.json',
'https://rdap.test/domain/example.com'
])
t.ok(ctx._logs.join('\n').includes('Registrar: Test Registrar'))
t.ok(ctx._logs.join('\n').includes('Nameservers: ns1.example.com'))
})
test('/bin/whois IP lookup resolves via ipv4 bootstrap', async (t) => {
const run = await loadWhoisBin()
const ctx = createCtx()
await withPatchedFetch(async (url) => {
if (String(url).includes('/rdap/ipv4.json')) {
return responseJson({
services: [[['203.0.113.0/24'], ['https://arin.test/rdap']]]
})
}
return responseJson({
objectClassName: 'ip network',
startAddress: '203.0.113.0',
endAddress: '203.0.113.255',
ipVersion: 'v4',
handle: 'NET-203-0-113-0-1'
})
}, async () => {
await run(ctx, ['whois', '203.0.113.10'])
})
t.is(ctx.exitCode, 0)
t.ok(ctx._logs.join('\n').includes('IP Version: v4'))
t.ok(ctx._logs.join('\n').includes('Range: 203.0.113.0 - 203.0.113.255'))
})
test('/bin/whois ASN lookup resolves autnum and supports --json', async (t) => {
const run = await loadWhoisBin()
const ctx = createCtx()
await withPatchedFetch(async (url) => {
if (String(url).includes('/rdap/asn.json')) {
return responseJson({
services: [[['13335-13335'], ['https://asn.test/']]]
})
}
return responseJson({
objectClassName: 'autnum',
handle: 'AS13335',
startAutnum: 13335,
endAutnum: 13335,
name: 'CLOUDFLARENET'
})
}, async () => {
await run(ctx, ['whois', '--json', 'AS13335'])
})
t.is(ctx.exitCode, 0)
t.ok(ctx._logs.join('\n').includes('"objectClassName": "autnum"'))
t.absent(ctx._logs.join('\n').includes('ASN Range:'))
})
test('/bin/whois exits non-zero when no bootstrap service matches', async (t) => {
const run = await loadWhoisBin()
const ctx = createCtx()
await withPatchedFetch(async (url) => {
if (String(url).includes('/rdap/dns.json')) {
return responseJson({
services: [[['net'], ['https://rdap.test/']]]
})
}
return responseJson({})
}, async () => {
await run(ctx, ['whois', 'example.com'])
})
t.is(ctx.exitCode, 1)
t.ok(ctx._errs.join('\n').includes('no RDAP service found'))
})
test('/bin/whois handles upstream HTTP failures', async (t) => {
const run = await loadWhoisBin()
const ctx = createCtx()
await withPatchedFetch(async (url) => {
if (String(url).includes('/rdap/dns.json')) {
return responseJson({
services: [[['com'], ['https://rdap.test/']]]
})
}
return responseJson({ errorCode: 404 }, 404)
}, async () => {
await run(ctx, ['whois', 'example.com'])
})
t.is(ctx.exitCode, 1)
t.ok(ctx._errs.join('\n').includes('HTTP error'))
})
test('/bin/whois validates arguments and help output', async (t) => {
const run = await loadWhoisBin()
const helpCtx = createCtx()
await run(helpCtx, ['whois', '--help'])
t.is(helpCtx.exitCode, 0)
t.ok(helpCtx._logs.join('\n').includes('usage: whois'))
const badCtx = createCtx()
await run(badCtx, ['whois', '-Z'])
t.is(badCtx.exitCode, 1)
t.ok(badCtx._errs.join('\n').includes('unknown option'))
const missingCtx = createCtx()
await run(missingCtx, ['whois'])
t.is(missingCtx.exitCode, 1)
t.ok(missingCtx._errs.join('\n').includes('expected exactly one target'))
})