mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-15 03:50:40 +00:00
124 lines
3.2 KiB
TypeScript
124 lines
3.2 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const createFeishuClientMock = vi.hoisted(() => vi.fn());
|
|
const fetchRemoteMediaMock = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("./client.js", () => ({
|
|
createFeishuClient: createFeishuClientMock,
|
|
}));
|
|
|
|
vi.mock("./runtime.js", () => ({
|
|
getFeishuRuntime: () => ({
|
|
channel: {
|
|
media: {
|
|
fetchRemoteMedia: fetchRemoteMediaMock,
|
|
},
|
|
},
|
|
}),
|
|
}));
|
|
|
|
import { registerFeishuDocTools } from "./docx.js";
|
|
|
|
describe("feishu_doc image fetch hardening", () => {
|
|
const convertMock = vi.hoisted(() => vi.fn());
|
|
const blockListMock = vi.hoisted(() => vi.fn());
|
|
const blockChildrenCreateMock = vi.hoisted(() => vi.fn());
|
|
const driveUploadAllMock = vi.hoisted(() => vi.fn());
|
|
const blockPatchMock = vi.hoisted(() => vi.fn());
|
|
const scopeListMock = vi.hoisted(() => vi.fn());
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
|
|
createFeishuClientMock.mockReturnValue({
|
|
docx: {
|
|
document: {
|
|
convert: convertMock,
|
|
},
|
|
documentBlock: {
|
|
list: blockListMock,
|
|
patch: blockPatchMock,
|
|
},
|
|
documentBlockChildren: {
|
|
create: blockChildrenCreateMock,
|
|
},
|
|
},
|
|
drive: {
|
|
media: {
|
|
uploadAll: driveUploadAllMock,
|
|
},
|
|
},
|
|
application: {
|
|
scope: {
|
|
list: scopeListMock,
|
|
},
|
|
},
|
|
});
|
|
|
|
convertMock.mockResolvedValue({
|
|
code: 0,
|
|
data: {
|
|
blocks: [{ block_type: 27 }],
|
|
first_level_block_ids: [],
|
|
},
|
|
});
|
|
|
|
blockListMock.mockResolvedValue({
|
|
code: 0,
|
|
data: {
|
|
items: [],
|
|
},
|
|
});
|
|
|
|
blockChildrenCreateMock.mockResolvedValue({
|
|
code: 0,
|
|
data: {
|
|
children: [{ block_type: 27, block_id: "img_block_1" }],
|
|
},
|
|
});
|
|
|
|
driveUploadAllMock.mockResolvedValue({ file_token: "token_1" });
|
|
blockPatchMock.mockResolvedValue({ code: 0 });
|
|
scopeListMock.mockResolvedValue({ code: 0, data: { scopes: [] } });
|
|
});
|
|
|
|
it("skips image upload when markdown image URL is blocked", async () => {
|
|
const consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
fetchRemoteMediaMock.mockRejectedValueOnce(
|
|
new Error("Blocked: resolves to private/internal IP address"),
|
|
);
|
|
|
|
const registerTool = vi.fn();
|
|
registerFeishuDocTools({
|
|
config: {
|
|
channels: {
|
|
feishu: {
|
|
appId: "app_id",
|
|
appSecret: "app_secret",
|
|
},
|
|
},
|
|
} as any,
|
|
logger: { debug: vi.fn(), info: vi.fn() } as any,
|
|
registerTool,
|
|
} as any);
|
|
|
|
const feishuDocTool = registerTool.mock.calls
|
|
.map((call) => call[0])
|
|
.find((tool) => tool.name === "feishu_doc");
|
|
expect(feishuDocTool).toBeDefined();
|
|
|
|
const result = await feishuDocTool.execute("tool-call", {
|
|
action: "write",
|
|
doc_token: "doc_1",
|
|
content: "",
|
|
});
|
|
|
|
expect(fetchRemoteMediaMock).toHaveBeenCalled();
|
|
expect(driveUploadAllMock).not.toHaveBeenCalled();
|
|
expect(blockPatchMock).not.toHaveBeenCalled();
|
|
expect(result.details.images_processed).toBe(0);
|
|
expect(consoleErrorSpy).toHaveBeenCalled();
|
|
consoleErrorSpy.mockRestore();
|
|
});
|
|
});
|