import { describe, expect, it } from 'vitest'; import { buildContent } from '../../content/schema'; import { createGameState, startAction } from '../../engine/game'; import { createSave, serializeSave } from '../../engine/save'; import { createMemoryBackend, loadGame, saveGame } from '../persistence'; function testContent() { return buildContent({ resources: [{ id: 'gold', name: 'Gold', startAmount: 0 }], actions: [ { id: 'forage', name: 'Forage', durationMs: 3000, yields: [{ resourceId: 'gold', amount: 1 }] }, ], }); } describe('loadGame()', () => { it('returns a fresh game when no save exists', async () => { const content = testContent(); const result = await loadGame(content, createMemoryBackend(), 1000); expect(result.state.resources.gold).toBe(0); expect(result.offlineMs).toBe(0); }); it('round-trips a saved game and credits offline progress', async () => { const content = testContent(); const state = createGameState(content); state.resources.gold = 10; startAction(state, content, 'forage'); const backend = createMemoryBackend(); await saveGame(state, backend, 1000); const result = await loadGame(content, backend, 1000 + 9000); // 9s offline expect(result.offlineMs).toBe(9000); expect(result.state.resources.gold).toBe(11); // 10 + one completion expect(result.state.activeActionId).toBeNull(); }); it('falls back to a fresh game on a corrupt save instead of throwing', async () => { const content = testContent(); const result = await loadGame(content, createMemoryBackend('@@@garbage@@@'), 1000); expect(result.state.resources.gold).toBe(0); expect(result.offlineMs).toBe(0); }); it('drops an active action that no longer exists in content', async () => { const content = testContent(); const stale = serializeSave( createSave( { resources: { gold: 1 }, activeActionId: 'ghost-action', actionElapsedMs: 0, actionQueue: [], }, 1000, ), ); const result = await loadGame(content, createMemoryBackend(stale), 1000); expect(result.state.activeActionId).toBeNull(); }); });