import { describe, expect, it } from "vitest"; import { currentOverride, isPinned, kindLabel, reasonLabel, withExcluded, withPinToggled, withRecentN, withRestored, type InjectionOverrideRequest, type InjectionResponse, } from "./injection"; const REF = { kind: "character", name: "林动" } as const; const emptyOverride = (): InjectionOverrideRequest => ({ pinned: [], excluded: [], recent_n: 5, }); describe("reasonLabel", () => { it("maps each known selection reason to a Chinese badge", () => { expect(reasonLabel("explicit_beat")).toBe("本章点名"); expect(reasonLabel("main_character")).toBe("主角常驻"); expect(reasonLabel("recent_digest")).toBe("近章出现"); expect(reasonLabel("foreshadow_window")).toBe("伏笔窗口"); expect(reasonLabel("author_pin")).toBe("作者置顶"); }); it("falls back to the raw code for an unknown reason", () => { expect(reasonLabel("future_reason")).toBe("future_reason"); }); }); describe("kindLabel", () => { it("maps entity kinds to Chinese", () => { expect(kindLabel("character")).toBe("角色"); expect(kindLabel("world_entity")).toBe("设定"); }); it("falls back to the raw kind when unknown", () => { expect(kindLabel("mystery")).toBe("mystery"); }); }); describe("currentOverride", () => { it("extracts pinned/excluded/recent_n from a response", () => { const data = { project_id: "p", chapter_no: 1, selected: [], recent_n: 3, pinned: [REF], excluded: [{ kind: "world_entity", name: "玄铁" }], } as unknown as InjectionResponse; expect(currentOverride(data)).toEqual({ pinned: [REF], excluded: [{ kind: "world_entity", name: "玄铁" }], recent_n: 3, }); }); }); describe("withPinToggled", () => { it("pins an unpinned ref and removes it from excluded", () => { const next = withPinToggled(withExcluded(emptyOverride(), REF), REF); expect(isPinned(next, REF)).toBe(true); expect(next.excluded).toEqual([]); }); it("unpins an already-pinned ref", () => { const pinned = withPinToggled(emptyOverride(), REF); const next = withPinToggled(pinned, REF); expect(isPinned(next, REF)).toBe(false); }); }); describe("withExcluded / withRestored", () => { it("excludes a ref, removing it from pinned, then restores it", () => { const pinnedThenExcluded = withExcluded(withPinToggled(emptyOverride(), REF), REF); expect(isPinned(pinnedThenExcluded, REF)).toBe(false); expect(pinnedThenExcluded.excluded).toEqual([REF]); const restored = withRestored(pinnedThenExcluded, REF); expect(restored.excluded).toEqual([]); }); it("is idempotent when excluding twice", () => { const once = withExcluded(emptyOverride(), REF); const twice = withExcluded(once, REF); expect(twice.excluded).toEqual([REF]); }); }); describe("withRecentN", () => { it("clamps below the minimum and above the maximum", () => { expect(withRecentN(emptyOverride(), 0).recent_n).toBe(1); expect(withRecentN(emptyOverride(), 999).recent_n).toBe(20); expect(withRecentN(emptyOverride(), 7).recent_n).toBe(7); }); });