HuggingFaceBio/carbon-tokenization
11
1/**2 * Embed Store Tests3 *4 * Covers the Yjs-backed embed store:5 * - get/set/has/remove6 * - rename (atomic via transact)7 * - patch (search-replace)8 * - keys / getAll9 * - observe / observeKey10 */11import { describe, it, expect } from "vitest";12import * as Y from "yjs";13import { createEmbedStore } from "../src/editor/embeds/embed-store";14 15function makeStore() {16 const ydoc = new Y.Doc();17 return { ydoc, store: createEmbedStore(ydoc) };18}19 20describe("embed-store — basic CRUD", () => {21 it("get returns empty string when key missing", () => {22 const { store } = makeStore();23 expect(store.get("nope.html")).toBe("");24 expect(store.has("nope.html")).toBe(false);25 });26 27 it("set + get round-trips html content", () => {28 const { store } = makeStore();29 store.set("chart.html", "<div>hi</div>");30 expect(store.get("chart.html")).toBe("<div>hi</div>");31 expect(store.has("chart.html")).toBe(true);32 });33 34 it("remove deletes the entry", () => {35 const { store } = makeStore();36 store.set("chart.html", "<div/>");37 store.remove("chart.html");38 expect(store.has("chart.html")).toBe(false);39 expect(store.get("chart.html")).toBe("");40 });41 42 it("keys returns all inserted keys", () => {43 const { store } = makeStore();44 store.set("a.html", "A");45 store.set("b.html", "B");46 expect(store.keys().sort()).toEqual(["a.html", "b.html"]);47 });48 49 it("getAll returns a plain object snapshot", () => {50 const { store } = makeStore();51 store.set("a.html", "A");52 store.set("b.html", "B");53 expect(store.getAll()).toEqual({ "a.html": "A", "b.html": "B" });54 });55});56 57describe("embed-store — rename", () => {58 it("moves content to the new key and deletes the old one", () => {59 const { store } = makeStore();60 store.set("old.html", "<svg/>");61 store.rename("old.html", "new.html");62 expect(store.has("old.html")).toBe(false);63 expect(store.get("new.html")).toBe("<svg/>");64 });65 66 it("is a no-op when the source key does not exist", () => {67 const { store } = makeStore();68 store.rename("missing.html", "target.html");69 expect(store.has("target.html")).toBe(false);70 });71});72 73describe("embed-store — patch", () => {74 it("returns false and does nothing when search text is missing", () => {75 const { store } = makeStore();76 store.set("chart.html", "<div>hello</div>");77 expect(store.patch("chart.html", "notfound", "bye")).toBe(false);78 expect(store.get("chart.html")).toBe("<div>hello</div>");79 });80 81 it("replaces first occurrence when search text is present", () => {82 const { store } = makeStore();83 store.set("chart.html", "<div>hello hello</div>");84 const ok = store.patch("chart.html", "hello", "bye");85 expect(ok).toBe(true);86 expect(store.get("chart.html")).toBe("<div>bye hello</div>");87 });88 89 it("returns false for missing keys", () => {90 const { store } = makeStore();91 expect(store.patch("missing.html", "a", "b")).toBe(false);92 });93});94 95describe("embed-store — observe", () => {96 it("observe() fires on any change", () => {97 const { store } = makeStore();98 let count = 0;99 const unsub = store.observe(() => { count++; });100 store.set("a.html", "A");101 store.set("b.html", "B");102 expect(count).toBe(2);103 unsub();104 store.set("c.html", "C");105 expect(count).toBe(2);106 });107 108 it("observeKey() only fires for the matching key", () => {109 const { store } = makeStore();110 const aCalls: string[] = [];111 const unsub = store.observeKey("a.html", (html) => { aCalls.push(html); });112 store.set("a.html", "A1");113 store.set("b.html", "B1");114 store.set("a.html", "A2");115 expect(aCalls).toEqual(["A1", "A2"]);116 unsub();117 });118});119 120describe("embed-store — collaboration", () => {121 it("concurrent sets on different keys merge correctly", () => {122 const docA = new Y.Doc();123 const docB = new Y.Doc();124 const storeA = createEmbedStore(docA);125 const storeB = createEmbedStore(docB);126 127 storeA.set("a.html", "<A/>");128 storeB.set("b.html", "<B/>");129 130 Y.applyUpdate(docA, Y.encodeStateAsUpdate(docB));131 Y.applyUpdate(docB, Y.encodeStateAsUpdate(docA));132 133 expect(storeA.getAll()).toEqual({ "a.html": "<A/>", "b.html": "<B/>" });134 expect(storeB.getAll()).toEqual({ "a.html": "<A/>", "b.html": "<B/>" });135 });136});137 