openpetswithchatandmcp/plugins/official/openpets.launch-buddy/test.js
Alvin Unreal 4f4c02eacd working
2026-06-11 20:33:53 +02:00

129 lines
6.3 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Golden test for openpets.launch-buddy.
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import {
cleanMessage,
dayKey,
deterministicIndex,
normalizeConfig,
parseMessageList,
register,
selectMessage,
shouldGreet,
} from "./index.js";
let createTestHarness;
try {
({ createTestHarness } = await import("@open-pets/plugin-sdk/testing"));
} catch {
({ createTestHarness } = await import(new URL("../../../packages/sdk/dist/testing.js", import.meta.url)));
}
assert.equal(cleanMessage(" hi\nthere "), "hi there");
assert.equal(cleanMessage("", "fallback"), "fallback");
assert.equal(cleanMessage("x".repeat(500)).length, 180);
assert.deepEqual(parseMessageList("One\n\nTwo"), ["One", "Two"]);
assert.equal(normalizeConfig({ delaySeconds: 999, awayHours: 0, reaction: "nope" }).delaySeconds, 60);
assert.equal(normalizeConfig({ delaySeconds: 999, awayHours: 0, reaction: "nope" }).awayHours, 1);
assert.equal(normalizeConfig({ delaySeconds: 999, awayHours: 0, reaction: "nope" }).reaction, "waving");
assert.equal(normalizeConfig({}).greetingMode, "custom");
assert.equal(normalizeConfig({}).frequency, "everyLaunch");
assert.equal(normalizeConfig({}).delaySeconds, 3);
assert.equal(deterministicIndex(3, 180_000), 0);
assert.equal(shouldGreet({ enabled: false, frequency: "everyLaunch", awayHours: 6 }, {}, 0), false);
assert.equal(shouldGreet({ enabled: false, frequency: "everyLaunch", awayHours: 6 }, {}, 0, true), true);
assert.equal(shouldGreet({ enabled: true, frequency: "oncePerDay", awayHours: 6 }, { lastGreetingDate: "1970-01-01" }, 1_000), false);
assert.equal(shouldGreet({ enabled: true, frequency: "afterAwayHours", awayHours: 6 }, { lastGreetingAt: 0 }, 1_000), true);
const PERMISSIONS = ["pet:speak", "pet:reaction", "audio", "schedule", "storage", "commands"];
const LOCALES = { en: JSON.parse(await readFile(new URL("./locales/en.json", import.meta.url), "utf8")) };
// 1) Default startup greeting is a filled custom message and runs every launch.
{
const h = createTestHarness(register, {
permissions: PERMISSIONS,
locales: LOCALES,
nowMs: Date.UTC(2026, 0, 1, 9, 0, 0),
});
await h.start();
assert.equal(h.calls.schedules.size, 1, "expected delayed launch greeting");
await h.clock.advance("4s");
h.expectSpoke(/Welcome back! I’m ready when you are\./);
h.expectReacted("waving");
assert.deepEqual(h.calls.reactions[0], { reaction: "waving", options: { showMessage: false } }, "default launch reaction should be silent");
h.expectNoErrors();
}
// 2) Startup greeting can still use once-per-day smart mode and configured sound/reaction.
{
const h = createTestHarness(register, {
permissions: PERMISSIONS,
config: { enabled: true, greetingMode: "smart", frequency: "oncePerDay", delaySeconds: 2, reaction: "celebrating", soundEnabled: true, soundChoice: "success" },
locales: LOCALES,
nowMs: Date.UTC(2026, 0, 1, 9, 0, 0),
});
await h.start();
assert.equal(h.calls.schedules.size, 1, "expected delayed launch greeting");
await h.clock.advance("3s");
h.expectSpoke(/Good (morning|afternoon|evening)|late/);
h.expectReacted("celebrating");
assert.deepEqual(h.calls.reactions[0], { reaction: "celebrating", options: { showMessage: false } }, "launch greeting reaction should be silent");
assert.ok(h.calls.sounds.some((s) => s.sound === "success"), "expected selected sound");
h.expectStored("lastGreetingDate", (v) => typeof v === "string" && /^\d{4}-\d{2}-\d{2}$/.test(v));
h.expectNoErrors();
}
// 3) Once-per-day suppresses normal startup but greet-now forces a greeting.
{
const nowMs = Date.UTC(2026, 0, 2, 13, 0, 0);
const h = createTestHarness(register, { permissions: PERMISSIONS, config: { greetingMode: "smart", frequency: "oncePerDay", delaySeconds: 0, soundEnabled: false }, locales: LOCALES, nowMs });
await h.start();
await h.ctx.storage.set("lastGreetingDate", dayKey(Date.now()));
await h.clock.advance("1s");
assert.equal(h.calls.speak.length, 0, "normal launch should be gated");
await h.runCommand("greet-now");
h.expectSpoke(/Good (morning|afternoon|evening)|late/);
assert.equal(h.calls.sounds.length, 0, "sound disabled — no audio");
h.expectNoErrors();
}
// 4) Custom message mode and custom sound are honored.
{
const h = createTestHarness(register, { permissions: PERMISSIONS, config: { greetingMode: "custom", customMessage: "Welcome, Captain.", frequency: "everyLaunch", delaySeconds: 0, reaction: "none", soundEnabled: true, soundChoice: "custom", customSound: "soft-pop" }, locales: LOCALES, nowMs: 10_000 });
await h.start();
await h.clock.advance("1s");
h.expectSpoke(/Welcome, Captain\./);
h.expectBubble({ durationMs: 6500 });
assert.equal(h.calls.react.length, 0, "reaction none should not react");
assert.equal(h.calls.reactions.length, 0, "reaction none should not record reaction options");
assert.ok(h.calls.sounds.some((s) => s.sound === "soft-pop"), "expected custom sound");
h.expectNoErrors();
}
// 5) Random mode uses the configured list deterministically.
{
const h = createTestHarness(register, { permissions: PERMISSIONS, config: { greetingMode: "random", messageList: "Alpha\nBeta\nGamma", frequency: "everyLaunch", delaySeconds: 0, soundEnabled: false }, locales: LOCALES, nowMs: 120_000 });
await h.start();
await h.clock.advance("1s");
h.expectSpoke(/Alpha|Beta|Gamma/);
h.expectNoErrors();
}
// 6) Away-hours gate waits until enough time has passed, then reset clears state.
{
const nowMs = 10 * 60 * 60_000;
assert.equal(shouldGreet({ enabled: true, frequency: "afterAwayHours", awayHours: 6 }, { lastGreetingAt: nowMs - 5 * 60 * 60_000 }, nowMs), false);
assert.equal(shouldGreet({ enabled: true, frequency: "afterAwayHours", awayHours: 6 }, { lastGreetingAt: nowMs - 7 * 60 * 60_000 }, nowMs), true);
const h = createTestHarness(register, { permissions: PERMISSIONS, locales: LOCALES, nowMs });
await h.start();
await h.ctx.storage.set("lastGreetingAt", nowMs);
await h.ctx.storage.set("lastGreetingDate", "1970-01-01");
await h.runCommand("reset-launch-buddy");
h.expectStored("lastGreetingAt", undefined);
h.expectStored("lastGreetingDate", undefined);
h.expectSpoke(/reset/i);
h.expectNoErrors();
}
// Keep selectMessage covered without harness side effects.
assert.equal(selectMessage({ t: (k) => k }, normalizeConfig({ greetingMode: "smart" }), Date.UTC(2026, 0, 1, 23)), "message.smart.night");