import { describe, expect, it } from "vitest"; import { matchFromOrders } from "./match"; import { matchFromSeed } from "./random"; import { parseSavedGame } from "./persistence"; const { deckOrders, coinFlips } = matchFromSeed("abc"); const match = matchFromOrders(deckOrders, coinFlips, 3); function savedGame(overrides: Record = {}) { return { version: 2, seed: "abc", mode: 3, frames: [{ state: match, selection: { handSlot: null, placeType: null } }], cursor: 0, resultOpen: true, ...overrides, }; } describe("saved game parsing", () => { it("accepts a complete saved timeline", () => { const saved = savedGame(); expect(parseSavedGame(JSON.stringify(saved))).toEqual(saved); }); it("accepts a one-deal game", () => { const saved = savedGame({ mode: 1, frames: [ { state: matchFromOrders(deckOrders, coinFlips, 1), selection: { handSlot: null, placeType: null } }, ], }); expect(parseSavedGame(JSON.stringify(saved))).toEqual(saved); }); it("rejects corrupt and incompatible data", () => { expect(parseSavedGame("not json")).toBeNull(); expect(parseSavedGame(JSON.stringify({ version: 2 }))).toBeNull(); expect(parseSavedGame(JSON.stringify(savedGame({ frames: [] })))).toBeNull(); expect(parseSavedGame(JSON.stringify(savedGame({ mode: 2 })))).toBeNull(); }); it("refuses a v1 save rather than guessing what it meant", () => { // A v1 save is one round: no carry, no deals for rounds two and three, no // coin flips. There is nothing honest to migrate it into, so it is dropped // and a fresh game is dealt. const v1 = { version: 1, seed: "abc", frames: [{ state: match.round, selection: {} }], cursor: 0, resultOpen: true }; expect(parseSavedGame(JSON.stringify(v1))).toBeNull(); }); });