eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1// Tests for Eleven's deterministic command floor. node test/commands.test.mjs
2import assert from "node:assert/strict";
3import { parseCommand, runCommand, commandNames, commandSummary } from "../agent/commands.mjs";
4import { sanitizeActions } from "../web/static/ui.js";
5
6let failures = 0;
7async function test(name, fn) {
8 try {
9 await fn();
10 console.log(`PASS ${name}`);
11 } catch (e) {
12 failures++;
13 console.log(`FAIL ${name} — ${e && e.message}`);
14 }
15}
16
17await test("parseCommand recognises registered commands", () => {
18 assert.deepEqual(parseCommand("/theme lagoon"), { name: "/theme", args: "lagoon" });
19 assert.deepEqual(parseCommand("/help"), { name: "/help", args: "" });
20 assert.deepEqual(parseCommand(" /Dark "), { name: "/dark", args: "" }); // trims + lowercases the verb
21});
22
23await test("parseCommand ignores non-commands", () => {
24 assert.equal(parseCommand("hello there"), null);
25 assert.equal(parseCommand("/unknown thing"), null); // unowned verb → falls through to chat
26 assert.equal(parseCommand(""), null);
27 assert.equal(parseCommand("not /theme"), null); // a slash mid-sentence isn't a command
28});
29
30await test("theme command emits a valid set_theme chip", () => {
31 const res = runCommand("/theme plum");
32 assert.equal(res.actions[0].type, "set_theme");
33 assert.equal(res.actions[0].theme, "plum");
34});
35
36await test("unknown theme offers the picker instead of a bad chip", () => {
37 const res = runCommand("/theme nope");
38 assert.equal(res.actions[0].type, "open_theme_picker");
39 assert.match(res.text, /lagoon/); // lists the real options
40});
41
42await test("appearance + profile commands emit their chips", () => {
43 assert.equal(runCommand("/dark").actions[0].appearance, "dark");
44 assert.equal(runCommand("/light").actions[0].appearance, "light");
45 assert.equal(runCommand("/profile").actions[0].type, "open_profile");
46});
47
48await test("every command's chips survive the client whitelist", () => {
49 // The whole point: a deterministic chip is indistinguishable from a model one,
50 // so sanitizeActions (the client's only render gate) must accept them all.
51 for (const name of commandNames()) {
52 const res = runCommand(name === "/theme" ? "/theme lagoon" : name);
53 const actions = res.actions || [];
54 assert.equal(sanitizeActions(actions).length, actions.length, `${name} produced an unrenderable chip`);
55 }
56});
57
58await test("help wording reflects whether AI is available", () => {
59 assert.match(runCommand("/help", { aiEnabled: true }).text, /ask me anything/i);
60 assert.match(runCommand("/help", { aiEnabled: false }).text, /aren't enabled/i);
61});
62
63await test("runCommand returns null for non-commands", () => {
64 assert.equal(runCommand("just chatting"), null);
65});
66
67await test("commandSummary lists every command (fed to Eleven's instructions)", () => {
68 const s = commandSummary();
69 for (const name of commandNames()) assert.match(s, new RegExp(name.replace("/", "\\/")));
70});
71
72console.log(failures === 0 ? "\nALL PASSED" : `\n${failures} FAILED`);
73process.exit(failures === 0 ? 0 : 1);
74