Files
writing-agent/tests/directives.test.ts
T
chenmoranzhiandCursor 8a22cdc37c 实现输入框指令解析、高亮与补全。
让玩家与人设等占位在发送前可预览并正确展开。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-14 01:14:20 +08:00

99 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it, vi } from "vitest";
import {
expandAtDirectives,
expandIdentityDirectives,
listDirectiveCatalog,
} from "../src/directives/expand.js";
describe("expandAtDirectives", () => {
it("replaces @玩家 and @user with persona name", () => {
const r = expandAtDirectives("你好,@玩家;再见 @user。", {
persona: { name: "林晚" },
});
expect(r.text).toBe("你好,林晚;再见 林晚。");
expect(r.hits.map((h) => h.kind)).toEqual([
"persona_name",
"persona_name",
]);
});
it("falls back to 玩家 when no persona", () => {
const r = expandAtDirectives("我是@玩家", {});
expect(r.text).toBe("我是玩家");
});
it("replaces @人设 with description", () => {
const r = expandAtDirectives("人设:@人设", {
persona: { name: "林晚", description: "冷静的调查员" },
});
expect(r.text).toBe("人设:冷静的调查员");
});
it("compat {{user}}", () => {
const r = expandIdentityDirectives("对{{user}}说", {
persona: { name: "阿泽" },
});
expect(r.text).toBe("对阿泽说");
});
it("leaves unknown @token alone", () => {
const r = expandAtDirectives("写给@某人 的信", {
persona: { name: "林晚" },
});
expect(r.text).toBe("写给@某人 的信");
expect(r.changed).toBe(false);
});
it("does not treat @玩家X as @玩家", () => {
const r = expandAtDirectives("@玩家X来了", {
persona: { name: "林晚" },
});
expect(r.text).toBe("@玩家X来了");
});
it("expands @玩家 when followed by Chinese", () => {
const r = expandAtDirectives("且对@玩家没有因为", {
persona: { name: "林晚" },
});
expect(r.text).toBe("且对林晚没有因为");
});
it("rolls @rd100 with target", () => {
vi.spyOn(Math, "random").mockReturnValue(0.18); // → 19 on 1..100
const r = expandAtDirectives("检定 @rd100 30", {
persona: { name: "林晚" },
});
expect(r.text).toBe("检定 投掷结果为 19,目标 30(成功)");
vi.restoreAllMocks();
});
it("rolls @r3d10 without target", () => {
const seq = [0.3, 0.6, 0.1];
let i = 0;
vi.spyOn(Math, "random").mockImplementation(() => seq[i++] ?? 0);
const r = expandAtDirectives("伤害 @r3d10", {});
expect(r.text).toMatch(/^伤害 投掷结果为 \d\+\d\+\d = \d+(3d10)$/);
vi.restoreAllMocks();
});
it("identity expand skips dice", () => {
const r = expandIdentityDirectives("先 @rd100 50 再说", {
persona: { name: "林晚" },
});
expect(r.text).toBe("先 @rd100 50 再说");
});
it("lists catalog", () => {
expect(listDirectiveCatalog().some((x) => x.insert === "@玩家")).toBe(
true,
);
});
it("keeps @玩家 when the persona name is @玩家", () => {
const r = expandIdentityDirectives("清晨,@玩家推开门。对{{user}}点头。", {
persona: { name: "@玩家", description: "占位" },
});
expect(r.text).toBe("清晨,@玩家推开门。对@玩家点头。");
});
});