Something went wrong. Try again.
Monorepo for Aesthetic.Computer aesthetic.computer
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136#!/usr/bin/env node// ๐พ land 2-player smoke test โ opens two headless Chromium pages on /land,// waits for boot + netcode, then asserts BOTH clients are receiving land// snapshots and can see each other in the roster. Screenshots land in /tmp.//// Usage: node artery/test-land-multiplayer.mjs [--url https://localhost:8888] [--keep]// --keep leave the browsers open (headful debugging on a desktop host)
import puppeteer from "puppeteer";
const argv = process.argv.slice(2);const flag = (n, d) => { const i = argv.indexOf("--" + n); return i === -1 ? d : argv[i + 1]; };const URL_BASE = flag("url", process.env.AC_LAND_URL || "https://localhost:8888");const KEEP = argv.includes("--keep");
const pass = (m) => console.log(`โ
${m}`);const fail = (m) => { console.log(`โ ${m}`); process.exitCode = 1; };
async function openPlayer(name) { const browser = await puppeteer.launch({ executablePath: "/usr/sbin/chromium-browser", headless: !KEEP, args: [ "--no-sandbox", "--ignore-certificate-errors", "--use-fake-ui-for-media-stream", "--window-size=900,600", ], }); const page = (await browser.pages())[0] ?? (await browser.newPage()); await page.setViewport({ width: 900, height: 600 }); const consoleLines = []; page.on("console", (msg) => { const t = msg.text(); consoleLines.push(t); if (/๐พ|welcome|roster|snap/.test(t)) console.log(`[${name}] ${t}`); }); await page.goto(`${URL_BASE}/land`, { waitUntil: "load", timeout: 60_000 }); return { browser, page, name, consoleLines };}
// The land piece batches a perf ring to bios, which mirrors it onto// window.__arena_perfStats (shared channel name โ see bios.mjs). meta carries// myHandle / snapsRx / position, which is all this smoke test needs.async function perf(page) { return page.evaluate(() => { const fn = window.__arena_perfStats; return typeof fn === "function" ? fn().meta : null; });}
async function perfWait(page, name, ms = 45_000) { const t0 = Date.now(); while (Date.now() - t0 < ms) { const m = await perf(page); if (m && m.snapsRx > 10) return m; await new Promise((r) => setTimeout(r, 1_500)); } console.log(`โ ๏ธ ${name}: perf meta never arrived`); return null;}
const p1 = await openPlayer("P1");const p2 = await openPlayer("P2");
// Boot + WS/UDP + first snaps take a few seconds; poll rather than guess.const m1 = await perfWait(p1.page, "P1");const m2 = await perfWait(p2.page, "P2");
console.log("P1 meta:", JSON.stringify(m1));console.log("P2 meta:", JSON.stringify(m2));
if (m1 && m1.snapsRx > 10) pass(`P1 (${m1.myHandle}) receiving snaps: ${m1.snapsRx}`);else fail("P1 not receiving snaps");if (m2 && m2.snapsRx > 10) pass(`P2 (${m2.myHandle}) receiving snaps: ${m2.snapsRx}`);else fail("P2 not receiving snaps");if (m1 && m2 && m1.myHandle !== m2.myHandle) pass("distinct handles");
// ๐ค Wire-level walker bot joins the same meadow and strolls โ both browser// clients must see it appear in their rosters. (Keyboard-driven walking// needs real pointer lock; verify that manually with --keep on a desktop.)const { WebSocket } = await import("ws");const { packCmd } = await import( "../system/public/aesthetic.computer/lib/pmove.mjs");const SESSION_URL = flag("session", "wss://localhost:8889");await new Promise((resolve) => { const bot = new WebSocket(SESSION_URL, { rejectUnauthorized: false }); const bsend = (type, content) => bot.send(JSON.stringify({ type, content: JSON.stringify(content) })); let seq = 0; const t0 = Date.now(); bot.on("message", (d) => { try { const m = JSON.parse(d.toString()); if (m.type?.startsWith("land:") && m.type !== "land:snap") { console.log(`[bot] ${m.type}`); } } catch {} }); bot.on("open", () => { console.log(`[bot] connected โ ${SESSION_URL}`); bsend("land:hello", { handle: "meadowbot" }); const iv = setInterval(() => { seq++; bsend("land:cmd", { handle: "meadowbot", firstSeq: seq, ack: 0, cmds: [packCmd({ ms: Date.now() - t0, fwd: 1, right: 0, yaw: 45, pitch: 0, buttons: 0 })] }); }, 50); setTimeout(() => { clearInterval(iv); bsend("land:bye", { handle: "meadowbot" }); bot.close(); resolve(); }, 5_000); }); bot.on("error", (e) => { console.log("[bot] error:", e.message); resolve(); });});await new Promise((r) => setTimeout(r, 2_000));for (const p of [p1, p2]) { if (p.consoleLines.some((l) => l.includes("meadowbot"))) { pass(`${p.name} saw meadowbot join its roster`); } else { fail(`${p.name} never saw meadowbot`); }}
await p1.page.screenshot({ path: "/tmp/land-p1.png" });await p2.page.screenshot({ path: "/tmp/land-p2.png" });console.log("๐ธ screenshots: /tmp/land-p1.png /tmp/land-p2.png");
if (!KEEP) { await p1.browser.close(); await p2.browser.close();}console.log(process.exitCode ? "โ FAIL" : "๐พ PASS");