import { describe, expect, it, vi } from "vitest"; import { mkdtemp, rm, writeFile } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { sendFile, sendTextMessage, type FeishuRuntime } from "../../src/feishu/client.js"; describe("Feishu client helpers", () => { it("accepts top-level file_key from the Lark SDK file upload response", async () => { const dir = await mkdtemp(join(tmpdir(), "hub-feishu-client-")); try { const file = join(dir, "student.pdf"); await writeFile(file, "pdf bytes"); const fileCreate = vi.fn(async () => ({ file_key: "file-key-1" })); const messageCreate = vi.fn(async () => ({ data: { message_id: "message-1" } })); const rt = mockRuntime({ fileCreate, messageCreate }); await expect(sendFile(rt, "chat-1", file, "student.pdf")).resolves.toBe("message-1"); expect(messageCreate).toHaveBeenCalledWith({ params: { receive_id_type: "chat_id" }, data: { receive_id: "chat-1", msg_type: "file", content: JSON.stringify({ file_key: "file-key-1" }) }, }); } finally { await rm(dir, { recursive: true, force: true }); } }); it("accepts top-level message_id from message create responses", async () => { const rt = mockRuntime({ fileCreate: vi.fn(), messageCreate: vi.fn(async () => ({ message_id: "message-1" })), }); await expect(sendTextMessage(rt, "chat-1", "hello")).resolves.toBe("message-1"); }); }); function mockRuntime(options: { readonly fileCreate: (payload: unknown) => Promise; readonly messageCreate: (payload: unknown) => Promise; }): FeishuRuntime { return { client: { im: { v1: { file: { create: options.fileCreate }, message: { create: options.messageCreate }, }, }, } as unknown as FeishuRuntime["client"], logger: { info() {}, warn() {}, error() {}, debug() {}, fatal() {}, child() { return this; }, level: "silent", } as unknown as FeishuRuntime["logger"], }; }