Team Ai
Apppublic

HuggingFaceBio/carbon-tokenization

sourceHugging Faceupdated 4mo agoView on Hugging Face
11likes
comments-store.test.ts150 linesDownload Raw Back to tests
1/**2 * Comment Store Tests3 *4 * Covers the Yjs-backed comment store:5 * - add / addReply / remove / get / getAll6 * - resolve / unresolve7 * - observe8 * - collaboration (concurrent adds merge)9 */10import { describe, it, expect } from "vitest";11import * as Y from "yjs";12import { createCommentStore, type CommentData, type ReplyData } from "../src/editor/comments";13 14function makeStore() {15  const ydoc = new Y.Doc();16  return { ydoc, store: createCommentStore(ydoc) };17}18 19function baseComment(overrides: Partial<Omit<CommentData, "replies">> = {}) {20  return {21    id: "c1",22    author: "alice",23    authorColor: "#f00",24    text: "hello",25    createdAt: 1_000,26    resolved: false,27    ...overrides,28  } as Omit<CommentData, "replies">;29}30 31describe("comment-store — CRUD", () => {32  it("add() stores a comment with an empty replies array", () => {33    const { store } = makeStore();34    store.add(baseComment());35    const got = store.get("c1");36    expect(got).toBeDefined();37    expect(got!.text).toBe("hello");38    expect(got!.replies).toEqual([]);39  });40 41  it("getAll() returns comments sorted by createdAt", () => {42    const { store } = makeStore();43    store.add(baseComment({ id: "late", createdAt: 3000 }));44    store.add(baseComment({ id: "early", createdAt: 1000 }));45    store.add(baseComment({ id: "mid", createdAt: 2000 }));46    const all = store.getAll();47    expect(all.map((c) => c.id)).toEqual(["early", "mid", "late"]);48  });49 50  it("remove() deletes a comment", () => {51    const { store } = makeStore();52    store.add(baseComment());53    store.remove("c1");54    expect(store.get("c1")).toBeUndefined();55  });56 57  it("get() on a missing id returns undefined", () => {58    const { store } = makeStore();59    expect(store.get("missing")).toBeUndefined();60  });61});62 63describe("comment-store — replies", () => {64  const reply: ReplyData = {65    id: "r1",66    author: "bob",67    authorColor: "#00f",68    text: "ack",69    createdAt: 1500,70  };71 72  it("addReply() appends to the replies array", () => {73    const { store } = makeStore();74    store.add(baseComment());75    store.addReply("c1", reply);76    store.addReply("c1", { ...reply, id: "r2", text: "ack2" });77    const got = store.get("c1")!;78    expect(got.replies.map((r) => r.id)).toEqual(["r1", "r2"]);79    expect(got.replies[1].text).toBe("ack2");80  });81 82  it("addReply() on a missing comment is a no-op", () => {83    const { store } = makeStore();84    store.addReply("missing", reply);85    expect(store.get("missing")).toBeUndefined();86  });87});88 89describe("comment-store — resolve/unresolve", () => {90  it("resolve() marks the comment resolved and records the resolver", () => {91    const { store } = makeStore();92    store.add(baseComment());93    store.resolve("c1", "carol");94    const got = store.get("c1")!;95    expect(got.resolved).toBe(true);96    expect(got.resolvedBy).toBe("carol");97    expect(typeof got.resolvedAt).toBe("number");98  });99 100  it("unresolve() clears the resolved metadata", () => {101    const { store } = makeStore();102    store.add(baseComment());103    store.resolve("c1", "carol");104    store.unresolve("c1");105    const got = store.get("c1")!;106    expect(got.resolved).toBe(false);107    expect(got.resolvedBy).toBeUndefined();108    expect(got.resolvedAt).toBeUndefined();109  });110 111  it("resolve() on a missing comment is a no-op", () => {112    const { store } = makeStore();113    store.resolve("missing", "carol");114    expect(store.get("missing")).toBeUndefined();115  });116});117 118describe("comment-store — observe", () => {119  it("fires on add and remove, stops after unsubscribe", () => {120    const { store } = makeStore();121    let count = 0;122    const unsub = store.observe(() => { count++; });123    store.add(baseComment({ id: "a" }));124    store.add(baseComment({ id: "b" }));125    store.remove("a");126    expect(count).toBe(3);127    unsub();128    store.remove("b");129    expect(count).toBe(3);130  });131});132 133describe("comment-store — collaboration", () => {134  it("concurrent adds in different docs both survive after sync", () => {135    const docA = new Y.Doc();136    const docB = new Y.Doc();137    const a = createCommentStore(docA);138    const b = createCommentStore(docB);139 140    a.add(baseComment({ id: "from-a" }));141    b.add(baseComment({ id: "from-b", author: "bob", authorColor: "#0f0" }));142 143    Y.applyUpdate(docA, Y.encodeStateAsUpdate(docB));144    Y.applyUpdate(docB, Y.encodeStateAsUpdate(docA));145 146    expect(a.getAll().map((c) => c.id).sort()).toEqual(["from-a", "from-b"]);147    expect(b.getAll().map((c) => c.id).sort()).toEqual(["from-a", "from-b"]);148  });149});150