Files
oh-my-pi-telegram/tests/menu-thinking.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

175 lines
4.8 KiB
TypeScript

/**
* Regression tests for Telegram thinking menu helpers
* Exercises thinking-menu markup, callback routing, voice guards, and send/update helpers
*/
import assert from "node:assert/strict";
import test from "node:test";
import {
buildTelegramThinkingMenuRenderPayload,
buildThinkingMenuReplyMarkup,
buildThinkingMenuText,
handleTelegramThinkingMenuCallbackAction,
openTelegramThinkingMenu,
updateTelegramThinkingMenuMessage,
} from "../lib/menu-thinking.ts";
const reasoningModel = {
provider: "openai",
id: "gpt-5",
reasoning: true,
};
test("Thinking menu text and reply markup expose all levels with current marker", () => {
assert.equal(buildThinkingMenuText(), "<b>🧠 Choose a thinking level:</b>");
const markup = buildThinkingMenuReplyMarkup("medium");
assert.equal(markup.inline_keyboard[0]?.[0]?.text, "⬆️ Main menu");
assert.equal(markup.inline_keyboard[0]?.[0]?.callback_data, "menu:back");
assert.equal(
markup.inline_keyboard.some((row) => row[0]?.text === "🟢 medium"),
true,
);
assert.equal(
markup.inline_keyboard.every(
(row, index) =>
index === 0 || row[0]?.callback_data.startsWith("thinking:set:"),
),
true,
);
});
test("Thinking callback sets valid levels and reports current level", async () => {
const calls: string[] = [];
let current = "low" as const;
const handled = await handleTelegramThinkingMenuCallbackAction(
"q1",
"thinking:set:high",
reasoningModel,
{
setThinkingLevel: (level) => {
current = level as typeof current;
calls.push(`set:${level}`);
},
getCurrentThinkingLevel: () => current,
updateStatusMessage: async () => {
calls.push("update-status");
},
answerCallbackQuery: async (_id, text) => {
calls.push(text ?? "answered");
},
},
);
assert.equal(handled, true);
assert.deepEqual(calls, ["set:high", "update-status", "Thinking: high"]);
});
test("Thinking callback handles invalid, voice-active, non-reasoning, and unrelated actions", async () => {
const answered: string[] = [];
const deps = {
setThinkingLevel: () => {
throw new Error("must not set level");
},
getCurrentThinkingLevel: () => "off" as const,
updateStatusMessage: async () => {
throw new Error("must not update status");
},
answerCallbackQuery: async (_id: string, text?: string) => {
answered.push(text ?? "answered");
},
};
assert.equal(
await handleTelegramThinkingMenuCallbackAction(
"q1",
"thinking:set:nope",
reasoningModel,
deps,
),
true,
);
assert.equal(
await handleTelegramThinkingMenuCallbackAction(
"q2",
"thinking:set:low",
reasoningModel,
{ ...deps, isVoiceReplyActive: () => true },
),
true,
);
assert.equal(
await handleTelegramThinkingMenuCallbackAction(
"q3",
"thinking:set:low",
{ provider: "x", id: "plain" },
deps,
),
true,
);
assert.equal(
await handleTelegramThinkingMenuCallbackAction(
"q4",
"menu:model",
reasoningModel,
deps,
),
false,
);
assert.deepEqual(answered, [
"Invalid thinking level.",
"Thinking controls are disabled during voice replies.",
"This model has no reasoning controls.",
]);
});
test("Thinking menu open and update helpers apply thinking mode and respect voice guard", async () => {
const state: any = {
chatId: 1,
messageId: 2,
mode: "status",
page: 0,
scope: "all",
scopedModels: [],
allModels: [],
};
const messages: unknown[] = [];
const deps = {
getModelMenuState: async () => state,
getActiveModel: () => reasoningModel,
getThinkingLevel: () => "medium" as const,
storeModelMenuState: (nextState: unknown) =>
messages.push(["store", nextState]),
editInteractiveMessage: async (...args: unknown[]) => {
messages.push(["edit", ...args]);
},
sendInteractiveMessage: async (...args: unknown[]) => {
messages.push(["send", ...args]);
return 99;
},
};
await openTelegramThinkingMenu(deps);
assert.equal(state.messageId, 99);
assert.equal(state.mode, "thinking");
await updateTelegramThinkingMenuMessage(state, reasoningModel, "high", deps);
assert.equal(state.mode, "thinking");
assert.equal(messages.length, 3);
const beforeVoiceGuard = messages.length;
await openTelegramThinkingMenu({ ...deps, isVoiceReplyActive: () => true });
await updateTelegramThinkingMenuMessage(state, reasoningModel, "low", {
...deps,
isVoiceReplyActive: () => true,
});
assert.equal(messages.length, beforeVoiceGuard);
const payload = buildTelegramThinkingMenuRenderPayload(reasoningModel, "low");
assert.equal(payload.nextMode, "thinking");
assert.equal(payload.mode, "html");
});