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.
This commit is contained in:
@@ -15,6 +15,13 @@ import {
|
||||
onSnapshot, updateDoc, deleteDoc, query, orderBy, limit, writeBatch, serverTimestamp,
|
||||
} from 'firebase/firestore';
|
||||
|
||||
// Adapter call recorder (instrumentation, no behavior change).
|
||||
// Tests assert adapter.subscribeDoc called (catches raw-SDK bypass like DisplayView).
|
||||
const ADAPTER_CALLS = [];
|
||||
function recordAdapterCall(entry) { ADAPTER_CALLS.push({ ...entry, ts: Date.now() }); }
|
||||
export function getAdapterCalls() { return [...ADAPTER_CALLS]; }
|
||||
export function resetAdapterCalls() { ADAPTER_CALLS.length = 0; }
|
||||
|
||||
// Path helpers mirror App.js getPath object.
|
||||
const APP_ID = process.env.REACT_APP_TRACKER_APP_ID || 'ttrpg-initiative-tracker-default';
|
||||
const PUBLIC_DATA_PATH = `artifacts/${APP_ID}/public/data`;
|
||||
@@ -112,12 +119,14 @@ export function createFirebaseStorage() {
|
||||
|
||||
// Subscribe = onSnapshot. cb fires immediately + on change. Returns unsubscribe.
|
||||
subscribeDoc(path, cb) {
|
||||
recordAdapterCall({ fn: 'subscribeDoc', path });
|
||||
return onSnapshot(doc(db, path), (snap) => {
|
||||
cb(snap.exists() ? { id: snap.id, ...snap.data() } : null);
|
||||
}, (err) => console.error(`subscribeDoc ${path}:`, err));
|
||||
},
|
||||
|
||||
subscribeCollection(collectionPath, cb, queryConstraints = []) {
|
||||
recordAdapterCall({ fn: 'subscribeCollection', path: collectionPath });
|
||||
const q = queryConstraints.length > 0
|
||||
? query(collection(db, collectionPath), ...queryConstraints)
|
||||
: collection(db, collectionPath);
|
||||
|
||||
Reference in New Issue
Block a user