Spaces:
Runtime error
Runtime error
| /** | |
| * Embed Store Tests | |
| * | |
| * Covers the Yjs-backed embed store: | |
| * - get/set/has/remove | |
| * - rename (atomic via transact) | |
| * - patch (search-replace) | |
| * - keys / getAll | |
| * - observe / observeKey | |
| */ | |
| import { describe, it, expect } from "vitest"; | |
| import * as Y from "yjs"; | |
| import { createEmbedStore } from "../src/editor/embeds/embed-store"; | |
| function makeStore() { | |
| const ydoc = new Y.Doc(); | |
| return { ydoc, store: createEmbedStore(ydoc) }; | |
| } | |
| describe("embed-store — basic CRUD", () => { | |
| it("get returns empty string when key missing", () => { | |
| const { store } = makeStore(); | |
| expect(store.get("nope.html")).toBe(""); | |
| expect(store.has("nope.html")).toBe(false); | |
| }); | |
| it("set + get round-trips html content", () => { | |
| const { store } = makeStore(); | |
| store.set("chart.html", "<div>hi</div>"); | |
| expect(store.get("chart.html")).toBe("<div>hi</div>"); | |
| expect(store.has("chart.html")).toBe(true); | |
| }); | |
| it("remove deletes the entry", () => { | |
| const { store } = makeStore(); | |
| store.set("chart.html", "<div/>"); | |
| store.remove("chart.html"); | |
| expect(store.has("chart.html")).toBe(false); | |
| expect(store.get("chart.html")).toBe(""); | |
| }); | |
| it("keys returns all inserted keys", () => { | |
| const { store } = makeStore(); | |
| store.set("a.html", "A"); | |
| store.set("b.html", "B"); | |
| expect(store.keys().sort()).toEqual(["a.html", "b.html"]); | |
| }); | |
| it("getAll returns a plain object snapshot", () => { | |
| const { store } = makeStore(); | |
| store.set("a.html", "A"); | |
| store.set("b.html", "B"); | |
| expect(store.getAll()).toEqual({ "a.html": "A", "b.html": "B" }); | |
| }); | |
| }); | |
| describe("embed-store — rename", () => { | |
| it("moves content to the new key and deletes the old one", () => { | |
| const { store } = makeStore(); | |
| store.set("old.html", "<svg/>"); | |
| store.rename("old.html", "new.html"); | |
| expect(store.has("old.html")).toBe(false); | |
| expect(store.get("new.html")).toBe("<svg/>"); | |
| }); | |
| it("is a no-op when the source key does not exist", () => { | |
| const { store } = makeStore(); | |
| store.rename("missing.html", "target.html"); | |
| expect(store.has("target.html")).toBe(false); | |
| }); | |
| }); | |
| describe("embed-store — patch", () => { | |
| it("returns false and does nothing when search text is missing", () => { | |
| const { store } = makeStore(); | |
| store.set("chart.html", "<div>hello</div>"); | |
| expect(store.patch("chart.html", "notfound", "bye")).toBe(false); | |
| expect(store.get("chart.html")).toBe("<div>hello</div>"); | |
| }); | |
| it("replaces first occurrence when search text is present", () => { | |
| const { store } = makeStore(); | |
| store.set("chart.html", "<div>hello hello</div>"); | |
| const ok = store.patch("chart.html", "hello", "bye"); | |
| expect(ok).toBe(true); | |
| expect(store.get("chart.html")).toBe("<div>bye hello</div>"); | |
| }); | |
| it("returns false for missing keys", () => { | |
| const { store } = makeStore(); | |
| expect(store.patch("missing.html", "a", "b")).toBe(false); | |
| }); | |
| }); | |
| describe("embed-store — observe", () => { | |
| it("observe() fires on any change", () => { | |
| const { store } = makeStore(); | |
| let count = 0; | |
| const unsub = store.observe(() => { count++; }); | |
| store.set("a.html", "A"); | |
| store.set("b.html", "B"); | |
| expect(count).toBe(2); | |
| unsub(); | |
| store.set("c.html", "C"); | |
| expect(count).toBe(2); | |
| }); | |
| it("observeKey() only fires for the matching key", () => { | |
| const { store } = makeStore(); | |
| const aCalls: string[] = []; | |
| const unsub = store.observeKey("a.html", (html) => { aCalls.push(html); }); | |
| store.set("a.html", "A1"); | |
| store.set("b.html", "B1"); | |
| store.set("a.html", "A2"); | |
| expect(aCalls).toEqual(["A1", "A2"]); | |
| unsub(); | |
| }); | |
| }); | |
| describe("embed-store — collaboration", () => { | |
| it("concurrent sets on different keys merge correctly", () => { | |
| const docA = new Y.Doc(); | |
| const docB = new Y.Doc(); | |
| const storeA = createEmbedStore(docA); | |
| const storeB = createEmbedStore(docB); | |
| storeA.set("a.html", "<A/>"); | |
| storeB.set("b.html", "<B/>"); | |
| Y.applyUpdate(docA, Y.encodeStateAsUpdate(docB)); | |
| Y.applyUpdate(docB, Y.encodeStateAsUpdate(docA)); | |
| expect(storeA.getAll()).toEqual({ "a.html": "<A/>", "b.html": "<B/>" }); | |
| expect(storeB.getAll()).toEqual({ "a.html": "<A/>", "b.html": "<B/>" }); | |
| }); | |
| }); | |