diff --git a/app/firebase/functions/src/notify/inbox.ts b/app/firebase/functions/src/notify/inbox.ts index 6e75730..49c98c8 100644 --- a/app/firebase/functions/src/notify/inbox.ts +++ b/app/firebase/functions/src/notify/inbox.ts @@ -106,6 +106,8 @@ export async function notifyQuestDone( if (before && before.dayKey === after.dayKey && (before.count as number | undefined ?? 0) >= count) return false; const db = getFirestore(); const [quest, user] = await Promise.all([db.doc(`quests/${questId}`).get(), db.doc(`users/${uid}`).get()]); + // 진행 문서에는 Quest 가 아닌 카운터도 있다(광고 일일 횟수 `questProgress/ad` 등) — Quest 문서가 없으면 알리지 않는다. + if (!quest.exists) return false; const title = localizedText(quest.get('title'), user.get('locale')); return notifyOnce(uid, `quest_${questId}_${String(after.dayKey)}_${count}`, { eventType: 'quest', type: 'essential', diff --git a/app/firebase/functions/test/inbox.test.ts b/app/firebase/functions/test/inbox.test.ts index 6219467..9c21876 100644 --- a/app/firebase/functions/test/inbox.test.ts +++ b/app/firebase/functions/test/inbox.test.ts @@ -59,6 +59,11 @@ it('영웅의 선물 발동은 회원 전원에게 발동자 닉네임으로', a expect(hero[0]!.fandomId).toBe(FANDOM); }); +it('Quest 문서가 없는 진행 카운터(광고 일일 횟수 ad)는 퀘스트 완료로 알리지 않는다', async () => { + expect(await notifyQuestDone(A, 'ad', undefined, { dayKey: '2026-10-08', count: 1 })).toBe(false); + expect((await inbox(A)).filter((n) => n.eventType === 'quest')).toHaveLength(0); +}); + it('퀘스트 완료는 횟수가 오른 때만 본인에게, 상세 경로를 싣는다', async () => { const day = '2026-10-05'; expect(await notifyQuestDone(A, 'test-inbox-quest', undefined, { dayKey: day, count: 1 })).toBe(true);