// Test helper: in-memory mock storage. Records all writes (addDoc/updateDoc). // Captures encounter patches + log entries so tests assert persistence. function createMockStorage() { const docs = new Map(); // path -> data const calls = []; // ordered {fn, path, data} return { calls, docs, async getDoc(path) { return docs.has(path) ? { ...docs.get(path) } : null; }, async setDoc(path, data) { calls.push({ fn: 'setDoc', path, data }); docs.set(path, { ...data }); }, async addDoc(path, data) { calls.push({ fn: 'addDoc', path, data }); }, async updateDoc(path, patch) { calls.push({ fn: 'updateDoc', path, data: patch }); if (!docs.has(path)) docs.set(path, {}); docs.set(path, { ...docs.get(path), ...patch }); }, async deleteDoc(path) { calls.push({ fn: 'deleteDoc', path }); docs.delete(path); }, async getCollection() { return []; }, async batchWrite(ops) { for (const op of ops) { if (op.type === 'delete') await this.deleteDoc(op.path); else await this.updateDoc(op.path, op.data); } }, async undo() {}, // filters updatesFor(prefix) { return calls.filter(c => c.fn === 'updateDoc' && c.path.startsWith(prefix)); }, logs() { return calls.filter(c => c.fn === 'addDoc').map(c => c.data); }, }; } // Standard ctx for tests. encPath + logPath + displayPath preset. // Returns { storage, ctx } so tests destructure both in one call: // const { storage, ctx } = mockCtx(); function mockCtx(storage) { storage = storage || createMockStorage(); const ctx = { storage, encPath: 'encounters/e1', logPath: 'logs', displayPath: 'activeDisplay/status', }; return { storage, ctx }; } // Standard 2-participant ready encounter. function readyEnc(opts = {}) { return { id: 'e1', name: opts.name || 'TestEnc', round: 0, isStarted: false, isPaused: false, currentTurnParticipantId: null, turnOrderIds: [], participants: opts.participants || [ { id: 'p1', name: 'Bob', type: 'character', initiative: 10, maxHp: 10, currentHp: 10, isActive: true, conditions: [], deathSaves: 0, deathFails: 0, isStable: false, isDying: false }, { id: 'p2', name: 'Mob', type: 'monster', initiative: 5, maxHp: 10, currentHp: 10, isActive: true, conditions: [], deathSaves: 0, deathFails: 0, isStable: false, isDying: false }, ], }; } module.exports = { createMockStorage, mockCtx, readyEnc };