// Rôle : vérifie l'atomicité des snapshots avec une vraie transaction IndexedDB. import { test, expect } from "@playwright/test"; import { resetSokkoStorage } from "./helpers/storage.js"; test("a synchronous snapshot error aborts all its IndexedDB writes", async ({ page }) => { await resetSokkoStorage(page); const result = await page.evaluate(async () => { const db = await import("/src/utils/indexedDbStorage.js"); await db.setToolboxSnapshot([{ id: "saved", modules: [] }], { game: "saved" }, { "saved:note": { text: "Keep" } }); let errorName = ""; try { await db.setToolboxSnapshot([{ id: "broken" }], {}, { "broken:note": { invalid: () => {} } }); } catch (error) { errorName = error.name; } return { errorName, toolboxes: await db.getToolboxes(), links: await db.getLinks(), modules: await db.getAllModuleData() }; }); expect(result).toEqual({ errorName: "DataCloneError", toolboxes: [{ id: "saved", modules: [] }], links: { game: "saved" }, modules: [{ key: "saved:note", data: { text: "Keep" } }] }); }); test("partial snapshots preserve deferred values and roll back deletes on failure", async ({ page }) => { await resetSokkoStorage(page); const result = await page.evaluate(async () => { const db = await import("/src/utils/indexedDbStorage.js"); await db.setToolboxSnapshot([{ id: "saved", modules: [] }], {}, { media: { image: "Keep" }, removed: { text: "Delete" } }); let failed = false; try { await db.setToolboxSnapshot([{ id: "broken" }], {}, { broken: { invalid: () => {} } }, ["media"]); } catch { failed = true; } const afterFailure = await db.getAllModuleData(); await db.setToolboxSnapshot([{ id: "saved", modules: [] }], {}, { note: { text: "New" } }, ["media"]); return { failed, afterFailure, afterSuccess: await db.getAllModuleData() }; }); expect(result).toEqual({ failed: true, afterFailure: [{ key: "media", data: { image: "Keep" } }, { key: "removed", data: { text: "Delete" } }], afterSuccess: [{ key: "media", data: { image: "Keep" } }, { key: "note", data: { text: "New" } }] }); });