fix(BUG-4): updateDoc patch on activeDisplay (not setDoc replace)

All 5 storage.setDoc(activeDisplay, {...}, {merge:true}) →
storage.updateDoc(activeDisplay, {...}).

setDoc merge:true worked in prod (firebase honors merge) but ws adapter
+ mock ignore opts arg entirely → clobbers doc. updateDoc uses PATCH
across all adapters (firebase real updateDoc, ws PATCH endpoint, mock
merge). Consistent, no clobber.

Sites fixed:
- hidePlayerHp toggle
- startEncounter (set active ids)
- endEncounter (null active ids)
- deactivate active display
- activate new display

TDD: HideHpToggle.test RED first (assert updateDoc patch, impl still
setDoc → 0 calls found). GREEN after switch.

Char tests updated: Encounter.characterization (2) + Combat.characterization
(2) assert updateDoc on activeDisplay, not setDoc.

BUG-4: prod was already fixed (merge:true), test was RED due to mock
ignoring opts. Now all 3 adapters consistent via updateDoc.
This commit is contained in:
david raistrick
2026-07-01 23:32:23 -04:00
parent d00cc104c9
commit c0998da0a7
5 changed files with 37 additions and 30 deletions
+5 -5
View File
@@ -50,14 +50,14 @@ describe('BUG-4: hide-player-HP toggle preserves activeDisplay', () => {
await waitFor(() => {
const writes = getAdapterCalls().filter(
c => c.fn === 'setDoc' && c.path.includes('activeDisplay/status')
c => c.fn === 'updateDoc' && c.path.includes('activeDisplay/status')
);
expect(writes.length).toBeGreaterThan(0);
const last = writes[writes.length - 1];
// data written must include activeCampaignId AND activeEncounterId
// BUG: writes only {hidePlayerHp:true}, clobbering them.
expect(last.data.activeCampaignId).toBe('c1');
expect(last.data.activeEncounterId).toBe('e1');
// patch must NOT clobber activeCampaignId/activeEncounterId.
// BUG: setDoc replace writes only {hidePlayerHp:true} clobbers.
// Fix: updateDoc patch — other fields untouched.
expect(last.patch.hidePlayerHp).toBe(true);
}, { timeout: 3000 });
});
});