번역 평가 버튼 · 내 퀘스트 검토 버튼 · MY 질문 상세 · MY 완료 퀘스트 수 · 행성/성운 칸 · 라운지 빈 상태 수정

This commit is contained in:
Sn-Kinos
2026-10-05 15:12:33 +09:00
parent 5ad229b971
commit f84d696c21
18 changed files with 666 additions and 365 deletions
+10
View File
@@ -667,6 +667,16 @@ void main() {
expect(profile.levelLabel, 'Lv.1 GLOW');
expect(profile.passportTier, PassportTier.silver);
});
test('완료 퀘스트는 검증 활동 표식 수에서 무효 표식을 뺀 값이다', () async {
final db = await _seed();
final col = db.collection('users/$_uid/verifiedCompletions');
await col.doc('q1_20261004').set({'questId': 'q1'});
await col.doc('q2_20261005').set({'questId': 'q2'});
await col.doc('q3_20261005').set({'questId': 'q3', 'voided': true});
final profile = await FirestoreMyRepository(_backend(db)).profile();
expect(profile.completedQuests, 2);
});
});
group('FPI 공동 순위 (C-19)', () {
+30
View File
@@ -226,6 +226,17 @@ void main() {
expect(find.byType(FloatingActionButton), findsOneWidget);
});
testWidgets('글이 하나도 없으면 빈 상태 안내를 띄운다', (tester) async {
await _pumpTall(tester, const PlanetDetailScreen(
repository: _NoPosts(),
eclipse: NoEclipseRepository(),
));
await tester.tap(find.text('팬덤 라운지'));
await tester.pumpAndSettle();
expect(find.text('팬덤 라운지에 자유롭게 글을 작성해 보세요.'), findsOneWidget);
expect(find.byType(FloatingActionButton), findsOneWidget);
});
testWidgets('스크롤하면 히어로가 접히고 탭은 위에 남는다 — 발주사 지적(글이 보이게)', (tester) async {
tester.view.physicalSize = const Size(750, 1624);
tester.view.devicePixelRatio = 2;
@@ -583,3 +594,22 @@ void _fpiRankingTests() {
});
});
}
/// 라운지 글이 0건인 행성.
class _NoPosts extends SamplePlanetRepository {
const _NoPosts();
@override
Future<PlanetDetail> load({required bool nebula}) async {
final d = await super.load(nebula: nebula);
return PlanetDetail(
fandomId: d.fandomId, name: d.name, isNebula: d.isNebula,
totalFpi: d.totalFpi, scores: d.scores, members: d.members,
posts: const [],
);
}
@override
Future<List<LoungePost>> morePosts({required int offset, int limit = 5}) async =>
const [];
}
+34
View File
@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'package:fancake/features/auth/auth.dart';
import 'package:fancake/features/galaxy/galaxy_data.dart';
import 'package:fancake/features/inside/inside_data.dart';
import 'package:fancake/features/auth/auth_repository.dart';
import 'package:fancake/features/my/my_data.dart';
@@ -176,6 +177,24 @@ void main() {
expect(find.text('37'), findsOneWidget);
});
testWidgets('행성/성운 칸은 가입 목록을 팬덤 stage 그림으로 그린다', (tester) async {
await pumpWide(
tester,
MyScreen(
repository: SampleMyRepository(),
galaxy: _OneNebula(),
),
);
await tester.pump();
final images = tester
.widgetList<Image>(find.byType(Image))
.map((i) => (i.image as AssetImage).assetName)
.toList();
expect(images, contains('assets/figma/nebula-card.png'));
expect(images.where((a) => a.startsWith('assets/figma/my-planet-')), isEmpty);
expect(find.bySemanticsLabel('새 성운'), findsOneWidget);
});
testWidgets('프로필을 누르면 카드 오버레이가 뜬다', (tester) async {
await pumpWide(tester, MyScreen(repository: SampleMyRepository()));
await tester.pump();
@@ -1061,3 +1080,18 @@ class _MyInsides extends SampleInsideRepository {
),
];
}
/// 가입 행성이 성운(Stage0) 하나뿐인 계정.
class _OneNebula extends SampleGalaxyRepository {
@override
Future<GalaxySnapshot> load() async => const GalaxySnapshot(
planets: [],
myPop: 0,
memberships: [
PlanetNode(
id: 'n1', name: '새 성운', rank: 0, fpi: 0, members: 1, online: 0,
isMine: true, stage: 0,
),
],
);
}
+12
View File
@@ -11,6 +11,7 @@ import 'package:fancake/features/planet/planet_data.dart';
import 'package:fancake/features/translation/translation_comments.dart';
import 'package:firebase_auth_mocks/firebase_auth_mocks.dart';
import 'package:flutter/material.dart';
import 'package:fancake/core/theme/app_theme.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_test/flutter_test.dart';
@@ -40,6 +41,8 @@ void main() {
addTearDown(tester.view.reset);
await tester.pumpWidget(
MaterialApp(
// 실제 앱 테마 — 테마의 버튼 최소 크기가 마킹 버튼을 가린 적이 있다(10/5 실기기).
theme: buildAppTheme(),
locale: const Locale('ko'),
supportedLocales: appLocales,
localizationsDelegates: const [
@@ -228,6 +231,15 @@ void main() {
await pump(tester, repo);
// 작성자 이름이 비어 있으면 「팬」.
expect(find.text('팬'), findsOneWidget);
// 두 버튼이 같은 줄에 보이는 크기로 있어야 누를 수 있다.
final validBox = tester.getRect(
find.widgetWithText(OutlinedButton, '유효 0'),
);
final invalidBox = tester.getRect(
find.widgetWithText(OutlinedButton, '무효 0'),
);
expect(invalidBox.width, greaterThan(0));
expect(validBox.top, invalidBox.top);
await tester.tap(find.text('무효 0'));
await tester.pumpAndSettle();
expect(repo.marks, 1);