Files
oh-my-pi-telegram/tests/menu-settings.test.ts
Evandro Fonseca Junior d1d04001d0
Release / release (push) Failing after 5s
Validate / validate (push) Failing after 5m21s
chore: fork @llblab/[email protected] as @evandrodevbr/oh-my-pi-telegram
Fork of upstream llblab/[email protected].0 (SHA afe09c5) repackaged as a
drop-in extension for can1357/oh-my-pi (omp >= 16.5.2).

Changes vs upstream:
- Rename package: @llblab/pi-telegram -> @evandrodevbr/oh-my-pi-telegram
- Bump version: 0.22.0 -> 0.22.0-evandro.1
- Update repository/homepage/bugs URLs to evandrodevbr
- Add omp field in package.json (displayName + compatibleWith)
- README: prepend 'Oh My Pi (omp) Compatibility' section with install
  commands, verified-components table, upstream lineage, and rationale
- CHANGELOG: add '0.22.0-evandro.1' entry under Unreleased
- docs/: rename @llblab/pi-telegram imports to @evandrodevbr/oh-my-pi-telegram
- tests/public-api.test.ts: rename package import paths

Gates re-run on the fork:
- npm run typecheck  -> tsc --noEmit (success)
- npm test           -> 1229 pass / 0 fail / 1 platform-only skip
- npm run audit      -> found 0 vulnerabilities
- npm run pack:check -> evandrodevbr-oh-my-pi-telegram-0.22.0-evandro.1.tgz

Verified:
- omp install --link ./pi-telegram -> Linked OK
- omp plugin list -> @evandrodevbr/[email protected].0-evandro.1

Upstream lineage: badlogic/pi-telegram -> llblab/pi-telegram (0.22.0) -> evandrodevbr/oh-my-pi-telegram (this fork)
2026-07-15 14:18:16 -03:00

264 lines
7.6 KiB
TypeScript

/**
* Regression tests for Telegram settings menu helpers
* Exercises settings text/markup, callback mutations, stale-message fallback, and runtime wiring
*/
import assert from "node:assert/strict";
import test from "node:test";
import {
buildProactivePushSettingsReplyMarkup,
buildProactivePushSettingsText,
buildAssistantRenderingSettingsReplyMarkup,
buildAssistantRenderingSettingsText,
buildDraftPreviewsSettingsReplyMarkup,
buildDraftPreviewsSettingsText,
buildTelegramSettingsMenuReplyMarkup,
buildTelegramSettingsMenuText,
buildTimeInjectionModeSettingsReplyMarkup,
buildVoiceReplyModeSettingsReplyMarkup,
createTelegramSettingsMenuRuntime,
handleTelegramSettingsMenuCallbackAction,
} from "../lib/menu-settings.ts";
test("Settings menu text and reply markup expose built-in controls", () => {
assert.equal(buildTelegramSettingsMenuText(), "<b>⚙️ Settings:</b>");
const markup = buildTelegramSettingsMenuReplyMarkup(
true,
false,
"manual",
"hidden",
undefined,
false,
);
assert.deepEqual(
markup.inline_keyboard.map((row) => row[0]?.callback_data),
[
"menu:back",
"settings:open:voice-reply",
"settings:open:time-injection",
"settings:open:draft-previews",
"settings:open:assistant-rendering",
"settings:open:proactive",
],
);
assert.equal(markup.inline_keyboard[1]?.[0]?.text, "👄 Voice reply: hidden");
assert.equal(
markup.inline_keyboard[2]?.[0]?.text,
"🕒 Time injection: hidden",
);
assert.equal(markup.inline_keyboard[3]?.[0]?.text, "📝 Draft previews: off");
assert.equal(markup.inline_keyboard[4]?.[0]?.text, "🧾 Rendering: rich");
assert.equal(markup.inline_keyboard[5]?.[0]?.text, "📌 Proactive push: on");
});
test("Settings detail markups show active values", () => {
assert.match(buildProactivePushSettingsText(true), /<code>on<\/code>/);
assert.match(buildDraftPreviewsSettingsText(false), /<code>off<\/code>/);
assert.equal(
buildDraftPreviewsSettingsReplyMarkup(true).inline_keyboard[1]?.[0]?.text,
"🟢 On",
);
assert.match(buildAssistantRenderingSettingsText("html"), /<code>html<\/code>/);
assert.equal(
buildAssistantRenderingSettingsReplyMarkup("rich").inline_keyboard[1]?.[0]
?.text,
"🟢 rich",
);
assert.equal(
buildProactivePushSettingsReplyMarkup(false).inline_keyboard[1]?.[1]?.text,
"🟡 Off",
);
assert.equal(
buildTimeInjectionModeSettingsReplyMarkup("interval")
.inline_keyboard[3]?.[0]?.text,
"🟢 interval",
);
assert.equal(
buildVoiceReplyModeSettingsReplyMarkup("mirror", true)
.inline_keyboard[3]?.[0]?.text,
"🟢 mirror",
);
assert.equal(
buildVoiceReplyModeSettingsReplyMarkup("manual", false)
.inline_keyboard[1]?.[0]?.text,
"🟢 hidden",
);
});
test("Settings callback action mutates voice, time, and proactive settings", async () => {
const calls: string[] = [];
const deps = {
isProactivePushEnabled: () => false,
getVoiceReplyMode: () => "manual" as const,
isVoiceReplyModeConfigured: () => true,
getTimeInjectionMode: () => "hidden" as const,
areDraftPreviewsEnabled: () => false,
getAssistantRenderingMode: () => "rich" as const,
setProactivePushEnabled: async (enabled: boolean) => {
calls.push(`proactive:${enabled}`);
},
setDraftPreviewsEnabled: async (enabled: boolean) => {
calls.push(`draft-previews:${enabled}`);
},
setAssistantRenderingMode: async (mode: "rich" | "html") => {
calls.push(`rendering:${mode}`);
},
setVoiceReplyMode: async (
mode: "manual" | "mirror" | "always" | undefined,
) => {
calls.push(`voice:${mode ?? "hidden"}`);
},
setTimeInjectionMode: async (mode: "hidden" | "always" | "interval") => {
calls.push(`time:${mode}`);
},
updateSettingsMessage: async (text: string) => {
calls.push(`update:${text.split("\n")[0]}`);
},
answerCallbackQuery: async (_id: string, text?: string) => {
calls.push(`answer:${text ?? ""}`);
},
};
assert.equal(
await handleTelegramSettingsMenuCallbackAction(
"q1",
"settings:set:voice-reply:hidden",
deps,
),
true,
);
assert.equal(
await handleTelegramSettingsMenuCallbackAction(
"q2",
"settings:set:time:off",
deps,
),
true,
);
assert.equal(
await handleTelegramSettingsMenuCallbackAction(
"q3",
"settings:set:draft-previews:on",
deps,
),
true,
);
assert.equal(
await handleTelegramSettingsMenuCallbackAction(
"q4",
"settings:set:assistant-rendering:html",
deps,
),
true,
);
assert.equal(
await handleTelegramSettingsMenuCallbackAction(
"q5",
"settings:set:proactive:on",
deps,
),
true,
);
assert.equal(
await handleTelegramSettingsMenuCallbackAction("q6", "other", deps),
false,
);
assert.deepEqual(calls, [
"voice:hidden",
"update:<b>👄 Voice reply mode:</b> <code>manual</code>",
"answer:Voice reply mode: hidden",
"time:hidden",
"update:<b>🕒 Time injection mode:</b> <code>hidden</code>",
"answer:Time injection: hidden",
"draft-previews:true",
"update:<b>📝 Draft previews:</b> <code>off</code>",
"answer:Draft previews enabled",
"rendering:html",
"update:<b>🧾 Assistant rendering:</b> <code>rich</code>",
"answer:Rendering: html",
"proactive:true",
"update:<b>📌 Proactive push:</b> <code>off</code>",
"answer:Proactive push enabled",
]);
});
test("Settings runtime opens menus and applies stale-message fallback toggles", async () => {
const state: any = {
chatId: 1,
messageId: 2,
mode: "status",
page: 0,
scope: "all",
scopedModels: [],
allModels: [],
};
const calls: string[] = [];
const runtime = createTelegramSettingsMenuRuntime({
isProactivePushEnabled: () => true,
getVoiceReplyMode: () => "manual",
isVoiceReplyModeConfigured: () => true,
getTimeInjectionMode: () => "hidden",
areDraftPreviewsEnabled: () => false,
getAssistantRenderingMode: () => "rich",
setProactivePushEnabled: async (enabled) => {
calls.push(`proactive:${enabled}`);
},
setDraftPreviewsEnabled: async (enabled) => {
calls.push(`draft-previews:${enabled}`);
},
setAssistantRenderingMode: async (mode) => {
calls.push(`rendering:${mode}`);
},
setVoiceReplyMode: async (mode) => {
calls.push(`voice:${mode ?? "hidden"}`);
},
setTimeInjectionMode: async (mode) => {
calls.push(`time:${mode}`);
},
getModelMenuState: async () => state,
getStoredModelMenuState: () => undefined,
storeModelMenuState: (nextState) => calls.push(`store:${nextState.mode}`),
editInteractiveMessage: async () => {
calls.push("edit");
},
sendInteractiveMessage: async (_chatId, _text, mode) => {
calls.push(`send:${mode}`);
return 99;
},
answerCallbackQuery: async (_id, text) => {
calls.push(`answer:${text ?? ""}`);
},
});
await runtime.openSettingsMenu(1, 2, "ctx");
assert.equal(state.messageId, 99);
assert.equal(state.mode, "settings");
assert.equal(
await runtime.handleCallbackQuery(
{ id: "q1", data: "settings:set:voice-reply:always" },
"ctx",
),
true,
);
assert.equal(
await runtime.handleCallbackQuery(
{ id: "q2", data: "settings:set:time:off" },
"ctx",
),
true,
);
assert.deepEqual(calls, [
"send:html",
"store:settings",
"voice:always",
"answer:Voice reply mode: always",
"time:hidden",
"answer:Time injection: hidden",
]);
});