라이브 티커 · 갤럭시 검색 색인 · 주간 랭킹 스냅샷 · 연속 ZAP 상한 · 가입 행성 Zap · 성운 목표 · 랭킹 갱신 안내 · 행성 터치 반응

This commit is contained in:
Sn-Kinos
2026-10-05 22:38:42 +09:00
parent 000c058097
commit 4bb92c2ee7
44 changed files with 727 additions and 78 deletions
+35
View File
@@ -121,6 +121,24 @@ void main() {
expect(home.growth.requiredSfpi, 16575);
});
test('갤럭시 검색은 맵 상위 12개 밖의 행성도 이름 색인으로 찾는다 (Figma 353:217832)', () async {
final db = await _seed();
for (var i = 0; i < 15; i++) {
await db.doc('fandoms/f$i').set({'name': 'Star$i', 'stage': 1, 'fpiScore': 1000 - i});
await db.doc('fandomNames/star$i').set({'fandomId': 'f$i'});
}
await db.doc('fandoms/low').set({'name': 'Moonlight', 'stage': 1, 'fpiScore': 1});
await db.doc('fandomNames/moonlight').set({'fandomId': 'low'});
final repo = FirestoreGalaxyRepository(_backend(db));
final map = await repo.load();
expect(map.planets.any((p) => p.id == 'low'), isFalse);
final hits = await repo.search('MOON');
expect(hits.single.name, 'Moonlight');
expect((await repo.search('star1')).map((p) => p.id).toSet(),
{'f1', 'f10', 'f11', 'f12', 'f13', 'f14'});
expect(await repo.search(' '), isEmpty);
});
test('홈과 상세는 같은 팬덤의 서버 Stage를 표시하고 개인 Stage를 섞지 않는다', () async {
final db = await _seed();
await db.doc('fandoms/bts').update({'stage': 4, 'colorKey': 'gold'});
@@ -134,10 +152,13 @@ void main() {
expect(detail.stage, 4);
expect(detail.isNebula, false);
await db.doc('fandoms/bts').update({'stage': 0});
// 성운 전환 목표는 앱 상수가 아니라 서버와 같은 운영값(B-10).
await db.doc('config/policy').set({'nebulaMinPop': 2000, 'nebulaMinMembers': 12});
final nebula = await FirestorePlanetRepository(_backend(db), fandomId: 'bts')
.load(nebula: false);
expect(nebula.stage, 0);
expect(nebula.isNebula, true);
expect([nebula.nebulaTargetPop, nebula.nebulaTargetMembers], [2000, 12]);
});
test('서버에 단계가 없으면 시작 단계로 지어내지 않는다', () async {
@@ -559,6 +580,20 @@ void main() {
expect(ranking.mine!.change, 1);
});
test('랭킹은 마지막 갱신 시각과 갱신 주기를 함께 준다 — 별첨 1 ② 예외처리', () async {
final db = await seedPlanet();
final at = DateTime.utc(2026, 10, 7, 3, 4);
await db.doc('fandoms/bts').update({
'fpiUpdatedAt': Timestamp.fromDate(at),
'memberRankedAt': Timestamp.fromDate(at),
});
final repo = FirestorePlanetRepository(_backend(db), fandomId: 'bts');
final planets = await repo.planetRanking(metric: FpiMetric.bpm);
expect([planets.updatedAt, planets.refreshMinutes], [at.toLocal(), 1]);
final users = await repo.userRanking(metric: FpiMetric.bpm, fandomId: 'bts');
expect([users.updatedAt, users.refreshMinutes], [at.toLocal(), 5]);
});
test('랭킹 모집단은 최근 7일 유효 활동 행성뿐이다 — 별첨 B', () async {
final db = await seedPlanet();
final ranking = await FirestorePlanetRepository(_backend(db), fandomId: 'bts')