




















@@ -0,0 +1,146 @@
1+import { beforeEach, describe, expect, it, vi } from "vitest";
2+import type { BuildTelegramMessageContextParams } from "./bot-message-context.types.js";
3+4+const inboundBodyMock = vi.hoisted(() =>
5+vi.fn(async () => ({
6+bodyText: "hello",
7+rawBody: "hello",
8+historyKey: undefined,
9+commandAuthorized: false,
10+effectiveWasMentioned: false,
11+canDetectMention: true,
12+shouldBypassMention: false,
13+stickerCacheHit: false,
14+locationData: undefined,
15+})),
16+);
17+18+vi.mock("./bot-message-context.body.js", () => ({
19+resolveTelegramInboundBody: (...args: unknown[]) => inboundBodyMock(...args),
20+}));
21+22+const { buildTelegramMessageContextForTest } =
23+await import("./bot-message-context.test-harness.js");
24+25+type CreateStatusReactionController = NonNullable<
26+NonNullable<BuildTelegramMessageContextParams["runtime"]>["createStatusReactionController"]
27+>;
28+type StatusReactionControllerParams = Parameters<CreateStatusReactionController>[0];
29+30+function createStatusReactionControllerStub() {
31+const controller = {
32+setQueued: vi.fn(async () => undefined),
33+setThinking: vi.fn(async () => undefined),
34+setTool: vi.fn(async () => undefined),
35+setCompacting: vi.fn(async () => undefined),
36+cancelPending: vi.fn(),
37+setDone: vi.fn(async () => undefined),
38+setError: vi.fn(async () => undefined),
39+clear: vi.fn(async () => undefined),
40+restoreInitial: vi.fn(async () => undefined),
41+};
42+const createStatusReactionController = vi.fn((params: StatusReactionControllerParams) => {
43+return controller;
44+});
45+return { controller, createStatusReactionController };
46+}
47+48+describe("buildTelegramMessageContext reactions", () => {
49+beforeEach(() => {
50+inboundBodyMock.mockClear();
51+});
52+53+it("does not create status reactions when the ack gate blocks an unmentioned group message", async () => {
54+const setMessageReaction = vi.fn(async () => undefined);
55+const { createStatusReactionController } = createStatusReactionControllerStub();
56+57+const ctx = await buildTelegramMessageContextForTest({
58+message: {
59+message_id: 12,
60+chat: { id: -1001234567890, type: "group", title: "Ops" },
61+date: 1_700_000_000,
62+text: "hello",
63+from: { id: 42, first_name: "Alice" },
64+},
65+cfg: {
66+agents: {
67+defaults: { model: "anthropic/claude-opus-4-5", workspace: "/tmp/openclaw" },
68+},
69+channels: {
70+telegram: {
71+groupPolicy: "open",
72+groups: { "*": { requireMention: true } },
73+},
74+},
75+messages: {
76+ackReaction: "👀",
77+groupChat: { mentionPatterns: [] },
78+statusReactions: { enabled: true },
79+},
80+},
81+ackReactionScope: "group-mentions",
82+botApi: { setMessageReaction },
83+runtime: { createStatusReactionController },
84+resolveGroupActivation: () => true,
85+resolveGroupRequireMention: () => true,
86+resolveTelegramGroupConfig: () => ({
87+groupConfig: { requireMention: true },
88+topicConfig: undefined,
89+}),
90+});
91+92+expect(ctx).not.toBeNull();
93+expect(ctx?.ackReactionPromise).toBeNull();
94+expect(ctx?.statusReactionController).toBeNull();
95+expect(createStatusReactionController).not.toHaveBeenCalled();
96+expect(setMessageReaction).not.toHaveBeenCalled();
97+});
98+99+it("keeps Telegram status reaction variants available for configured emoji fallbacks", async () => {
100+const setMessageReaction = vi.fn(async () => undefined);
101+const { controller, createStatusReactionController } = createStatusReactionControllerStub();
102+103+const ctx = await buildTelegramMessageContextForTest({
104+message: {
105+message_id: 34,
106+chat: {
107+id: 1234,
108+type: "private",
109+available_reactions: [{ type: "emoji", emoji: "👍" }],
110+},
111+date: 1_700_000_000,
112+text: "hello",
113+from: { id: 42, first_name: "Alice" },
114+},
115+cfg: {
116+agents: {
117+defaults: { model: "anthropic/claude-opus-4-5", workspace: "/tmp/openclaw" },
118+},
119+channels: { telegram: { dmPolicy: "open", allowFrom: ["*"] } },
120+messages: {
121+ackReaction: "👀",
122+groupChat: { mentionPatterns: [] },
123+statusReactions: {
124+enabled: true,
125+emojis: { done: "✅" },
126+},
127+},
128+},
129+ackReactionScope: "direct",
130+botApi: { setMessageReaction },
131+runtime: { createStatusReactionController },
132+});
133+134+await expect(ctx?.ackReactionPromise).resolves.toBe(true);
135+expect(controller.setQueued).toHaveBeenCalledTimes(1);
136+expect(createStatusReactionController).toHaveBeenCalledTimes(1);
137+138+const params = createStatusReactionController.mock.calls[0]?.[0];
139+expect(params?.initialEmoji).toBe("👀");
140+expect(params?.emojis?.done).toBe("✅");
141+142+await params?.adapter.setReaction("✅");
143+144+expect(setMessageReaction).toHaveBeenCalledWith(1234, 34, [{ type: "emoji", emoji: "👍" }]);
145+});
146+});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。