mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-18 21:34:46 +00:00
test: clear telegram session meta broad matchers
This commit is contained in:
@@ -442,15 +442,73 @@ function createConfiguredBindingRoute(
|
||||
};
|
||||
}
|
||||
|
||||
function requireValue<T>(value: T | null | undefined, label: string): T {
|
||||
if (value == null) {
|
||||
throw new Error(`expected ${label}`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function requireRecord(value: unknown, label: string): Record<string, unknown> {
|
||||
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
||||
throw new Error(`expected ${label} to be an object`);
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
function expectRecordFields(
|
||||
value: unknown,
|
||||
expected: Record<string, unknown>,
|
||||
label: string,
|
||||
): Record<string, unknown> {
|
||||
const record = requireRecord(value, label);
|
||||
for (const [key, expectedValue] of Object.entries(expected)) {
|
||||
expect(record[key], `${label}.${key}`).toEqual(expectedValue);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
function expectSendMessageCall(params: {
|
||||
sendMessage: ReturnType<typeof vi.fn>;
|
||||
callIndex?: number;
|
||||
chatId: unknown;
|
||||
text?: string;
|
||||
textIncludes?: string;
|
||||
optionFields?: Record<string, unknown>;
|
||||
requireReplyMarkup?: boolean;
|
||||
label: string;
|
||||
}): Record<string, unknown> {
|
||||
const call = requireValue(
|
||||
params.sendMessage.mock.calls[params.callIndex ?? 0],
|
||||
`${params.label} sendMessage call`,
|
||||
);
|
||||
expect(call[0]).toBe(params.chatId);
|
||||
if (params.text !== undefined) {
|
||||
expect(call[1]).toBe(params.text);
|
||||
}
|
||||
if (params.textIncludes !== undefined) {
|
||||
expect(String(call[1])).toContain(params.textIncludes);
|
||||
}
|
||||
const options = params.optionFields
|
||||
? expectRecordFields(call[2], params.optionFields, `${params.label} sendMessage options`)
|
||||
: requireRecord(call[2], `${params.label} sendMessage options`);
|
||||
if (params.requireReplyMarkup) {
|
||||
requireRecord(options.reply_markup, `${params.label} reply markup`);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
function expectUnauthorizedNewCommandBlocked(sendMessage: ReturnType<typeof vi.fn>) {
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
expect(persistentBindingMocks.resolveConfiguredBindingRoute).not.toHaveBeenCalled();
|
||||
expect(persistentBindingMocks.ensureConfiguredBindingRouteReady).not.toHaveBeenCalled();
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
-1001234567890,
|
||||
"You are not authorized to use this command.",
|
||||
expect.objectContaining({ message_thread_id: 42 }),
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: -1001234567890,
|
||||
text: "You are not authorized to use this command.",
|
||||
optionFields: { message_thread_id: 42 },
|
||||
label: "unauthorized /new",
|
||||
});
|
||||
}
|
||||
|
||||
describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
@@ -546,18 +604,19 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
const menuCall = commandAuthMocks.resolveCommandArgMenu.mock.calls.find(
|
||||
([params]) => params.command.key === "think" && params.provider === "anthropic",
|
||||
)?.[0];
|
||||
expect(menuCall).toEqual(
|
||||
expect.objectContaining({
|
||||
provider: "anthropic",
|
||||
model: "claude-opus-4-7",
|
||||
}),
|
||||
expectRecordFields(
|
||||
menuCall,
|
||||
{ provider: "anthropic", model: "claude-opus-4-7" },
|
||||
"thinking menu call",
|
||||
);
|
||||
expect(sessionMocks.loadSessionStore).toHaveBeenCalledWith("/tmp/openclaw-sessions.json");
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
100,
|
||||
expect.stringContaining("Current thinking level: high.\nChoose level for /think."),
|
||||
expect.objectContaining({ reply_markup: expect.any(Object) }),
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: 100,
|
||||
textIncludes: "Current thinking level: high.\nChoose level for /think.",
|
||||
requireReplyMarkup: true,
|
||||
label: "thinking menu",
|
||||
});
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -582,17 +641,18 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
const menuCall = commandAuthMocks.resolveCommandArgMenu.mock.calls.find(
|
||||
([params]) => params.command.key === "think" && params.provider === "anthropic",
|
||||
)?.[0];
|
||||
expect(menuCall).toEqual(
|
||||
expect.objectContaining({
|
||||
provider: "anthropic",
|
||||
model: "claude-opus-4-7",
|
||||
}),
|
||||
);
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
100,
|
||||
expect.stringContaining("Choose level for /think."),
|
||||
expect.objectContaining({ reply_markup: expect.any(Object) }),
|
||||
expectRecordFields(
|
||||
menuCall,
|
||||
{ provider: "anthropic", model: "claude-opus-4-7" },
|
||||
"thread thinking menu call",
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: 100,
|
||||
textIncludes: "Choose level for /think.",
|
||||
requireReplyMarkup: true,
|
||||
label: "thread thinking menu",
|
||||
});
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -626,17 +686,18 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
const menuCall = commandAuthMocks.resolveCommandArgMenu.mock.calls.find(
|
||||
([params]) => params.command.key === "think" && params.provider === "openai",
|
||||
)?.[0];
|
||||
expect(menuCall).toEqual(
|
||||
expect.objectContaining({
|
||||
provider: "openai",
|
||||
model: "gpt-5.5",
|
||||
}),
|
||||
);
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
100,
|
||||
expect.stringContaining("Current thinking level: medium.\nChoose level for /think."),
|
||||
expect.objectContaining({ reply_markup: expect.any(Object) }),
|
||||
expectRecordFields(
|
||||
menuCall,
|
||||
{ provider: "openai", model: "gpt-5.5" },
|
||||
"default model thinking menu call",
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: 100,
|
||||
textIncludes: "Current thinking level: medium.\nChoose level for /think.",
|
||||
requireReplyMarkup: true,
|
||||
label: "default model thinking menu",
|
||||
});
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -669,11 +730,13 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
});
|
||||
await handler(createTelegramPrivateCommandContext());
|
||||
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
100,
|
||||
expect.stringContaining("Current thinking level: xhigh.\nChoose level for /think."),
|
||||
expect.objectContaining({ reply_markup: expect.any(Object) }),
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: 100,
|
||||
textIncludes: "Current thinking level: xhigh.\nChoose level for /think.",
|
||||
requireReplyMarkup: true,
|
||||
label: "target model thinking menu",
|
||||
});
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -706,11 +769,13 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
});
|
||||
await handler(createTelegramPrivateCommandContext());
|
||||
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
100,
|
||||
expect.stringContaining("Current thinking level: minimal.\nChoose level for /think."),
|
||||
expect.objectContaining({ reply_markup: expect.any(Object) }),
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: 100,
|
||||
textIncludes: "Current thinking level: minimal.\nChoose level for /think.",
|
||||
requireReplyMarkup: true,
|
||||
label: "agent thinking menu",
|
||||
});
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -743,9 +808,11 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
await runPromise;
|
||||
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
const dispatcherOptions = requireRecord(
|
||||
replyMocks.dispatchReplyWithBufferedBlockDispatcher.mock.calls[0]?.[0].dispatcherOptions,
|
||||
).toEqual(expect.objectContaining({ beforeDeliver: expect.any(Function) }));
|
||||
"dispatcher options",
|
||||
);
|
||||
expect(dispatcherOptions.beforeDeliver).toBeTypeOf("function");
|
||||
});
|
||||
|
||||
it("does not inject approval buttons for native command replies once the monitor owns approvals", async () => {
|
||||
@@ -848,12 +915,10 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
const deliveredCall = deliveryMocks.deliverReplies.mock.calls[0]?.[0] as
|
||||
| DeliverRepliesParams
|
||||
| undefined;
|
||||
expect(deliveredCall).toEqual(
|
||||
expect.objectContaining({
|
||||
silent: true,
|
||||
replies: [expect.objectContaining({ isError: true })],
|
||||
}),
|
||||
);
|
||||
const deliveryParams = requireValue(deliveredCall, "silent error delivery params");
|
||||
expect(deliveryParams.silent).toBe(true);
|
||||
expect(deliveryParams.replies).toHaveLength(1);
|
||||
expect(deliveryParams.replies[0]?.isError).toBe(true);
|
||||
});
|
||||
|
||||
it("routes Telegram native commands through configured ACP topic bindings", async () => {
|
||||
@@ -1055,12 +1120,14 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
]
|
||||
>
|
||||
)[0]?.[0];
|
||||
expect(dispatchCall?.ctx).toEqual(
|
||||
expect.objectContaining({
|
||||
expectRecordFields(
|
||||
dispatchCall?.ctx,
|
||||
{
|
||||
CommandTargetSessionKey: "agent:main:telegram:group:-1001234567890:topic:42",
|
||||
MessageThreadId: 42,
|
||||
OriginatingTo: "telegram:-1001234567890:topic:42",
|
||||
}),
|
||||
},
|
||||
"topic dispatch context",
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1091,11 +1158,13 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
await handler(createTelegramTopicCommandContext());
|
||||
|
||||
expect(replyMocks.dispatchReplyWithBufferedBlockDispatcher).not.toHaveBeenCalled();
|
||||
expect(sendMessage).toHaveBeenCalledWith(
|
||||
-1001234567890,
|
||||
"Configured ACP binding is unavailable right now. Please try again.",
|
||||
expect.objectContaining({ message_thread_id: 42 }),
|
||||
);
|
||||
expectSendMessageCall({
|
||||
sendMessage,
|
||||
chatId: -1001234567890,
|
||||
text: "Configured ACP binding is unavailable right now. Please try again.",
|
||||
optionFields: { message_thread_id: 42 },
|
||||
label: "unavailable ACP binding",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps /new blocked in ACP-bound Telegram topics when sender is unauthorized", async () => {
|
||||
@@ -1180,22 +1249,26 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
createTelegramTopicCommandContext({ match: "bind --cwd /tmp/work", threadId: 42 }),
|
||||
);
|
||||
|
||||
expect(sessionMocks.resolveAndPersistSessionFile).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
expectRecordFields(
|
||||
sessionMocks.resolveAndPersistSessionFile.mock.calls[0]?.[0],
|
||||
{
|
||||
sessionId: "sess-topic",
|
||||
sessionKey: "agent:main:telegram:group:-1001234567890:topic:42",
|
||||
storePath: "/tmp/openclaw-sessions/sessions.json",
|
||||
sessionsDir: "/tmp/openclaw-sessions",
|
||||
fallbackSessionFile: path.resolve("/tmp/openclaw-sessions", "sess-topic-topic-42.jsonl"),
|
||||
}),
|
||||
},
|
||||
"resolved session file params",
|
||||
);
|
||||
expect(pluginRuntimeMocks.executePluginCommand).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
expectRecordFields(
|
||||
(pluginRuntimeMocks.executePluginCommand.mock.calls as unknown as Array<[unknown]>)[0]?.[0],
|
||||
{
|
||||
sessionKey: "agent:main:telegram:group:-1001234567890:topic:42",
|
||||
sessionId: "sess-topic",
|
||||
sessionFile: path.resolve("/tmp/openclaw-sessions", "sess-topic-topic-42.jsonl"),
|
||||
messageThreadId: 42,
|
||||
}),
|
||||
},
|
||||
"plugin command params",
|
||||
);
|
||||
});
|
||||
|
||||
@@ -1228,10 +1301,10 @@ describe("registerTelegramNativeCommands — session metadata", () => {
|
||||
|
||||
await handler(createTelegramPrivateCommandContext({ match: "status" }));
|
||||
|
||||
expect(deliveryMocks.deliverReplies).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
replies: [{ text: "No response generated. Please try again." }],
|
||||
}),
|
||||
const deliveryCall = requireValue(
|
||||
deliveryMocks.deliverReplies.mock.calls[0]?.[0],
|
||||
"empty response delivery params",
|
||||
);
|
||||
expect(deliveryCall.replies).toEqual([{ text: "No response generated. Please try again." }]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user