From 221cd4fb178f7ea45b5f7483ba32d9267cf2dd27 Mon Sep 17 00:00:00 2001 From: Stanislav Popov Date: Fri, 27 Jun 2025 17:58:55 +0500 Subject: [PATCH] test: add coverage for telegram context --- tests/telegram/context.test.ts | 105 +++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 tests/telegram/context.test.ts diff --git a/tests/telegram/context.test.ts b/tests/telegram/context.test.ts new file mode 100644 index 0000000..cd629c4 --- /dev/null +++ b/tests/telegram/context.test.ts @@ -0,0 +1,105 @@ +import { jest, describe, it, expect, beforeEach } from "@jest/globals"; +import type { Context, Update } from "telegraf"; +import type { ConfigChatType } from "../../src/types"; + +const mockUseConfig = jest.fn(); +const mockLog = jest.fn(); + +jest.unstable_mockModule("../../src/config.ts", () => ({ + useConfig: () => mockUseConfig(), +})); + +jest.unstable_mockModule("../../src/helpers.ts", () => ({ + log: (...args: unknown[]) => mockLog(...args), +})); + +let getActionUserMsg: typeof import("../../src/telegram/context.ts").getActionUserMsg; +let getCtxChatMsg: typeof import("../../src/telegram/context.ts").getCtxChatMsg; + +beforeEach(async () => { + jest.resetModules(); + mockUseConfig.mockReset(); + mockLog.mockReset(); + const mod = await import("../../src/telegram/context.ts"); + getActionUserMsg = mod.getActionUserMsg; + getCtxChatMsg = mod.getCtxChatMsg; +}); + +function createCtx(update?: Partial, botName = "bot") { + return { + ...(update ? { update } : {}), + botInfo: { username: botName }, + } as unknown as Context; +} + +describe("getActionUserMsg", () => { + it("returns user and message from callback query", () => { + const ctx = createCtx({ + callback_query: { + from: { id: 1, username: "u" }, + message: { text: "hi" }, + }, + }); + const res = getActionUserMsg(ctx); + expect(res.user).toEqual({ id: 1, username: "u" }); + expect(res.msg).toEqual({ text: "hi" }); + }); + + it("returns empty object when no callback", () => { + const res = getActionUserMsg(createCtx()); + expect(res).toEqual({}); + }); +}); + +describe("getCtxChatMsg", () => { + const baseChat: ConfigChatType = { + id: 123, + name: "default", + completionParams: {}, + chatParams: {}, + toolParams: {}, + } as ConfigChatType; + + function createMsg(username: string) { + return { + chat: { id: 123, type: "private", username }, + from: { username }, + text: "hi", + } as any; + } + + it("returns chat when user allowed", () => { + mockUseConfig.mockReturnValue({ chats: [baseChat], privateUsers: [] }); + const ctx = createCtx({ message: createMsg("u") }); + const { chat, msg } = getCtxChatMsg(ctx); + expect(chat).toMatchObject(baseChat); + expect(msg?.text).toBe("hi"); + }); + + it("returns undefined chat when user not allowed", () => { + mockUseConfig.mockReturnValue({ + chats: [{ ...baseChat, privateUsers: ["other"] }], + privateUsers: [], + }); + // use different chat id to trigger access check + const ctx = createCtx({ + message: { + ...createMsg("u"), + chat: { id: 999, type: "private", username: "u" }, + }, + }); + const { chat } = getCtxChatMsg(ctx); + expect(chat).toBeUndefined(); + }); + + it("allows admin users", () => { + mockUseConfig.mockReturnValue({ + chats: [baseChat], + privateUsers: [], + adminUsers: ["admin"], + }); + const ctx = createCtx({ message: createMsg("admin") }); + const { chat } = getCtxChatMsg(ctx); + expect(chat).toMatchObject(baseChat); + }); +});