Files

52 lines
2.0 KiB
TypeScript

import { initializeApp, deleteApp, getApps, type App } from 'firebase-admin/app';
import { getFirestore } from 'firebase-admin/firestore';
/**
* 에뮬레이터 전용 테스트 환경.
*
* `FIRESTORE_EMULATOR_HOST` 가 없으면 **실 프로젝트로 붙을 위험**이 있으므로
* 바로 실패시킨다. 테스트가 운영 데이터를 건드리는 사고는 한 번이면 치명적이다.
*/
export const PROJECT_ID = 'demo-fanuzu';
export function bootAdmin(): App {
if (!process.env.FIRESTORE_EMULATOR_HOST) {
throw new Error(
'FIRESTORE_EMULATOR_HOST 가 없습니다. `npm run test:emulator` 로 실행하십시오.',
);
}
const existing = getApps()[0];
if (existing) return existing;
return initializeApp({ projectId: PROJECT_ID, storageBucket: `${PROJECT_ID}.appspot.com` });
}
export async function shutdownAdmin(): Promise<void> {
for (const app of getApps()) await deleteApp(app);
}
/**
* 그 사용자가 남긴 문서를 전부 지운다.
*
* **`users/{uid}` 아래만 지우면 모자란다.** 기여 차감은 팬덤 멤버 문서에도
* 누적되므로, 거기를 남겨 두면 다음 테스트에서 값이 겹쳐 올라간다. 실제로
* 그 때문에 「기여 40」을 기대하는 검증이 회차가 쌓이며 120 을 보았다.
*/
export async function wipeUser(uid: string): Promise<void> {
const db = getFirestore();
for (const sub of [
'popLots', 'popTransactions', 'growthEvents', 'questProgress', 'wallet',
'consents', 'purchases', 'subscription', 'subscriptionEvents', 'adBonuses',
'verifiedCompletions', 'rateLimits',
]) {
const snap = await db.collection(`users/${uid}/${sub}`).get();
await Promise.all(snap.docs.map((d) => d.ref.delete()));
}
await db.doc(`users/${uid}`).delete();
// 이 사용자가 멤버로 올라간 팬덤 문서까지 지운다.
const members = await db.collectionGroup('members').get();
await Promise.all(
members.docs.filter((d) => d.id === uid).map((d) => d.ref.delete()),
);
}