import { afterAll, beforeAll, expect, it } from 'vitest'; import { getFirestore } from 'firebase-admin/firestore'; import { bootAdmin, shutdownAdmin } from './support.js'; import { snapshotWeeklyRanking, weekKeyOf } from '../src/fandom/weekly.js'; /** 별첨 B 「Ranking Snapshot — 주 1회 영구 Archive」. */ const ids = ['test-week-a', 'test-week-b', 'test-week-c', 'test-week-out']; beforeAll(async () => { bootAdmin(); const db = getFirestore(); await db.doc('fandoms/test-week-a').set({ name: 'A', fpiScore: 300, rankingEligible: true, growthPop: 1200, sfpi: 34 }); await db.doc('fandoms/test-week-b').set({ name: 'B', fpiScore: 300, rankingEligible: true }); await db.doc('fandoms/test-week-c').set({ name: 'C', fpiScore: 100, rankingEligible: true }); await db.doc('fandoms/test-week-out').set({ name: 'X', fpiScore: 999, rankingEligible: false }); }); afterAll(async () => { const db = getFirestore(); for (const id of ids) await db.recursiveDelete(db.doc(`fandoms/${id}`)); await db.recursiveDelete(db.collection('rankingSnapshots')); await shutdownAdmin(); }); it('월요일 00:10 KST 에 돌면 방금 끝난 주를 가리킨다', () => { // 2026-10-05(월) 00:10 KST → 9/28~10/4 = 2026-W40. expect(weekKeyOf(new Date('2026-10-05T00:10:00+09:00'))).toBe('2026-W40'); expect(weekKeyOf(new Date('2027-01-04T00:10:00+09:00'))).toBe('2026-W53'); }); it('모집단 행성의 공동 순위를 한 번만 영구 보관한다', async () => { const db = getFirestore(); const at = new Date('2026-10-05T00:10:00+09:00'); expect(await snapshotWeeklyRanking(at)).toEqual({ week: '2026-W40', created: true }); const snap = (await db.doc('rankingSnapshots/2026-W40').get()).data()!; const ours = (snap.planets as Array<{ fandomId: string; rank: number }>) .filter((p) => ids.includes(p.fandomId)).map((p) => [p.fandomId, p.rank]); expect(ours.map(([id]) => id)).toEqual(['test-week-a', 'test-week-b', 'test-week-c']); // 같은 점수는 같은 순위(1·1·3) — 다른 테스트 행성이 섞여도 상대 순서는 같다. expect(ours[0]![1]).toBe(ours[1]![1]); // HOME 「이번 주 성장」 기준선(A-37) — 그 시각의 Growth POP · sFPI 누계를 함께 남긴다. const a = (snap.planets as Array>).find((p) => p.fandomId === 'test-week-a')!; expect([a.growthPop, a.sfpi]).toEqual([1200, 34]); // 다시 돌아도 덮지 않는다. await db.doc('fandoms/test-week-c').update({ fpiScore: 9_999 }); expect(await snapshotWeeklyRanking(at)).toEqual({ week: '2026-W40', created: false }); const again = (await db.doc('rankingSnapshots/2026-W40').get()).data()!; expect(again.planets).toEqual(snap.planets); });