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)
264 lines
7.6 KiB
TypeScript
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",
|
|
]);
|
|
});
|