63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { deserialize, loadGame, saveGame, SaveStorage, serialize } from '../../src/sim/save';
|
|
import { createNewGame } from '../../src/sim/state';
|
|
import { issueCard } from '../../src/sim/loyalty';
|
|
import { STARTING_CASH_CENTS } from '../../src/sim/economy';
|
|
|
|
function memoryStorage(): SaveStorage {
|
|
const data = new Map<string, string>();
|
|
return { getItem: (k) => data.get(k) ?? null, setItem: (k, v) => void data.set(k, v) };
|
|
}
|
|
|
|
describe('save', () => {
|
|
it('round-trips the full state', () => {
|
|
const s = createNewGame(7);
|
|
issueCard(s.loyalty);
|
|
s.prices['tetris|new'] = 2500;
|
|
expect(deserialize(serialize(s))).toEqual(s);
|
|
});
|
|
|
|
it('rejects unknown save versions', () => {
|
|
const s = { ...createNewGame(1), saveVersion: 99 };
|
|
expect(() => deserialize(JSON.stringify(s))).toThrow('Unsupported save version: 99');
|
|
});
|
|
|
|
it('rejects malformed saves', () => {
|
|
expect(() => deserialize('{"saveVersion":1}')).toThrow('Corrupted save');
|
|
});
|
|
|
|
it('rejects invalid JSON and non-object saves', () => {
|
|
expect(() => deserialize('{not json')).toThrow('Corrupted save');
|
|
expect(() => deserialize('null')).toThrow('Corrupted save');
|
|
expect(() => deserialize('[]')).toThrow('Corrupted save');
|
|
expect(() => deserialize('42')).toThrow('Corrupted save');
|
|
});
|
|
|
|
it('rejects saves with a missing field', () => {
|
|
const { day: _day, ...rest } = createNewGame(1);
|
|
expect(() => deserialize(JSON.stringify(rest))).toThrow('Corrupted save');
|
|
});
|
|
|
|
it('rejects saves missing bankruptcy fields', () => {
|
|
const { negativeMonthEnds: _n, ...noMonths } = createNewGame(1);
|
|
expect(() => deserialize(JSON.stringify(noMonths))).toThrow('Corrupted save');
|
|
const { bankrupt: _b, ...noBankrupt } = createNewGame(1);
|
|
expect(() => deserialize(JSON.stringify(noBankrupt))).toThrow('Corrupted save');
|
|
expect(() => deserialize(JSON.stringify({ ...createNewGame(1), bankrupt: 'no' }))).toThrow('Corrupted save');
|
|
});
|
|
|
|
it('keeps the current and monthly saves apart', () => {
|
|
const storage = memoryStorage();
|
|
const s = createNewGame(1);
|
|
saveGame(storage, s, { monthly: true });
|
|
s.cash = 1;
|
|
saveGame(storage, s, { monthly: false });
|
|
expect(loadGame(storage, 'current')!.cash).toBe(1);
|
|
expect(loadGame(storage, 'monthly')!.cash).toBe(STARTING_CASH_CENTS);
|
|
});
|
|
|
|
it('returns null when nothing is saved', () => {
|
|
expect(loadGame(memoryStorage(), 'current')).toBeNull();
|
|
});
|
|
});
|