forked from bai/curriculum-project-hub
09cadd0148
用 Vitest 组织测试,对齐 Courseware 半边的测试纪律(非散脚本): - test/unit/workspace.test.ts: 路径 confinement(读写回环/..逃逸/绝对路径逃逸/ 父目录创建/列举/不存在 error JSON)—— 11 tests - test/unit/prompt.test.ts: @bot 提取(单 mention/多 mention/纯@bot/无 mention/ 非 JSON/无 text 字段)—— 8 tests - test/unit/permission.test.ts: roleGrantsEdit 单调性(READ 不含 / EDIT 含 / MANAGE 含,ADR-0004 can_mono)—— 3 tests extractPrompt 导出供测试。修了 test helper 默认参数 bug(显式传 undefined 触发 默认值,绕过 mentions 检查)。 vitest run 22/22 通过;tsc rc=0。 Integration 层(trigger 全链路 + lock WellFormed + 真 cph)待本地 postgres 后再起。
76 lines
2.4 KiB
TypeScript
76 lines
2.4 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { extractPrompt } from "../../src/feishu/trigger.js";
|
|
import type { MessageReceiveEvent } from "../../src/feishu/client.js";
|
|
|
|
const bot = { key: "@_user_1", id: { open_id: "ou_bot" }, name: "Bot" };
|
|
|
|
function msg(text: string, mentions: typeof bot[] | undefined = [bot]): MessageReceiveEvent["message"] {
|
|
return {
|
|
message_id: "m",
|
|
chat_id: "c",
|
|
chat_type: "group",
|
|
message_type: "text",
|
|
content: JSON.stringify({ text }),
|
|
mentions,
|
|
};
|
|
}
|
|
|
|
describe("extractPrompt (@bot mention parsing)", () => {
|
|
it("extracts the prompt after @bot", () => {
|
|
expect(extractPrompt(msg("@_user_1 帮我写教案"))).toBe("帮我写教案");
|
|
});
|
|
|
|
it("strips multiple mentions", () => {
|
|
const other = { key: "@_user_2", id: { open_id: "ou_other" }, name: "Other" };
|
|
expect(extractPrompt(msg("@_user_1 @_user_2 检查例题2", [bot, other]))).toBe("检查例题2");
|
|
});
|
|
|
|
it("returns null when only @bot with no prompt", () => {
|
|
expect(extractPrompt(msg("@_user_1"))).toBeNull();
|
|
});
|
|
|
|
it("returns null when @bot followed by whitespace only", () => {
|
|
expect(extractPrompt(msg("@_user_1 "))).toBeNull();
|
|
});
|
|
it("returns null when no mentions", () => {
|
|
const m: MessageReceiveEvent["message"] = {
|
|
message_id: "m", chat_id: "c", chat_type: "group",
|
|
message_type: "text",
|
|
content: JSON.stringify({ text: "hello" }),
|
|
mentions: undefined,
|
|
};
|
|
expect(extractPrompt(m)).toBeNull();
|
|
});
|
|
|
|
it("returns null for non-text message_type (content still parseable)", () => {
|
|
const m = msg("{}", [bot]);
|
|
// message_type check is the caller's job; extractPrompt only parses content.
|
|
// But with empty text it returns null.
|
|
expect(extractPrompt({ ...m, content: JSON.stringify({ text: "" }) })).toBeNull();
|
|
});
|
|
|
|
it("returns null when content is not valid JSON", () => {
|
|
const m: MessageReceiveEvent["message"] = {
|
|
message_id: "m",
|
|
chat_id: "c",
|
|
chat_type: "group",
|
|
message_type: "text",
|
|
content: "not json",
|
|
mentions: [bot],
|
|
};
|
|
expect(extractPrompt(m)).toBeNull();
|
|
});
|
|
|
|
it("returns null when JSON has no text field", () => {
|
|
const m: MessageReceiveEvent["message"] = {
|
|
message_id: "m",
|
|
chat_id: "c",
|
|
chat_type: "group",
|
|
message_type: "text",
|
|
content: JSON.stringify({ foo: "bar" }),
|
|
mentions: [bot],
|
|
};
|
|
expect(extractPrompt(m)).toBeNull();
|
|
});
|
|
});
|