david raistrick
79af61cb8b
match main firebase behavior; fix contract + mismatches
...
Contract rewritten to match main prod truth:
- require id injection in all doc/collection results
- honor setDoc({merge:true}) (main L1624 + 4 activeDisplay sites)
- drop invented bare<->prefixed cross-lookup tests (main never does this)
- add setDoc{merge}, batch set-only/update-only contract coverage
Fix mismatches vs main:
- subscribeCollection hook now forwards queryConstraints (was dropped;
LOG_QUERY sort+limit honored again). Mock onSnapshot honors orderBy+limit.
2 new contract tests prove the chain.
- subscribeDoc/subscribeCollection adapters now forward errCb. App hooks +
DisplayView propagate subscribe errors to UI (match main onSnapshot 3rd arg).
- ws adapter signatures accept queryConstraints + errCb (interface match).
activeDisplay writes match main:
- 5 unguarded sites -> setDoc({merge:true}) (create-if-missing, not updateDoc)
- 3 guarded sites stay updateDoc
Delete memory adapter: third storage system added complexity, zero value.
firebase-mock covers fast tests, ws covers server path. Factory throws on
unknown mode now.
Delete phantom 'Phase A/B' comment in firebase.js header.
Tests updated to assert setDoc{merge} (not updateDoc) for activeDisplay writes.
83/83 green.
2026-07-04 12:22:19 -04:00
david raistrick
d979b03f2e
tests: BUG-4 RED locked (hide-HP clobbers activeDisplay), add write recorder
...
src/tests/HideHpToggle.test.js: renders App, selects campaign, toggles
hide-player-HP switch, asserts setDoc data includes activeCampaignId +
activeEncounterId. RED: data only {hidePlayerHp:true}, both clobbered.
Root cause proven with evidence (recorder):
setDoc(activeDisplay/status, {hidePlayerHp:true}, {merge:true})
data written = {hidePlayerHp:true} ONLY
activeCampaignId = undefined
activeEncounterId = undefined
setDoc = replace per contract. {merge:true} arg ignored. Toggle wipes
encounter pointer → DisplayView reads null → 'Game Session Paused'.
Fix: use updateDoc (patch), not setDoc.
src/storage/firebase.js: adapter recorder now captures setDoc + updateDoc
(data + opts). Was subscribe-only. Enables write-path assertions.
2026-06-30 13:55:14 -04:00
david raistrick
84a8b78acd
M2: refactor DisplayView to storage adapter (red test first)
...
DisplayView missed in original M2 refactor — raw onSnapshot(doc(db,path))
survived. In ws/memory mode db is a stub sentinel, so raw SDK calls crash
('Expected first argument to collection() to be a CollectionReference...').
Reported by human testing player display after start combat.
TDD:
1. RED: DisplayView.characterization.test.js asserts adapter.subscribeDoc
called for campaign + encounter + activeDisplay paths. Adapter recorder
(getAdapterCalls/resetAdapterCalls in firebase.js) instruments subscribe
calls — catches raw-SDK bypass that firebase mock alone cannot (mock db
satisfies raw onSnapshot, hiding the bug).
2. Fix: 2 raw onSnapshot sites in DisplayView -> storage.subscribeDoc.
3. GREEN: 2 new tests pass, 116 total green.
Audit confirmed DisplayView was the ONLY remaining raw SDK site in App.js.
2026-06-29 13:13:46 -04:00
david raistrick
812298fa73
M2: refactor all firebase write sites to storage adapter
...
- 37 call sites: setDoc/updateDoc/deleteDoc/addDoc/getDocs/writeBatch -> storage.*
- adapter wraps SDK, path-string interface
- storage instance app-wide (getStorage)
- firebase.js: static imports (getDoc/getDocs alias), no dynamic import
56 frontend tests green. STORAGE=firebase = identical behavior.
2026-06-28 21:05:39 -04:00
david raistrick
12b24eb707
M2 (C): storage barrel re-export, App.js imports swapped
...
- src/storage/index.js: re-exports Firebase SDK
- App.js: imports from ./storage (was firebase/* direct)
- STORAGE=firebase = identical behavior
- dev server compiles clean
Safe refactor proof. Next: per-call-site path-based rewrite for ws adapter.
2026-06-28 17:51:39 -04:00