Verified: - pnpm build - pnpm check - pnpm test Co-authored-by: xzq-xu <53989315+xzq-xu@users.noreply.github.com> Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
117 lines
3.9 KiB
TypeScript
117 lines
3.9 KiB
TypeScript
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();
|
|
});
|
|
});
|