import { beforeAll, beforeEach, describe, expect, it, vi } from "vitest" ;
import type { TelegramBotDeps } from "./bot-deps.js" ;
const buildTelegramMessageContext = vi.hoisted(() => vi.fn());
const dispatchTelegramMessage = vi.hoisted(() => vi.fn());
const upsertChannelPairingRequest = vi.hoisted(() =>
vi.fn(async () => ({ code: "PAIRCODE" , created: true })),
);
vi.mock("./bot-message-context.js" , () => ({
buildTelegramMessageContext,
}));
vi.mock("./bot-message-dispatch.js" , () => ({
dispatchTelegramMessage,
}));
let createTelegramMessageProcessor: typeof import ("./bot-message.js" ).createTelegramMessageProcessor;
describe("telegram bot message processor" , () => {
beforeAll(async () => {
({ createTelegramMessageProcessor } = await import ("./bot-message.js" ));
});
beforeEach(() => {
buildTelegramMessageContext.mockClear();
dispatchTelegramMessage.mockClear();
upsertChannelPairingRequest.mockClear();
});
const telegramDepsForTest = {
upsertChannelPairingRequest,
} as unknown as TelegramBotDeps;
const baseDeps = {
bot: {},
cfg: {},
account: {},
telegramCfg: {},
historyLimit: 0 ,
groupHistories: {},
dmPolicy: {},
allowFrom: [],
groupAllowFrom: [],
ackReactionScope: "none" ,
logger: {},
resolveGroupActivation: () => true ,
resolveGroupRequireMention: () => false ,
resolveTelegramGroupConfig: () => ({}),
runtime: {},
replyToMode: "auto" ,
streamMode: "partial" ,
textLimit: 4096 ,
telegramDeps: telegramDepsForTest,
opts: {},
} as unknown as Parameters<typeof createTelegramMessageProcessor>[0 ];
async function processSampleMessage(
processMessage: ReturnType<typeof createTelegramMessageProcessor>,
) {
await processMessage(
{
message: {
chat: { id: 123 , type: "private" , title: "chat" },
message_id: 456 ,
},
} as unknown as Parameters<typeof processMessage>[0 ],
[],
[],
{},
);
}
function createDispatchFailureHarness(
context: Record<string, unknown>,
sendMessage: ReturnType<typeof vi.fn>,
) {
const runtimeError = vi.fn();
buildTelegramMessageContext.mockResolvedValue(context);
dispatchTelegramMessage.mockRejectedValue(new Error("dispatch exploded" ));
const processMessage = createTelegramMessageProcessor({
...baseDeps,
bot: { api: { sendMessage } },
runtime: { error: runtimeError },
} as unknown as Parameters<typeof createTelegramMessageProcessor>[0 ]);
return { processMessage, runtimeError };
}
it("dispatches when context is available" , async () => {
buildTelegramMessageContext.mockResolvedValue({ route: { sessionKey: "agent:main:main" } });
const processMessage = createTelegramMessageProcessor(baseDeps);
await processSampleMessage(processMessage);
expect(dispatchTelegramMessage).toHaveBeenCalledTimes(1 );
});
it("skips dispatch when no context is produced" , async () => {
buildTelegramMessageContext.mockResolvedValue(null );
const processMessage = createTelegramMessageProcessor(baseDeps);
await processSampleMessage(processMessage);
expect(dispatchTelegramMessage).not.toHaveBeenCalled();
});
it("sends user-visible fallback when dispatch throws" , async () => {
const sendMessage = vi.fn().mockResolvedValue(undefined);
const { processMessage, runtimeError } = createDispatchFailureHarness(
{
chatId: 123 ,
threadSpec: { id: 456 , scope: "forum" },
route: { sessionKey: "agent:main:main" },
},
sendMessage,
);
await expect(processSampleMessage(processMessage)).resolves.toBeUndefined();
expect(sendMessage).toHaveBeenCalledWith(
123 ,
"Something went wrong while processing your request. Please try again." ,
{ message_thread_id: 456 },
);
expect(runtimeError).toHaveBeenCalledWith(expect.stringContaining("dispatch exploded" ));
});
it("omits message_thread_id for General-topic fallback replies" , async () => {
const sendMessage = vi.fn().mockResolvedValue(undefined);
const { processMessage } = createDispatchFailureHarness(
{
chatId: 123 ,
threadSpec: { id: 1 , scope: "forum" },
route: { sessionKey: "agent:main:main" },
},
sendMessage,
);
await expect(processSampleMessage(processMessage)).resolves.toBeUndefined();
expect(sendMessage).toHaveBeenCalledWith(
123 ,
"Something went wrong while processing your request. Please try again." ,
undefined,
);
});
it("swallows fallback delivery failures after dispatch throws" , async () => {
const sendMessage = vi.fn().mockRejectedValue(new Error("blocked by user" ));
const { processMessage, runtimeError } = createDispatchFailureHarness(
{
chatId: 123 ,
route: { sessionKey: "agent:main:main" },
},
sendMessage,
);
await expect(processSampleMessage(processMessage)).resolves.toBeUndefined();
expect(sendMessage).toHaveBeenCalledWith(
123 ,
"Something went wrong while processing your request. Please try again." ,
undefined,
);
expect(runtimeError).toHaveBeenCalledWith(expect.stringContaining("dispatch exploded" ));
});
});
Messung V0.5 in Prozent C=94 H=95 G=94
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-05)
¤
*© Formatika GbR, Deutschland