UNPKG

@gguf/claw

Version:

Multi-channel AI gateway with extensible messaging integrations

117 lines (101 loc) 3.94 kB
import { beforeEach, describe, expect, it, vi } from "vitest"; const resolveFeishuAccountMock = vi.hoisted(() => vi.fn()); const getFeishuRuntimeMock = vi.hoisted(() => vi.fn()); const sendMessageFeishuMock = vi.hoisted(() => vi.fn()); const sendMarkdownCardFeishuMock = vi.hoisted(() => vi.fn()); const createFeishuClientMock = vi.hoisted(() => vi.fn()); const resolveReceiveIdTypeMock = vi.hoisted(() => vi.fn()); const createReplyDispatcherWithTypingMock = vi.hoisted(() => vi.fn()); const streamingInstances = vi.hoisted(() => [] as any[]); vi.mock("./accounts.js", () => ({ resolveFeishuAccount: resolveFeishuAccountMock })); vi.mock("./runtime.js", () => ({ getFeishuRuntime: getFeishuRuntimeMock })); vi.mock("./send.js", () => ({ sendMessageFeishu: sendMessageFeishuMock, sendMarkdownCardFeishu: sendMarkdownCardFeishuMock, })); vi.mock("./client.js", () => ({ createFeishuClient: createFeishuClientMock })); vi.mock("./targets.js", () => ({ resolveReceiveIdType: resolveReceiveIdTypeMock })); vi.mock("./streaming-card.js", () => ({ FeishuStreamingSession: class { active = false; start = vi.fn(async () => { this.active = true; }); update = vi.fn(async () => {}); close = vi.fn(async () => { this.active = false; }); isActive = vi.fn(() => this.active); constructor() { streamingInstances.push(this); } }, })); import { createFeishuReplyDispatcher } from "./reply-dispatcher.js"; describe("createFeishuReplyDispatcher streaming behavior", () => { beforeEach(() => { vi.clearAllMocks(); streamingInstances.length = 0; resolveFeishuAccountMock.mockReturnValue({ accountId: "main", appId: "app_id", appSecret: "app_secret", domain: "feishu", config: { renderMode: "auto", streaming: true, }, }); resolveReceiveIdTypeMock.mockReturnValue("chat_id"); createFeishuClientMock.mockReturnValue({}); createReplyDispatcherWithTypingMock.mockImplementation((opts) => ({ dispatcher: {}, replyOptions: {}, markDispatchIdle: vi.fn(), _opts: opts, })); getFeishuRuntimeMock.mockReturnValue({ channel: { text: { resolveTextChunkLimit: vi.fn(() => 4000), resolveChunkMode: vi.fn(() => "line"), resolveMarkdownTableMode: vi.fn(() => "preserve"), convertMarkdownTables: vi.fn((text) => text), chunkTextWithMode: vi.fn((text) => [text]), }, reply: { createReplyDispatcherWithTyping: createReplyDispatcherWithTypingMock, resolveHumanDelayConfig: vi.fn(() => undefined), }, }, }); }); it("keeps auto mode plain text on non-streaming send path", async () => { createFeishuReplyDispatcher({ cfg: {} as never, agentId: "agent", runtime: {} as never, chatId: "oc_chat", }); const options = createReplyDispatcherWithTypingMock.mock.calls[0]?.[0]; await options.deliver({ text: "plain text" }, { kind: "final" }); expect(streamingInstances).toHaveLength(0); expect(sendMessageFeishuMock).toHaveBeenCalledTimes(1); expect(sendMarkdownCardFeishuMock).not.toHaveBeenCalled(); }); it("uses streaming session for auto mode markdown payloads", async () => { createFeishuReplyDispatcher({ cfg: {} as never, agentId: "agent", runtime: { log: vi.fn(), error: vi.fn() } as never, chatId: "oc_chat", }); const options = createReplyDispatcherWithTypingMock.mock.calls[0]?.[0]; await options.deliver({ text: "```ts\nconst x = 1\n```" }, { kind: "final" }); expect(streamingInstances).toHaveLength(1); expect(streamingInstances[0].start).toHaveBeenCalledTimes(1); expect(streamingInstances[0].close).toHaveBeenCalledTimes(1); expect(sendMessageFeishuMock).not.toHaveBeenCalled(); expect(sendMarkdownCardFeishuMock).not.toHaveBeenCalled(); }); });