Files
2026-06-10 06:53:13 -07:00

50 lines
2.0 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { emptyArtifact, type Provenance } from "../src/model";
import { addThread, appendMessage, setStatus } from "../src/threadModel";
const BEN: Provenance = { kind: "human", id: "ben" };
const fp = { text: "anchored", before: "a", after: "b", lineHint: 3 };
describe("addThread", () => {
it("adds an anchor + an open thread with the first message and returns their ids", () => {
const a = emptyArtifact("docs/x.md");
const { threadId, anchorId } = addThread(a, fp, { author: BEN, body: "first" });
expect(Object.keys(a.anchors)).toContain(anchorId);
expect(a.anchors[anchorId].fingerprint).toEqual(fp);
const t = a.threads.find((x) => x.id === threadId)!;
expect(t.anchorId).toBe(anchorId);
expect(t.status).toBe("open");
expect(t.messages).toHaveLength(1);
expect(t.messages[0].body).toBe("first");
expect(t.messages[0].author).toEqual(BEN);
expect(t.messages[0].id).toMatch(/^m_/);
expect(t.messages[0].createdAt).toMatch(/^\d{4}-\d{2}-\d{2}T/);
});
});
describe("appendMessage", () => {
it("appends a message to the named thread", () => {
const a = emptyArtifact("docs/x.md");
const { threadId } = addThread(a, fp, { author: BEN, body: "first" });
appendMessage(a, threadId, { author: BEN, body: "reply" });
const t = a.threads.find((x) => x.id === threadId)!;
expect(t.messages.map((m) => m.body)).toEqual(["first", "reply"]);
});
it("throws for an unknown thread id", () => {
const a = emptyArtifact("docs/x.md");
expect(() => appendMessage(a, "nope", { author: BEN, body: "x" })).toThrow(/nope/);
});
});
describe("setStatus", () => {
it("flips a thread between open and resolved", () => {
const a = emptyArtifact("docs/x.md");
const { threadId } = addThread(a, fp, { author: BEN, body: "first" });
setStatus(a, threadId, "resolved");
expect(a.threads[0].status).toBe("resolved");
setStatus(a, threadId, "open");
expect(a.threads[0].status).toBe("open");
});
});