Figma 설명 프레임 반영 — 로그인·온보딩·스플래시 · HOME · GALAXY · 퀘스트·이클립스·알림
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import 'package:fancake/core/config/feature_flags.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
/// 스플래시 업데이트 확인(Figma `510:19053`) — 설치 버전이 운영 최신 버전보다 낮을 때만 안내.
|
||||
void main() {
|
||||
test('버전 비교', () {
|
||||
expect(isOlderVersion('0.5.0', '0.5.1'), isTrue);
|
||||
expect(isOlderVersion('0.5.0+7', '0.10.0'), isTrue);
|
||||
expect(isOlderVersion('0.5.0', '0.5.0'), isFalse);
|
||||
expect(isOlderVersion('0.6.0', '0.5.9'), isFalse);
|
||||
expect(isOlderVersion('1.0', '1.0.0'), isFalse);
|
||||
expect(isOlderVersion('0.5.0', 'abc'), isFalse);
|
||||
});
|
||||
|
||||
test('config/features.latestAppVersion 을 읽고, 없으면 null', () async {
|
||||
final flags = FeatureFlags(
|
||||
source: Stream.value({FeatureFlags.latestVersionKey: ' 0.6.0 '}),
|
||||
);
|
||||
await Future<void>.delayed(Duration.zero);
|
||||
expect(flags.latestVersion, '0.6.0');
|
||||
expect(FeatureFlags().latestVersion, isNull);
|
||||
});
|
||||
}
|
||||
@@ -198,7 +198,9 @@ void main() {
|
||||
expect(snapshot.popBalance, 12540);
|
||||
expect(snapshot.liveTicker, contains('버프'));
|
||||
expect(snapshot.growth.fandomName, 'BTS');
|
||||
expect(snapshot.growth.contributorName, 'BTS_Hong');
|
||||
// 설명 프레임 `2097:16391` — 인사 줄은 로그인 사용자 기준. 팬덤의 직전 기여자가 아니다.
|
||||
expect(snapshot.growth.contributorName, isNot('BTS_Hong'));
|
||||
expect(snapshot.growth.contributedPop, 0);
|
||||
expect(snapshot.growth.currentPop, 6270);
|
||||
// 서버가 growthPercent 를 주지 않으면 진행도로 낸다.
|
||||
expect(snapshot.growth.growthPercent, 63);
|
||||
@@ -827,14 +829,21 @@ void main() {
|
||||
expect(profile.nickname, '팬');
|
||||
});
|
||||
|
||||
test('홈 기여자명에 이메일이 남아 있어도 가린다', () async {
|
||||
test('홈 인사 줄은 로그인 사용자의 닉네임 · 사진이고 이메일 형태는 가린다', () async {
|
||||
final db = await _seed();
|
||||
await db.doc('fandoms/bts').set({
|
||||
'name': 'BTS', 'lastContributorName': 'test123@naver.com',
|
||||
'lastContributedPop': 10,
|
||||
await db.doc('users/$_uid').set({
|
||||
'nickname': 'ARMY_Kim', 'photoUrl': 'https://example.com/p.png',
|
||||
}, SetOptions(merge: true));
|
||||
final snapshot = await FirestoreHomeRepository(_backend(db)).load();
|
||||
var snapshot = await FirestoreHomeRepository(_backend(db)).load();
|
||||
expect(snapshot.growth.contributorName, 'ARMY_Kim');
|
||||
expect(snapshot.growth.photoUrl, 'https://example.com/p.png');
|
||||
|
||||
await db.doc('users/$_uid').set({
|
||||
'nickname': 'test123@naver.com', 'photoUrl': '',
|
||||
}, SetOptions(merge: true));
|
||||
snapshot = await FirestoreHomeRepository(_backend(db)).load();
|
||||
expect(snapshot.growth.contributorName, '팬');
|
||||
expect(snapshot.growth.photoUrl, isNull);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -118,7 +118,7 @@ void main() {
|
||||
|
||||
testWidgets('이름을 넣고 만들면 기본 행성 변경을 되묻는다', (tester) async {
|
||||
await _pump(tester, const NebulaCreateScreen());
|
||||
await tester.enterText(find.byType(TextField), 'BTS_RM');
|
||||
await tester.enterText(find.byType(TextField), 'BTS RM');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -131,13 +131,13 @@ void main() {
|
||||
testWidgets('변경을 누르면 fn-nebula-create 로 만들고 새 성운 ID 를 들고 닫힌다', (tester) async {
|
||||
final repo = _CreateRepo();
|
||||
final results = await _pushed(tester, NebulaCreateScreen(repository: repo));
|
||||
await tester.enterText(find.byType(TextField), 'BTS_RM');
|
||||
await tester.enterText(find.byType(TextField), 'BTS RM');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('변경'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(repo.calls, ['BTS_RM']);
|
||||
expect(repo.calls, ['BTS RM']);
|
||||
expect(results, ['new-nebula']);
|
||||
expect(find.byType(NebulaCreateScreen), findsNothing);
|
||||
});
|
||||
@@ -147,7 +147,7 @@ void main() {
|
||||
error: const BackendException('E-FDM-02', '이미 오늘 성운을 생성하셨습니다.'),
|
||||
);
|
||||
final results = await _pushed(tester, NebulaCreateScreen(repository: repo));
|
||||
await tester.enterText(find.byType(TextField), 'BTS_RM');
|
||||
await tester.enterText(find.byType(TextField), 'BTS RM');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -161,7 +161,7 @@ void main() {
|
||||
testWidgets('대표 변경 30일 대기 중이면 성운만 생겼다고 알리고 닫힌다(C-15)', (tester) async {
|
||||
final repo = _CreateRepo(primaryChanged: false);
|
||||
final results = await _pushed(tester, NebulaCreateScreen(repository: repo));
|
||||
await tester.enterText(find.byType(TextField), 'BTS_RM');
|
||||
await tester.enterText(find.byType(TextField), 'BTS RM');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
@@ -180,7 +180,7 @@ void main() {
|
||||
|
||||
testWidgets('오늘 이미 만들었으면 사유를 알리고 진행하지 않는다', (tester) async {
|
||||
await _pump(tester, const NebulaCreateScreen(alreadyCreatedToday: true));
|
||||
await tester.enterText(find.byType(TextField), 'BTS_RM');
|
||||
await tester.enterText(find.byType(TextField), 'BTS RM');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
@@ -121,6 +121,20 @@ class _PrimaryRepository extends SampleGalaxyRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/// 오늘 성운을 이미 만든 계정.
|
||||
class _CreatedTodayRepository extends SampleGalaxyRepository {
|
||||
@override
|
||||
Future<GalaxySnapshot> load() async {
|
||||
final s = await super.load();
|
||||
return GalaxySnapshot(
|
||||
planets: s.planets,
|
||||
myPop: s.myPop,
|
||||
memberships: s.memberships,
|
||||
nebulaCreatedToday: true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
group('GALAXY 모아보기 (§2.56 · §2.58) — 기본 행성 변경', () {
|
||||
Future<void> pumpHome(WidgetTester tester, GalaxyRepository repo) async {
|
||||
@@ -146,6 +160,24 @@ void main() {
|
||||
expect(repo.changes, ['newjeans']);
|
||||
});
|
||||
|
||||
testWidgets('그리드 변경 — 격자 ↔ 리스트(540:19580)', (tester) async {
|
||||
await pumpHome(tester, _PrimaryRepository());
|
||||
expect(find.text('NewJeans'), findsNothing); // 격자는 그림만
|
||||
await tester.tap(find.bySemanticsLabel('리스트 그리드'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('NewJeans'), findsOneWidget);
|
||||
await tester.tap(find.bySemanticsLabel('격자 그리드'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('NewJeans'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('오늘 성운을 만들었으면 성운 생성은 초과 안내 모달만(540:19592 · 543:19609)', (tester) async {
|
||||
await pumpHome(tester, _CreatedTodayRepository());
|
||||
await tester.tap(find.text('성운 생성'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('이미 오늘 성운을 생성하셨습니다.'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('30일 대기 중이면 서버 사유(E-FDM-04)를 알린다', (tester) async {
|
||||
final repo = _PrimaryRepository(
|
||||
error: const BackendException('E-FDM-04', '기본 행성은 변경 후 30일이 지나야 다시 바꿀 수 있습니다.'),
|
||||
@@ -465,7 +497,10 @@ void main() {
|
||||
await _pump(tester, const GalaxySearchScreen());
|
||||
await tester.enterText(find.byType(TextField), 'BTS');
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('멤버 12,840명'), findsOneWidget);
|
||||
// 결과 줄 — Figma `353:218091` 가입자 수 · 「FPI : n」 · 규모 칩.
|
||||
expect(find.text('12,840'), findsOneWidget);
|
||||
expect(find.text('FPI : 284,310'), findsOneWidget);
|
||||
expect(find.text('중형 팬덤'), findsOneWidget);
|
||||
|
||||
await tester.testTextInput.receiveAction(TextInputAction.search);
|
||||
await tester.pumpAndSettle();
|
||||
@@ -479,10 +514,47 @@ void main() {
|
||||
await _pump(tester, GalaxySearchScreen(onOpen: (p) => opened = p));
|
||||
await tester.enterText(find.byType(TextField), 'BTS');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.textContaining('멤버 12,840명'));
|
||||
await tester.tap(find.text('12,840'));
|
||||
expect(opened?.name, 'BTS');
|
||||
});
|
||||
|
||||
testWidgets('탭(행성 · 성운) · 필터(전체 · 가입자 수 · FPI) — 543:19672 · 543:19683', (tester) async {
|
||||
await _pump(tester, const GalaxySearchScreen());
|
||||
await tester.enterText(find.byType(TextField), 'e');
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('행성'), findsOneWidget);
|
||||
expect(find.text('성운'), findsOneWidget);
|
||||
// 가입자 수 순 — NewJeans(11,230) 가 SEVENTEEN(10,450) 보다 위.
|
||||
await tester.tap(find.text('가입자 수'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
tester.getTopLeft(find.text('NewJeans')).dy,
|
||||
lessThan(tester.getTopLeft(find.text('SEVENTEEN')).dy),
|
||||
);
|
||||
// 성운 탭 — 표본은 모두 정식 행성이라 비고, FPI 필터는 없다.
|
||||
await tester.tap(find.text('성운'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('NewJeans'), findsNothing);
|
||||
expect(find.text('FPI'), findsNothing);
|
||||
});
|
||||
|
||||
testWidgets('가입 → 가입 처리 후 가입중(543:19694)', (tester) async {
|
||||
final joined = <String>[];
|
||||
await _pump(
|
||||
tester,
|
||||
GalaxySearchScreen(
|
||||
repository: const SampleGalaxyRepository(),
|
||||
onJoin: (p) async => joined.add(p.id),
|
||||
),
|
||||
);
|
||||
await tester.enterText(find.byType(TextField), 'IVE');
|
||||
await tester.pumpAndSettle();
|
||||
await tester.tap(find.text('가입'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(joined, ['ive']);
|
||||
expect(find.text('가입중'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('없는 이름이면 사유를 알린다', (tester) async {
|
||||
await _pump(tester, const GalaxySearchScreen());
|
||||
await tester.enterText(find.byType(TextField), 'zzzz');
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'package:fancake/core/theme/app_theme.dart';
|
||||
import 'package:fancake/features/planet/lounge_post_screens.dart';
|
||||
import 'package:fancake/features/planet/moderation.dart';
|
||||
import 'package:fancake/features/planet/planet_detail_screen.dart';
|
||||
import 'package:fancake/features/planet/widgets/planet_detail_hero.dart';
|
||||
|
||||
import 'eclipse_stubs.dart';
|
||||
|
||||
@@ -588,6 +589,50 @@ void _fpiRankingTests() {
|
||||
expect(find.byType(FpiUserRankingScreen), findsOneWidget);
|
||||
expect(find.text('나의 BPM 랭킹'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('소속 행성 카드를 눌러도 사용자 랭킹으로 간다 (546:14629)', (tester) async {
|
||||
await pump(tester);
|
||||
// 맨 위 내 줄 카드는 「(나)」 없이 이름만 둔다.
|
||||
await tester.tap(find.text('BTS'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(FpiUserRankingScreen), findsOneWidget);
|
||||
});
|
||||
});
|
||||
|
||||
testWidgets('내가 만든 행성은 가입 버튼을 숨긴다 (544:19765)', (tester) async {
|
||||
Widget hero(bool owner) => MaterialApp(
|
||||
theme: buildAppTheme(),
|
||||
home: const Scaffold(body: SizedBox()),
|
||||
builder: (_, _) => SizedBox(
|
||||
height: 543,
|
||||
child: PlanetDetailHero(
|
||||
name: 'BTS',
|
||||
members: 850,
|
||||
totalFpi: 1220,
|
||||
joined: true,
|
||||
isOwner: owner,
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpWidget(hero(false));
|
||||
await tester.pump();
|
||||
expect(find.text('가입중'), findsOneWidget);
|
||||
expect(find.text('소형 팬덤'), findsOneWidget);
|
||||
await tester.pumpWidget(hero(true));
|
||||
await tester.pump();
|
||||
expect(find.text('가입중'), findsNothing);
|
||||
});
|
||||
|
||||
test('팬덤 규모 — 1,000명 미만 소형 · 50,000명 미만 중형 · 이상 대형 (544:19765)', () {
|
||||
expect(FandomSize.of(999), FandomSize.small);
|
||||
expect(FandomSize.of(1000), FandomSize.medium);
|
||||
expect(FandomSize.of(49999), FandomSize.medium);
|
||||
expect(FandomSize.of(50000), FandomSize.large);
|
||||
});
|
||||
|
||||
test('국기 — 국가 코드 → 국기, 미지정은 흰 깃발 (546:14713)', () {
|
||||
expect(flagOf('KR'), '🇰🇷');
|
||||
expect(flagOf('ZZ'), '🏳');
|
||||
});
|
||||
|
||||
group('사용자 지표 랭킹 화면 (Figma 546:14646)', () {
|
||||
|
||||
@@ -69,7 +69,7 @@ void main() {
|
||||
final repo = _AdRepo();
|
||||
await watchAd(tester, repo);
|
||||
expect(repo.claimed, ['imp-1']);
|
||||
expect(find.text('광고 추가 보상 +20 POP'), findsOneWidget);
|
||||
expect(find.text('광고 추가 보상 +20 기여 POP'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('불러오지 못하면 기본 보상만 받는다', (tester) async {
|
||||
@@ -193,8 +193,11 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test('완료 탭은 진행 완료와 보상 완료를 함께 받는다', () {
|
||||
expect(QuestTab.done.accepts(_stage(card, QuestStage.completed)), isTrue);
|
||||
// 명세 `518:88405` — 진행완료는 진행중 탭, 보상완료만 완료 탭.
|
||||
test('진행완료는 진행중 탭, 보상완료만 완료 탭이 받는다', () {
|
||||
expect(QuestTab.inProgress.accepts(_stage(card, QuestStage.completed)), isTrue);
|
||||
expect(QuestTab.inProgress.accepts(_stage(card, QuestStage.inProgress)), isTrue);
|
||||
expect(QuestTab.done.accepts(_stage(card, QuestStage.completed)), isFalse);
|
||||
expect(QuestTab.done.accepts(_stage(card, QuestStage.rewarded)), isTrue);
|
||||
expect(QuestTab.done.accepts(_stage(card, QuestStage.inProgress)), isFalse);
|
||||
});
|
||||
@@ -328,10 +331,10 @@ void main() {
|
||||
// 시청 후 대기(482:15084)는 지급이 끝나면 걷힌다.
|
||||
expect(find.byType(QuestAdWarpScreen), findsNothing);
|
||||
expect(find.byType(QuestRewardScreen), findsOneWidget);
|
||||
// 별첨 B **B-28** 이 배수형(×2/×3)을 철회했다. 기본 보상과 광고 추가 보상은
|
||||
// 별개 원장 행이고, 화면은 **서버가 돌려준 지급액만** 띄운다(`fnAdReward.rewarded`).
|
||||
expect(find.text('+10 받았어요!'), findsOneWidget);
|
||||
expect(find.text('광고 추가 보상 +10 POP'), findsOneWidget);
|
||||
// 기본 보상과 광고 추가 보상은 별개 원장 행이고, 화면은 **서버가 돌려준 지급액만** 띄운다
|
||||
// (`fnAdReward.rewarded`). 운영 Quest 는 명세 `518:88685` 대로 둘의 합계(× 배수)를 크게 보인다.
|
||||
expect(find.text('+20 받았어요!'), findsOneWidget);
|
||||
expect(find.text('광고 추가 보상 +10 기여 POP'), findsOneWidget);
|
||||
});
|
||||
|
||||
testWidgets('스트리밍은 무보상 참여로 열려 있고 보상 · 광고 화면 없이 참여만 알린다(C-04)', (tester) async {
|
||||
@@ -530,6 +533,46 @@ void main() {
|
||||
}
|
||||
}
|
||||
});
|
||||
group('Figma 설명 프레임 대조 (2026-10-06)', () {
|
||||
QuestCard ugc({int participants = 0, int? capacity, QuestStage stage = QuestStage.notStarted}) =>
|
||||
QuestCard(
|
||||
id: 'u', title: 't', categoryName: 'c', author: QuestAuthor.user,
|
||||
stage: stage, goal: 1, progress: 0, rewardPop: 10,
|
||||
participants: participants, capacity: capacity,
|
||||
);
|
||||
|
||||
// 명세 `523:18176` 퀘스트 종료 시점 1 — 참여 인원 충족 시 종료.
|
||||
test('사용자 퀘스트는 모집 인원이 차면 마감이다', () {
|
||||
expect(questFull(ugc(participants: 5, capacity: 5)), isTrue);
|
||||
expect(questFull(ugc(participants: 4, capacity: 5)), isFalse);
|
||||
expect(questFull(ugc(participants: 3)), isFalse);
|
||||
});
|
||||
|
||||
// 명세 `518:88395` — 카테고리 값은 등록된 분류(건강 · 커뮤니티 …)다. 활동명(걷기)이 아니다.
|
||||
test('카드 카테고리는 활동이 아니라 분류 이름이다', () {
|
||||
expect(QuestType.steps.category, '건강');
|
||||
expect(QuestType.community.category, '커뮤니티');
|
||||
expect(QuestType.vote.category, '행성 활동');
|
||||
});
|
||||
|
||||
// 명세 `518:88685` — 광고 시청 POP = 보상 POP × 배수. 운영 Quest 는 합계를 크게 보인다.
|
||||
testWidgets('운영 퀘스트는 광고를 보면 기본 + 증분 합계를 띄운다', (tester) async {
|
||||
const card = QuestCard(
|
||||
id: 'a', title: 't', categoryName: 'c', author: QuestAuthor.admin,
|
||||
stage: QuestStage.completed, goal: 1, progress: 1, rewardPop: 20, participants: 0,
|
||||
);
|
||||
await pumpWide(
|
||||
tester,
|
||||
const QuestRewardScreen(
|
||||
detail: QuestDetail(card: card, imageLabel: '', description: ''),
|
||||
reward: QuestReward(rewardedPop: 20, balanceAfter: 0),
|
||||
adBonusPop: 20,
|
||||
),
|
||||
);
|
||||
expect(find.text('+40 받았어요!'), findsOneWidget);
|
||||
expect(find.text('광고 추가 보상 +20 기여 POP'), findsOneWidget);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// 지갑이 서버 값으로 바뀐 표본 — 생성 예치 · 수수료 뒤 헤더가 다시 맞는가.
|
||||
|
||||
@@ -14,6 +14,9 @@ import 'package:fancake/features/home/widgets/quest_row.dart';
|
||||
import 'package:fancake/features/inside/inside_detail_screen.dart';
|
||||
import 'package:fancake/features/quest/widgets/quest_card_tile.dart' show QuestIconBox;
|
||||
|
||||
import 'package:fancake/core/router/app_router.dart' show scrollTabToTop;
|
||||
import 'package:fancake/features/notification/notification_screen.dart';
|
||||
import 'package:fancake/features/home/nebula_create_screen.dart' show isValidNebulaName;
|
||||
import 'eclipse_stubs.dart';
|
||||
|
||||
class _LiveGrowthRepo extends SampleHomeRepository {
|
||||
@@ -379,4 +382,59 @@ void main() {
|
||||
await tester.pumpAndSettle();
|
||||
expect(opened, ['https://example.com/a']);
|
||||
});
|
||||
|
||||
group('설명 프레임 대조(홈 일반)', () {
|
||||
Future<bool> badgeShown(WidgetTester tester, List<AppNotification> items) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: buildAppTheme(),
|
||||
home: Scaffold(
|
||||
body: HomeHeader(
|
||||
key: UniqueKey(),
|
||||
pop: 0,
|
||||
notifications: SampleNotificationRepository(items: items),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.pumpAndSettle();
|
||||
return tester.widget<Badge>(find.byKey(const ValueKey('home-bell-badge'))).isLabelVisible;
|
||||
}
|
||||
|
||||
AppNotification n(bool read) => AppNotification(
|
||||
id: 'n$read', kind: NotificationKind.quest, title: 't', at: DateTime(2026), read: read,
|
||||
);
|
||||
|
||||
testWidgets('2097:16385 — 안 읽은 알림이 있으면 알림 아이콘에 배지', (tester) async {
|
||||
expect(await badgeShown(tester, [n(false), n(true)]), isTrue);
|
||||
expect(await badgeShown(tester, [n(true)]), isFalse);
|
||||
});
|
||||
|
||||
testWidgets('2097:16427 — 열린 탭을 다시 누르면 루트 화면이 맨 위로', (tester) async {
|
||||
final key = GlobalKey<NavigatorState>();
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
navigatorKey: key,
|
||||
home: Scaffold(
|
||||
body: ListView(children: [for (var i = 0; i < 50; i++) SizedBox(height: 100, child: Text('$i'))]),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.drag(find.byType(ListView), const Offset(0, -1500));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('0'), findsNothing);
|
||||
scrollTabToTop(key);
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
});
|
||||
|
||||
test('516:87397 — 성운명 규칙은 서버와 같다', () {
|
||||
for (final ok in ['방탄', 'BTS Army 7', '가' * 20]) {
|
||||
expect(isValidNebulaName(ok), isTrue, reason: ok);
|
||||
}
|
||||
for (final bad in ['가', '가' * 21, ' 방탄', '방탄 ', '방 탄', '방탄!', '방탄😀']) {
|
||||
expect(isValidNebulaName(bad), isFalse, reason: bad);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -110,6 +110,74 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('프로필 국가 — 사본 국가 리스트 모달(178:23489) 대로 국가명 · 단수 선택 · 「선택」 후 적용', (
|
||||
tester,
|
||||
) async {
|
||||
final (auth, repo) = await boot(tester, needs: true);
|
||||
await auth.signIn(SocialProvider.google);
|
||||
await tester.pumpAndSettle();
|
||||
for (final label in [
|
||||
'서비스 이용약관 (필수)',
|
||||
'개인정보 수집·이용 및 처리방침 동의 (필수)',
|
||||
'위치기반 서비스 이용약관 (필수)',
|
||||
'만 14세 이상입니다. (필수)',
|
||||
]) {
|
||||
await tester.tap(find.text(label));
|
||||
}
|
||||
await tester.pump();
|
||||
await tester.tap(find.text('완료'));
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
await tester.tap(find.text('국가/지역').first);
|
||||
await tester.pumpAndSettle();
|
||||
await tester.scrollUntilVisible(
|
||||
find.text('대한민국'),
|
||||
300,
|
||||
scrollable: find.byType(Scrollable).last,
|
||||
);
|
||||
await tester.tap(find.text('대한민국'));
|
||||
await tester.pump();
|
||||
await tester.tap(find.widgetWithText(FilledButton, '선택'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('대한민국'), findsOneWidget);
|
||||
|
||||
await tester.enterText(find.byType(TextField).first, '우주팬');
|
||||
await tester.pump();
|
||||
await tester.tap(find.text('다음'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(repo.profile?.country, 'KR');
|
||||
});
|
||||
|
||||
testWidgets('프로필 뒤로가기(511:86825) — 약관으로 돌아가 동의가 체크된 채 보이고 다시 기록하지 않는다', (
|
||||
tester,
|
||||
) async {
|
||||
final (auth, repo) = await boot(tester, needs: true);
|
||||
await auth.signIn(SocialProvider.google);
|
||||
await tester.pumpAndSettle();
|
||||
for (final label in [
|
||||
'서비스 이용약관 (필수)',
|
||||
'개인정보 수집·이용 및 처리방침 동의 (필수)',
|
||||
'위치기반 서비스 이용약관 (필수)',
|
||||
'만 14세 이상입니다. (필수)',
|
||||
]) {
|
||||
await tester.tap(find.text(label));
|
||||
}
|
||||
await tester.pump();
|
||||
await tester.tap(find.text('완료'));
|
||||
await tester.pumpAndSettle();
|
||||
final first = repo.agreed;
|
||||
|
||||
await tester.tap(find.byType(BackButton));
|
||||
await tester.pumpAndSettle();
|
||||
// 필수 4항이 이미 체크돼 있어 「완료」가 바로 켜져 있다.
|
||||
final done = find.widgetWithText(FilledButton, '완료');
|
||||
expect(tester.widget<FilledButton>(done).onPressed, isNotNull);
|
||||
await tester.tap(done);
|
||||
await tester.pumpAndSettle();
|
||||
expect(identical(repo.agreed, first), isTrue);
|
||||
expect(find.byType(BackButton), findsOneWidget); // ③ 프로필로 돌아왔다.
|
||||
});
|
||||
|
||||
testWidgets('가입 모드에서 받은 약관은 다시 묻지 않고 기록만 한다', (tester) async {
|
||||
final (auth, repo) = await boot(tester, needs: true);
|
||||
auth.pendingConsent = {
|
||||
|
||||
@@ -29,7 +29,10 @@ void main() {
|
||||
await tester.pumpWidget(MaterialApp(theme: buildAppTheme(), home: Scaffold(body: widget)));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.textContaining('0 POP', findRichText: true), findsNothing);
|
||||
expect(find.textContaining('님의', findRichText: true), findsNothing);
|
||||
// HOME 히어로의 「{닉네임} 님의」는 로그인 사용자 인사 줄이라 늘 있다(설명 프레임 `2097:16391`).
|
||||
if (widget is PlanetGrowthCard) {
|
||||
expect(find.textContaining('님의', findRichText: true), findsNothing);
|
||||
}
|
||||
expect(find.text('함께 키워가는 팬덤 행성'), findsOneWidget);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user