import { afterAll, beforeAll, beforeEach, describe, expect, it } from 'vitest'; import { getFirestore } from 'firebase-admin/firestore'; import { bootAdmin, shutdownAdmin } from './support.js'; import { fnSignupConsent } from '../src/account/account.js'; /** 가입 약관 동의 — 필수 3항 검사 · 항목별 동의 행 · 동의 시각 기록. */ const U = 'test-consent-user'; const db = () => getFirestore(); type CallReq = Parameters[0]; const as = (uid: string, data: Record) => ({ data, auth: { uid, token: {} } }) as CallReq; const codeOf = async (p: Promise) => { try { await p; return 'ok'; } catch (e) { return (e as { code?: string }).code; } }; const wipe = () => db().recursiveDelete(db().doc(`users/${U}`)); beforeAll(() => { bootAdmin(); }); afterAll(async () => { await wipe(); await shutdownAdmin(); }); beforeEach(wipe); describe('fnSignupConsent', () => { it('필수(서비스 · 개인정보 수집·이용 · 만 14세) 하나라도 빠지면 거부하고 기록하지 않는다', async () => { expect(await codeOf(fnSignupConsent.run(as(U, { version: 'v1', agreed: ['service', 'age'] })))) .toBe('invalid-argument'); expect((await db().doc(`users/${U}`).get()).get('termsAgreedAt')).toBeUndefined(); }); it('필수만 동의 — 항목별 행 · 마케팅 기본 OFF · termsAgreedAt', async () => { await fnSignupConsent.run(as(U, { version: 'v1', agreed: ['service', 'privacy', 'age'] })); const user = (await db().doc(`users/${U}`).get()).data()!; expect(user.termsAgreedAt).toBeDefined(); expect(user.termsVersion).toBe('v1'); expect(user.notificationPrefs.marketing).toBe(false); const rows = (await db().collection(`users/${U}/consents`).get()).docs.map((d) => d.id).sort(); expect(rows).toEqual(['age_v1_grant', 'marketing_v1_revoke', 'privacy_v1_grant', 'service_v1_grant']); }); it('마케팅 선택 동의는 알림 마케팅 구분과 같은 값이 된다', async () => { await fnSignupConsent.run(as(U, { version: 'v1', agreed: ['service', 'privacy', 'age', 'marketing'] })); expect((await db().doc(`users/${U}`).get()).get('notificationPrefs.marketing')).toBe(true); expect((await db().doc(`users/${U}/consents/marketing_v1_grant`).get()).get('granted')).toBe(true); }); it('로그인하지 않은 호출은 거부', async () => { expect(await codeOf(fnSignupConsent.run({ data: { version: 'v1', agreed: [] } } as CallReq))) .not.toBe('ok'); }); });