refactor(tests): dedupe browser and telegram tool test fixtures
This commit is contained in:
@@ -108,16 +108,33 @@ function mockSingleBrowserProxyNode() {
|
||||
]);
|
||||
}
|
||||
|
||||
describe("browser tool snapshot maxChars", () => {
|
||||
function resetBrowserToolMocks() {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
}
|
||||
|
||||
function registerBrowserToolAfterEachReset() {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
resetBrowserToolMocks();
|
||||
});
|
||||
}
|
||||
|
||||
async function runSnapshotToolCall(params: {
|
||||
snapshotFormat: "ai" | "aria";
|
||||
refs?: "aria" | "dom";
|
||||
maxChars?: number;
|
||||
profile?: string;
|
||||
}) {
|
||||
const tool = createBrowserTool();
|
||||
await tool.execute?.("call-1", { action: "snapshot", ...params });
|
||||
}
|
||||
|
||||
describe("browser tool snapshot maxChars", () => {
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("applies the default ai snapshot limit", async () => {
|
||||
const tool = createBrowserTool();
|
||||
await tool.execute?.("call-1", { action: "snapshot", snapshotFormat: "ai" });
|
||||
await runSnapshotToolCall({ snapshotFormat: "ai" });
|
||||
|
||||
expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith(
|
||||
undefined,
|
||||
@@ -184,8 +201,7 @@ describe("browser tool snapshot maxChars", () => {
|
||||
configMocks.loadConfig.mockReturnValue({
|
||||
browser: { snapshotDefaults: { mode: "efficient" } },
|
||||
});
|
||||
const tool = createBrowserTool();
|
||||
await tool.execute?.("call-1", { action: "snapshot", snapshotFormat: "ai" });
|
||||
await runSnapshotToolCall({ snapshotFormat: "ai" });
|
||||
|
||||
expect(browserClientMocks.browserSnapshot).toHaveBeenCalledWith(
|
||||
undefined,
|
||||
@@ -263,11 +279,7 @@ describe("browser tool snapshot maxChars", () => {
|
||||
});
|
||||
|
||||
describe("browser tool url alias support", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
});
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("accepts url alias for open", async () => {
|
||||
const tool = createBrowserTool();
|
||||
@@ -308,11 +320,7 @@ describe("browser tool url alias support", () => {
|
||||
});
|
||||
|
||||
describe("browser tool act compatibility", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
});
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("accepts flattened act params for backward compatibility", async () => {
|
||||
const tool = createBrowserTool();
|
||||
@@ -364,10 +372,7 @@ describe("browser tool act compatibility", () => {
|
||||
});
|
||||
|
||||
describe("browser tool snapshot labels", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
});
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("returns image + text when labels are requested", async () => {
|
||||
const tool = createBrowserTool();
|
||||
@@ -409,11 +414,7 @@ describe("browser tool snapshot labels", () => {
|
||||
});
|
||||
|
||||
describe("browser tool external content wrapping", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
});
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("wraps aria snapshots as external content", async () => {
|
||||
browserClientMocks.browserSnapshot.mockResolvedValueOnce({
|
||||
@@ -525,11 +526,7 @@ describe("browser tool external content wrapping", () => {
|
||||
});
|
||||
|
||||
describe("browser tool act stale target recovery", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
configMocks.loadConfig.mockReturnValue({ browser: {} });
|
||||
nodesUtilsMocks.listNodes.mockResolvedValue([]);
|
||||
});
|
||||
registerBrowserToolAfterEachReset();
|
||||
|
||||
it("retries chrome act once without targetId when tab id is stale", async () => {
|
||||
browserActionsMocks.browserAct
|
||||
|
||||
@@ -51,6 +51,22 @@ describe("handleTelegramAction", () => {
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
async function sendInlineButtonsMessage(params: {
|
||||
to: string;
|
||||
buttons: Array<Array<{ text: string; callback_data: string; style?: string }>>;
|
||||
inlineButtons: "dm" | "group" | "all";
|
||||
}) {
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to: params.to,
|
||||
content: "Choose",
|
||||
buttons: params.buttons,
|
||||
},
|
||||
telegramConfig({ capabilities: { inlineButtons: params.inlineButtons } }),
|
||||
);
|
||||
}
|
||||
|
||||
async function expectReactionAdded(reactionLevel: "minimal" | "extensive") {
|
||||
await handleTelegramAction(defaultReactionAction, reactionConfig(reactionLevel));
|
||||
expect(reactMessageTelegram).toHaveBeenCalledWith(
|
||||
@@ -103,9 +119,6 @@ describe("handleTelegramAction", () => {
|
||||
});
|
||||
|
||||
it("accepts snake_case message_id for reactions", async () => {
|
||||
const cfg = {
|
||||
channels: { telegram: { botToken: "tok", reactionLevel: "minimal" } },
|
||||
} as OpenClawConfig;
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "react",
|
||||
@@ -113,7 +126,7 @@ describe("handleTelegramAction", () => {
|
||||
message_id: "456",
|
||||
emoji: "✅",
|
||||
},
|
||||
cfg,
|
||||
reactionConfig("minimal"),
|
||||
);
|
||||
expect(reactMessageTelegram).toHaveBeenCalledWith(
|
||||
"123",
|
||||
@@ -143,9 +156,6 @@ describe("handleTelegramAction", () => {
|
||||
});
|
||||
|
||||
it("removes reactions on empty emoji", async () => {
|
||||
const cfg = {
|
||||
channels: { telegram: { botToken: "tok", reactionLevel: "minimal" } },
|
||||
} as OpenClawConfig;
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "react",
|
||||
@@ -153,7 +163,7 @@ describe("handleTelegramAction", () => {
|
||||
messageId: "456",
|
||||
emoji: "",
|
||||
},
|
||||
cfg,
|
||||
reactionConfig("minimal"),
|
||||
);
|
||||
expect(reactMessageTelegram).toHaveBeenCalledWith(
|
||||
"123",
|
||||
@@ -476,44 +486,29 @@ describe("handleTelegramAction", () => {
|
||||
});
|
||||
|
||||
it("allows inline buttons in DMs with tg: prefixed targets", async () => {
|
||||
const cfg = telegramConfig({ capabilities: { inlineButtons: "dm" } });
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to: "tg:5232990709",
|
||||
content: "Choose",
|
||||
buttons: [[{ text: "Ok", callback_data: "cmd:ok" }]],
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
await sendInlineButtonsMessage({
|
||||
to: "tg:5232990709",
|
||||
buttons: [[{ text: "Ok", callback_data: "cmd:ok" }]],
|
||||
inlineButtons: "dm",
|
||||
});
|
||||
expect(sendMessageTelegram).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows inline buttons in groups with topic targets", async () => {
|
||||
const cfg = telegramConfig({ capabilities: { inlineButtons: "group" } });
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to: "telegram:group:-1001234567890:topic:456",
|
||||
content: "Choose",
|
||||
buttons: [[{ text: "Ok", callback_data: "cmd:ok" }]],
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
await sendInlineButtonsMessage({
|
||||
to: "telegram:group:-1001234567890:topic:456",
|
||||
buttons: [[{ text: "Ok", callback_data: "cmd:ok" }]],
|
||||
inlineButtons: "group",
|
||||
});
|
||||
expect(sendMessageTelegram).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sends messages with inline keyboard buttons when enabled", async () => {
|
||||
const cfg = telegramConfig({ capabilities: { inlineButtons: "all" } });
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to: "@testchannel",
|
||||
content: "Choose",
|
||||
buttons: [[{ text: " Option A ", callback_data: " cmd:a " }]],
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
await sendInlineButtonsMessage({
|
||||
to: "@testchannel",
|
||||
buttons: [[{ text: " Option A ", callback_data: " cmd:a " }]],
|
||||
inlineButtons: "all",
|
||||
});
|
||||
expect(sendMessageTelegram).toHaveBeenCalledWith(
|
||||
"@testchannel",
|
||||
"Choose",
|
||||
@@ -524,24 +519,19 @@ describe("handleTelegramAction", () => {
|
||||
});
|
||||
|
||||
it("forwards optional button style", async () => {
|
||||
const cfg = telegramConfig({ capabilities: { inlineButtons: "all" } });
|
||||
await handleTelegramAction(
|
||||
{
|
||||
action: "sendMessage",
|
||||
to: "@testchannel",
|
||||
content: "Choose",
|
||||
buttons: [
|
||||
[
|
||||
{
|
||||
text: "Option A",
|
||||
callback_data: "cmd:a",
|
||||
style: "primary",
|
||||
},
|
||||
],
|
||||
await sendInlineButtonsMessage({
|
||||
to: "@testchannel",
|
||||
inlineButtons: "all",
|
||||
buttons: [
|
||||
[
|
||||
{
|
||||
text: "Option A",
|
||||
callback_data: "cmd:a",
|
||||
style: "primary",
|
||||
},
|
||||
],
|
||||
},
|
||||
cfg,
|
||||
);
|
||||
],
|
||||
});
|
||||
expect(sendMessageTelegram).toHaveBeenCalledWith(
|
||||
"@testchannel",
|
||||
"Choose",
|
||||
@@ -601,6 +591,25 @@ describe("readTelegramButtons", () => {
|
||||
});
|
||||
|
||||
describe("handleTelegramAction per-account gating", () => {
|
||||
function accountTelegramConfig(params: {
|
||||
accounts: Record<
|
||||
string,
|
||||
{ botToken: string; actions?: { sticker?: boolean; reactions?: boolean } }
|
||||
>;
|
||||
topLevelBotToken?: string;
|
||||
topLevelActions?: { reactions?: boolean };
|
||||
}): OpenClawConfig {
|
||||
return {
|
||||
channels: {
|
||||
telegram: {
|
||||
...(params.topLevelBotToken ? { botToken: params.topLevelBotToken } : {}),
|
||||
...(params.topLevelActions ? { actions: params.topLevelActions } : {}),
|
||||
accounts: params.accounts,
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
}
|
||||
|
||||
async function expectAccountStickerSend(cfg: OpenClawConfig, accountId = "media") {
|
||||
await handleTelegramAction(
|
||||
{ action: "sendSticker", to: "123", fileId: "sticker-id", accountId },
|
||||
@@ -614,15 +623,11 @@ describe("handleTelegramAction per-account gating", () => {
|
||||
}
|
||||
|
||||
it("allows sticker when account config enables it", async () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: {
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
},
|
||||
const cfg = accountTelegramConfig({
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
});
|
||||
await expectAccountStickerSend(cfg);
|
||||
});
|
||||
|
||||
@@ -647,30 +652,22 @@ describe("handleTelegramAction per-account gating", () => {
|
||||
|
||||
it("uses account-merged config, not top-level config", async () => {
|
||||
// Top-level has no sticker enabled, but the account does
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: {
|
||||
botToken: "tok-base",
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
},
|
||||
const cfg = accountTelegramConfig({
|
||||
topLevelBotToken: "tok-base",
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
});
|
||||
await expectAccountStickerSend(cfg);
|
||||
});
|
||||
|
||||
it("inherits top-level reaction gate when account overrides sticker only", async () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: {
|
||||
actions: { reactions: false },
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
},
|
||||
const cfg = accountTelegramConfig({
|
||||
topLevelActions: { reactions: false },
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true } },
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
});
|
||||
|
||||
const result = await handleTelegramAction(
|
||||
{
|
||||
@@ -689,16 +686,12 @@ describe("handleTelegramAction per-account gating", () => {
|
||||
});
|
||||
|
||||
it("allows account to explicitly re-enable top-level disabled reaction gate", async () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
telegram: {
|
||||
actions: { reactions: false },
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true, reactions: true } },
|
||||
},
|
||||
},
|
||||
const cfg = accountTelegramConfig({
|
||||
topLevelActions: { reactions: false },
|
||||
accounts: {
|
||||
media: { botToken: "tok-media", actions: { sticker: true, reactions: true } },
|
||||
},
|
||||
} as OpenClawConfig;
|
||||
});
|
||||
|
||||
await handleTelegramAction(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user