import { describe, expect, it } from "vitest"; import type { ReviewConflictView, ReviewHistoryItem } from "@/lib/api/types"; import { latestReview, normalizeConflicts, normalizeForeshadowSug, normalizePace, } from "./history"; const item = ( conflicts: ReviewConflictView[], ): ReviewHistoryItem => ({ id: "00000000-0000-0000-0000-000000000001", project_id: "00000000-0000-0000-0000-000000000002", chapter_no: 128, conflicts, }); describe("normalizeConflicts", () => { it("tightens loose dicts into ReviewConflict, preserving order", () => { const out = normalizeConflicts( item([ { type: "设定违例", where: "第4段", refs: ["第30章"], suggestion: "统一血脉", }, { type: "时间线倒错", where: "第8段", refs: [], suggestion: "调整" }, ]), ); expect(out).toEqual([ { type: "设定违例", where: "第4段", refs: ["第30章"], suggestion: "统一血脉", original: null, replacement: null, }, { type: "时间线倒错", where: "第8段", refs: [], suggestion: "调整", original: null, replacement: null, }, ]); }); it("falls back type to 未分类 and tolerates missing refs", () => { const out = normalizeConflicts( item([{ type: "", where: "", suggestion: "" }]), ); expect(out).toEqual([ { type: "未分类", where: "", refs: [], suggestion: "", original: null, replacement: null, }, ]); }); it("returns [] for undefined item or missing conflicts", () => { expect(normalizeConflicts(undefined)).toEqual([]); }); }); describe("normalizeForeshadowSug", () => { it("tightens flat list with kind, defaulting kind to planted", () => { const out = normalizeForeshadowSug({ ...item([]), foreshadow_sug: [ { kind: "resolved", code: "F-012", title: "神秘玉佩", where: "第4段" }, { title: "残破地图" }, ], }); expect(out).toEqual([ { kind: "resolved", code: "F-012", title: "神秘玉佩", where: "第4段", note: null, }, { kind: "planted", code: null, title: "残破地图", where: null, note: null }, ]); }); it("returns [] when missing", () => { expect(normalizeForeshadowSug(item([]))).toEqual([]); expect(normalizeForeshadowSug(undefined)).toEqual([]); }); }); describe("normalizePace", () => { it("tightens dict into PaceReport, filtering bad water/beats", () => { const out = normalizePace({ ...item([]), pace: { water: [{ where: "第3段", reason: "注水" }, "junk"], hook: true, beat_map: [1, 3, "x", 5], }, }); expect(out).toEqual({ water: [{ where: "第3段", reason: "注水" }], hook: true, beat_map: [1, 3, 5], }); }); it("returns null when pace is missing or not a dict", () => { expect(normalizePace(item([]))).toBeNull(); expect(normalizePace(undefined)).toBeNull(); }); }); describe("latestReview", () => { it("returns first item (history is newest-first)", () => { const a = item([]); const b = item([]); expect(latestReview([a, b])).toBe(a); expect(latestReview([])).toBeUndefined(); expect(latestReview(undefined)).toBeUndefined(); }); });