import assert from "node:assert/strict"; import fs from "node:fs"; import path from "node:path"; import test from "node:test"; import ts from "typescript"; const repoRoot = path.resolve(import.meta.dirname, "../../.."); const sourcePath = path.join(repoRoot, "web/protocol/save-transaction.ts"); const transpiled = ts.transpileModule(fs.readFileSync(sourcePath, "utf8"), { compilerOptions: { module: ts.ModuleKind.ES2022, target: ts.ScriptTarget.ES2022 }, fileName: sourcePath, reportDiagnostics: true, }); assert.deepEqual(transpiled.diagnostics, []); const moduleUrl = `data:text/javascript;base64,${Buffer.from(transpiled.outputText).toString("base64")}`; const { SAVE_ATTEMPT_STAGES, advanceSaveTransaction, beginSaveTransaction, commitSaveTransaction, createSaveTransactionState, failSaveTransaction, } = await import(moduleUrl); const oldCommit = { revision: 7, sha256: "a".repeat(64) }; const newCommit = { revision: 8, sha256: "b".repeat(64) }; function stateAt(stage) { let result = beginSaveTransaction(createSaveTransactionState(oldCommit), newCommit.revision); assert.equal(result.ok, true); for (const next of SAVE_ATTEMPT_STAGES.slice(1, SAVE_ATTEMPT_STAGES.indexOf(stage) + 1)) { result = advanceSaveTransaction(result.state, next, next === "OPFS_STAGE" ? newCommit.sha256 : undefined); assert.equal(result.ok, true); } return result.state; } test("M7-05 preserves the old committed identity at every failed save stage", () => { for (const stage of SAVE_ATTEMPT_STAGES) { const failed = failSaveTransaction(stateAt(stage), `SAVE_${stage}_INTERRUPTED`); assert.equal(failed.status, "FAILED"); assert.equal(failed.stage, stage); assert.deepEqual(failed.committed, oldCommit); assert.equal(failed.candidate.revision, newCommit.revision); } }); test("M7-05 advances committed revision and hash only after matching metadata commit", () => { const metadata = stateAt("METADATA_COMMIT"); assert.deepEqual(commitSaveTransaction(metadata, { ...newCommit, sha256: "c".repeat(64) }), { ok: false, state: metadata, errorCode: "SAVE_TRANSACTION_COMMIT_MISMATCH", }); const committed = commitSaveTransaction(metadata, newCommit); assert.equal(committed.ok, true); assert.deepEqual(committed.state.committed, newCommit); assert.equal(committed.state.status, "SUCCEEDED"); }); test("M7-05 rejects reentrant and out-of-order save transitions", () => { const running = beginSaveTransaction(createSaveTransactionState(oldCommit), 8); assert.equal(running.ok, true); assert.equal(beginSaveTransaction(running.state, 9).errorCode, "SAVE_TRANSACTION_INVALID_TRANSITION"); assert.equal(advanceSaveTransaction(running.state, "SCENE_COMMIT").errorCode, "SAVE_TRANSACTION_INVALID_TRANSITION"); });