// Tests for Eleven's deterministic command floor. node test/commands.test.mjs import assert from "node:assert/strict"; import { parseCommand, runCommand, commandNames, commandSummary } from "../agent/commands.mjs"; import { sanitizeActions } from "../web/static/ui.js"; let failures = 0; async function test(name, fn) { try { await fn(); console.log(`PASS ${name}`); } catch (e) { failures++; console.log(`FAIL ${name} — ${e && e.message}`); } } await test("parseCommand recognises registered commands", () => { assert.deepEqual(parseCommand("/theme lagoon"), { name: "/theme", args: "lagoon" }); assert.deepEqual(parseCommand("/help"), { name: "/help", args: "" }); assert.deepEqual(parseCommand(" /Dark "), { name: "/dark", args: "" }); // trims + lowercases the verb }); await test("parseCommand ignores non-commands", () => { assert.equal(parseCommand("hello there"), null); assert.equal(parseCommand("/unknown thing"), null); // unowned verb → falls through to chat assert.equal(parseCommand(""), null); assert.equal(parseCommand("not /theme"), null); // a slash mid-sentence isn't a command }); await test("theme command emits a valid set_theme chip", () => { const res = runCommand("/theme plum"); assert.equal(res.actions[0].type, "set_theme"); assert.equal(res.actions[0].theme, "plum"); }); await test("unknown theme offers the picker instead of a bad chip", () => { const res = runCommand("/theme nope"); assert.equal(res.actions[0].type, "open_theme_picker"); assert.match(res.text, /lagoon/); // lists the real options }); await test("appearance + profile commands emit their chips", () => { assert.equal(runCommand("/dark").actions[0].appearance, "dark"); assert.equal(runCommand("/light").actions[0].appearance, "light"); assert.equal(runCommand("/profile").actions[0].type, "open_profile"); }); await test("every command's chips survive the client whitelist", () => { // The whole point: a deterministic chip is indistinguishable from a model one, // so sanitizeActions (the client's only render gate) must accept them all. for (const name of commandNames()) { const res = runCommand(name === "/theme" ? "/theme lagoon" : name); const actions = res.actions || []; assert.equal(sanitizeActions(actions).length, actions.length, `${name} produced an unrenderable chip`); } }); await test("help wording reflects whether AI is available", () => { assert.match(runCommand("/help", { aiEnabled: true }).text, /ask me anything/i); assert.match(runCommand("/help", { aiEnabled: false }).text, /aren't enabled/i); }); await test("runCommand returns null for non-commands", () => { assert.equal(runCommand("just chatting"), null); }); await test("commandSummary lists every command (fed to Eleven's instructions)", () => { const s = commandSummary(); for (const name of commandNames()) assert.match(s, new RegExp(name.replace("/", "\\/"))); }); console.log(failures === 0 ? "\nALL PASSED" : `\n${failures} FAILED`); process.exit(failures === 0 ? 0 : 1);