포그라운드 Push 표시 · 퀘스트 알림 다국어 제목 · 약관 미동의 계정의 행성 가입·성운 생성 차단
This commit is contained in:
@@ -67,3 +67,14 @@ it('퀘스트 완료는 횟수가 오른 때만 본인에게, 상세 경로를
|
||||
expect(quest[0]!.title).toBe('[만보기] 퀘스트를 완료했어요!');
|
||||
expect(quest[0]!.targetPath).toBe('quests/test-inbox-quest');
|
||||
});
|
||||
|
||||
it('운영 Quest 의 다국어 제목은 사용자 언어(없으면 ko)로 푼다', async () => {
|
||||
const db = getFirestore();
|
||||
await db.doc('quests/test-inbox-quest').set({ title: { ko: '신곡 스트리밍', en: 'Stream the single' } });
|
||||
await db.doc(`users/${B}`).set({ locale: 'en' });
|
||||
await notifyQuestDone(A, 'test-inbox-quest', undefined, { dayKey: '2026-10-06', count: 1 });
|
||||
await notifyQuestDone(B, 'test-inbox-quest', undefined, { dayKey: '2026-10-06', count: 1 });
|
||||
const titles = async (uid: string) => (await inbox(uid)).filter((n) => n.eventType === 'quest').map((n) => n.title);
|
||||
expect(await titles(A)).toContain('[신곡 스트리밍] 퀘스트를 완료했어요!');
|
||||
expect(await titles(B)).toEqual(['[Stream the single] 퀘스트를 완료했어요!']);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest';
|
||||
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { FieldValue, getFirestore, Timestamp } from 'firebase-admin/firestore';
|
||||
|
||||
import { bootAdmin, shutdownAdmin, wipeUser } from './support.js';
|
||||
@@ -36,9 +36,14 @@ const user = async (uid = UID) => (await db().doc(`users/${uid}`).get()).data()
|
||||
const fandom = async (id: string) => (await db().doc(`fandoms/${id}`).get()).data() ?? {};
|
||||
|
||||
beforeAll(() => { bootAdmin(); });
|
||||
// 가입 · 성운 생성은 약관 동의(`termsAgreedAt`)가 있어야 한다 — 시험 계정은 동의를 마친 상태로 시작한다.
|
||||
const agree = (uid: string) => db().doc(`users/${uid}`).set({ termsAgreedAt: Timestamp.now() }, { merge: true });
|
||||
beforeEach(async () => {
|
||||
for (const uid of [UID, OTHER, 'test-planet-create-third']) await agree(uid);
|
||||
});
|
||||
afterAll(async () => { await shutdownAdmin(); });
|
||||
afterEach(async () => {
|
||||
for (const uid of [UID, OTHER]) {
|
||||
for (const uid of [UID, OTHER, 'test-planet-create-third']) {
|
||||
await wipeUser(uid);
|
||||
await db().recursiveDelete(db().collection(`users/${uid}/nebulaCreates`));
|
||||
await db().recursiveDelete(db().collection(`users/${uid}/memberships`));
|
||||
@@ -64,6 +69,7 @@ describe('성운 생성', () => {
|
||||
|
||||
it('대표 변경 30일 대기 중이면 성운 · 멤버십만 만들고 대표는 그대로 둔다(C-15)', async () => {
|
||||
await db().doc(`users/${UID}`).set({
|
||||
termsAgreedAt: Timestamp.now(),
|
||||
primaryFandomId: 'old', fandomId: 'old', primaryChangedAt: Timestamp.fromMillis(Date.now() - 86_400_000),
|
||||
});
|
||||
const { fandomId, primaryChanged } = await call(fnNebulaCreate, { name: 'Cooldown' });
|
||||
@@ -106,6 +112,14 @@ describe('가입 · 탈퇴 · 대표 팬덤', () => {
|
||||
expect((await user()).fandomIds).toEqual([id]);
|
||||
});
|
||||
|
||||
it('약관에 동의하지 않은 계정은 가입 · 성운 생성을 거부한다', async () => {
|
||||
const { fandomId } = await call(fnNebulaCreate, { name: 'Terms Gate' });
|
||||
await db().doc(`users/${OTHER}`).set({ termsAgreedAt: FieldValue.delete() }, { merge: true });
|
||||
expect(await codeOf(() => call(fnFandomJoin, { fandomId }, OTHER))).toBe('E-PERM-01');
|
||||
expect(await codeOf(() => call(fnNebulaCreate, { name: 'Terms Gate Two' }, OTHER))).toBe('E-PERM-01');
|
||||
expect((await fandom(fandomId as string)).memberCount).toBe(1);
|
||||
});
|
||||
|
||||
it('없는 팬덤 가입 · 가입하지 않은 팬덤을 대표로 지정은 거부한다', async () => {
|
||||
expect(await codeOf(() => call(fnFandomJoin, { fandomId: 'missing-fandom' }))).toBe('E-PERM-01');
|
||||
const { fandomId } = await call(fnNebulaCreate, { name: 'NotMine' }, OTHER);
|
||||
|
||||
Reference in New Issue
Block a user