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

138 lines
3.5 KiB
TypeScript

/**
* Regression tests for Telegram outbound voice delivery helpers
* Exercises direct voice-sender ownership after extraction from outbound.ts
*/
import assert from "node:assert/strict";
import test from "node:test";
import { createTelegramVoiceReplySender } from "../lib/outbound-voice.ts";
import { createTelegramThreadTarget } from "../lib/target.ts";
import {
clearTelegramVoiceSynthesisProviders,
registerTelegramVoiceSynthesisProvider,
} from "../lib/voice.ts";
test.beforeEach(() => {
clearTelegramVoiceSynthesisProviders();
});
test("Outbound voice sender uploads provider opus result with reply markup and transcript", async () => {
registerTelegramVoiceSynthesisProvider(
async () => ({ audioPath: "/tmp/direct.opus", transcriptText: "spoken" }),
{ id: "direct-test" },
);
const uploads: unknown[] = [];
const actions: unknown[] = [];
const sendVoice = createTelegramVoiceReplySender({
execCommand: async () => ({
stdout: "",
stderr: "",
code: 0,
killed: false,
}),
sendRecordVoiceAction: async (chatId) => {
actions.push(chatId);
},
sendMultipart: async (...args) => {
uploads.push(args);
},
});
await sendVoice({ chatId: 1, replyToMessageId: 2 }, "hello", {
replyMarkup: { inline_keyboard: [] },
replyToPrompt: true,
});
assert.deepEqual(actions, [1]);
assert.deepEqual(uploads, [
[
"sendVoice",
{
chat_id: "1",
caption: "spoken",
reply_parameters: JSON.stringify({
message_id: 2,
allow_sending_without_reply: true,
}),
reply_markup: JSON.stringify({ inline_keyboard: [] }),
},
"voice",
"/tmp/direct.opus",
"direct.opus",
],
]);
});
test("Outbound voice sender uploads voice into thread target", async () => {
registerTelegramVoiceSynthesisProvider(async () => "/tmp/direct.ogg", {
id: "thread-test",
});
const uploads: unknown[] = [];
const sendVoice = createTelegramVoiceReplySender({
execCommand: async () => ({
stdout: "",
stderr: "",
code: 0,
killed: false,
}),
sendMultipart: async (...args) => {
uploads.push(args);
},
});
await sendVoice(
{
chatId: -1007,
replyToMessageId: 2,
target: createTelegramThreadTarget(-1007, 42),
},
"hello",
);
const fields = (uploads[0] as unknown[])[1] as Record<string, string>;
assert.equal(fields.chat_id, "-1007");
assert.equal(fields.message_thread_id, "42");
assert.equal(
fields.reply_parameters,
JSON.stringify({
message_id: 2,
allow_sending_without_reply: true,
}),
);
});
test("Outbound voice sender records and throws when every source fails", async () => {
const events: Array<{ category: string; message: string; phase?: unknown }> =
[];
const sendVoice = createTelegramVoiceReplySender({
execCommand: async () => ({
stdout: "",
stderr: "",
code: 0,
killed: false,
}),
sendMultipart: async () => {},
recordRuntimeEvent: (category, error, details) => {
events.push({
category,
message: (error as Error).message,
phase: details?.phase,
});
},
});
await assert.rejects(
sendVoice({ chatId: 1, replyToMessageId: 2 }, "hello"),
/every voice synthesis provider and outbound voice handler failed/,
);
assert.deepEqual(events, [
{
category: "voice",
message:
"Failed to send voice reply: every voice synthesis provider and outbound voice handler failed.",
phase: "send",
},
]);
});