forked from EduCraft/curriculum-project-hub
fix(hub): 稳定 Feishu trigger 集成测试
This commit is contained in:
@@ -57,23 +57,41 @@ export const silentLogger: FastifyBaseLogger = {
|
||||
export interface MockFeishuRuntime extends FeishuRuntime {
|
||||
readonly sentTexts: string[];
|
||||
readonly sentCards: unknown[];
|
||||
readonly sentPatches: unknown[];
|
||||
readonly reactions: Array<{ readonly messageId: string; readonly emoji: string }>;
|
||||
}
|
||||
|
||||
export function mockFeishuRuntime(): MockFeishuRuntime {
|
||||
const sentTexts: string[] = [];
|
||||
const sentCards: unknown[] = [];
|
||||
const sentPatches: unknown[] = [];
|
||||
const reactions: Array<{ messageId: string; emoji: string }> = [];
|
||||
// Mock the client — sendText/sendCard are in client.ts, not on the runtime
|
||||
// object directly. We patch by providing a runtime whose client is a stub;
|
||||
// the actual send functions cast through shape, so a minimal stub works.
|
||||
const rt: MockFeishuRuntime = {
|
||||
client: {
|
||||
request: async (p: unknown) => {
|
||||
const payload = p as { url?: string; data?: { reaction_type?: { emoji_type?: string } } };
|
||||
const match = payload.url?.match(/\/messages\/([^/]+)\/reactions$/);
|
||||
if (match?.[1] !== undefined) {
|
||||
reactions.push({
|
||||
messageId: match[1],
|
||||
emoji: payload.data?.reaction_type?.emoji_type ?? "",
|
||||
});
|
||||
}
|
||||
return {};
|
||||
},
|
||||
im: {
|
||||
v1: {
|
||||
message: {
|
||||
create: async (p: unknown) => {
|
||||
const payload = p as { data?: { msg_type?: string; content?: string } };
|
||||
if (payload.data?.msg_type === "interactive") {
|
||||
sentCards.push(payload.data.content ? JSON.parse(payload.data.content) : null);
|
||||
const card = payload.data.content ? JSON.parse(payload.data.content) : null;
|
||||
sentCards.push(card);
|
||||
const text = textFromCard(card);
|
||||
if (text !== null) sentTexts.push(text);
|
||||
} else {
|
||||
try {
|
||||
const c = JSON.parse(payload.data?.content ?? "{}") as { text?: string };
|
||||
@@ -84,6 +102,14 @@ export function mockFeishuRuntime(): MockFeishuRuntime {
|
||||
}
|
||||
return { data: { message_id: "mock-msg-id" } };
|
||||
},
|
||||
patch: async (p: unknown) => {
|
||||
const payload = p as { data?: { content?: string } };
|
||||
const card = payload.data?.content ? JSON.parse(payload.data.content) : null;
|
||||
sentPatches.push(card);
|
||||
const text = textFromCard(card);
|
||||
if (text !== null) sentTexts.push(text);
|
||||
return {};
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -91,10 +117,27 @@ export function mockFeishuRuntime(): MockFeishuRuntime {
|
||||
logger: silentLogger,
|
||||
sentTexts,
|
||||
sentCards,
|
||||
sentPatches,
|
||||
reactions,
|
||||
};
|
||||
return rt;
|
||||
}
|
||||
|
||||
function textFromCard(card: unknown): string | null {
|
||||
if (typeof card !== "object" || card === null) return null;
|
||||
const elements = (card as { elements?: unknown }).elements;
|
||||
if (!Array.isArray(elements)) return null;
|
||||
const parts: string[] = [];
|
||||
for (const element of elements) {
|
||||
if (typeof element !== "object" || element === null) continue;
|
||||
const text = (element as { text?: unknown }).text;
|
||||
if (typeof text !== "object" || text === null) continue;
|
||||
const content = (text as { content?: unknown }).content;
|
||||
if (typeof content === "string") parts.push(content);
|
||||
}
|
||||
return parts.length === 0 ? null : parts.join("\n");
|
||||
}
|
||||
|
||||
export interface MockToolCall {
|
||||
readonly toolCallId: string;
|
||||
readonly toolName: string;
|
||||
|
||||
Reference in New Issue
Block a user