// Rôle : teste les rollbacks optimistes par clé des données de modules IndexedDB. import { test } from "node:test"; import assert from "node:assert/strict"; import { applyModuleDataValue, commitModuleDataCheckpoints, createModuleDataCheckpoint, createModuleDataCheckpoints, removeModuleDataKeys, rollbackModuleDataCheckpoints } from "../website/src/features/toolboxes/storage/optimisticModuleData.js"; test("module data rollback restores a failed simple write", () => { const initialData = { "tbx:mod-a": { text: "before" } }; const initialVersions = {}; const checkpoint = createModuleDataCheckpoint(initialData, initialVersions, "tbx:mod-a"); const versions = commitModuleDataCheckpoints(initialVersions, [checkpoint]); const optimisticData = applyModuleDataValue(initialData, "tbx:mod-a", { text: "after" }); assert.deepEqual(rollbackModuleDataCheckpoints(optimisticData, versions, [checkpoint]), initialData); }); test("module data rollback ignores a stale failure for the same module", () => { const initialData = { "tbx:mod-a": { text: "before" } }; const firstCheckpoint = createModuleDataCheckpoint(initialData, {}, "tbx:mod-a"); const firstVersions = commitModuleDataCheckpoints({}, [firstCheckpoint]); const firstOptimisticData = applyModuleDataValue(initialData, "tbx:mod-a", { text: "after" }); const secondCheckpoint = createModuleDataCheckpoint(firstOptimisticData, firstVersions, "tbx:mod-a"); const secondVersions = commitModuleDataCheckpoints(firstVersions, [secondCheckpoint]); const secondOptimisticData = applyModuleDataValue(firstOptimisticData, "tbx:mod-a", { text: "latest" }); assert.strictEqual(rollbackModuleDataCheckpoints(secondOptimisticData, secondVersions, [firstCheckpoint]), secondOptimisticData); }); test("module data rollback restores one module even when another module changed later", () => { const initialData = { "tbx:mod-a": { text: "before-a" }, "tbx:mod-b": { text: "before-b" } }; const firstCheckpoint = createModuleDataCheckpoint(initialData, {}, "tbx:mod-a"); const firstVersions = commitModuleDataCheckpoints({}, [firstCheckpoint]); const firstOptimisticData = applyModuleDataValue(initialData, "tbx:mod-a", { text: "after-a" }); const secondCheckpoint = createModuleDataCheckpoint(firstOptimisticData, firstVersions, "tbx:mod-b"); const secondVersions = commitModuleDataCheckpoints(firstVersions, [secondCheckpoint]); const secondOptimisticData = applyModuleDataValue(firstOptimisticData, "tbx:mod-b", { text: "after-b" }); assert.deepEqual(rollbackModuleDataCheckpoints(secondOptimisticData, secondVersions, [firstCheckpoint]), { "tbx:mod-a": { text: "before-a" }, "tbx:mod-b": { text: "after-b" } }); }); test("module data rollback for batch removal restores only untouched keys", () => { const initialData = { "tbx:mod-a": { text: "before-a" }, "tbx:mod-b": { text: "before-b" }, "tbx:mod-c": { text: "before-c" } }; const batchCheckpoints = createModuleDataCheckpoints(initialData, {}, ["tbx:mod-a", "tbx:mod-b"]); const batchVersions = commitModuleDataCheckpoints({}, batchCheckpoints); const removedData = removeModuleDataKeys(initialData, ["tbx:mod-a", "tbx:mod-b"]); const laterCheckpoint = createModuleDataCheckpoint(removedData, batchVersions, "tbx:mod-b"); const laterVersions = commitModuleDataCheckpoints(batchVersions, [laterCheckpoint]); const laterData = applyModuleDataValue(removedData, "tbx:mod-b", { text: "latest-b" }); assert.deepEqual(rollbackModuleDataCheckpoints(laterData, laterVersions, batchCheckpoints), { "tbx:mod-a": { text: "before-a" }, "tbx:mod-b": { text: "latest-b" }, "tbx:mod-c": { text: "before-c" } }); }); test("module data rollback keeps removal of an initially missing key stable", () => { const initialData = { "tbx:mod-a": { text: "before-a" } }; const checkpoint = createModuleDataCheckpoint(initialData, {}, "tbx:missing"); const versions = commitModuleDataCheckpoints({}, [checkpoint]); const optimisticData = removeModuleDataKeys(initialData, ["tbx:missing"]); assert.deepEqual(rollbackModuleDataCheckpoints(optimisticData, versions, [checkpoint]), initialData); });