Files

309 lines
8.5 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
@Tags(['design'])
library;
import 'package:fancake/core/data/repositories.dart';
import 'package:fancake/core/router/app_router.dart';
import 'package:fancake/core/theme/app_theme.dart';
import 'package:fancake/features/auth/auth_repository.dart';
import 'package:fancake/features/eclipse/eclipse_data.dart';
import 'package:fancake/features/galaxy/galaxy_search_screen.dart';
import 'package:fancake/features/planet/fpi_ranking_screen.dart';
import 'package:fancake/features/planet/lounge_post_screens.dart';
import 'package:fancake/features/planet/moderation.dart';
import 'package:fancake/features/planet/planet_data.dart';
import 'package:fancake/features/planet/planet_detail_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import '../eclipse_stubs.dart';
import 'design_match_test.dart' as base;
/// 디자인 일치 2단계 **그룹 B**(F2 갤럭시 · F3 행성/성운 상세) 렌더.
///
/// 공유 하네스([base.main])를 그대로 돌리되 shots 만 이 그룹 것으로 바꾼다.
/// 표본은 Figma 사본 문구와 같게 여기서 만든다(공유 표본 저장소는 건드리지 않는다).
///
/// 실행: `DESIGN_MATCH_OUT=<폴더> fvm flutter test --tags design test/design_match/b_test.dart`
void main() {
base.shots
..clear()
..addAll(_shots);
base.main();
}
Future<void> _settle(WidgetTester t) async {
for (var i = 0; i < 6; i++) {
await t.pump(const Duration(milliseconds: 300));
}
}
Future<void> _tap(WidgetTester t, Finder f) async {
await t.tap(f.first, warnIfMissed: false);
await _settle(t);
}
Future<void> _overlay(
WidgetTester t,
void Function(BuildContext c) open,
) async {
open(t.element(find.byType(Scaffold).last));
await _settle(t);
}
final _now = DateTime.now();
const _photo = 'assets/figma/lounge-post-sample.png';
LoungePost _post(
String author,
Duration ago,
String text, {
int likes = 8,
int comments = 24,
List<String> images = const [],
String? photo,
Duration? video,
}) => LoungePost(
id: author,
authorName: author,
createdAt: _now.subtract(ago),
title: '',
body: text,
likes: likes,
comments: comments,
images: images,
authorPhoto: photo,
videoDuration: video,
);
/// F3-05 `244:22509` — 첫 댓글 전 글.
final _hongPost = _post(
'BTS_Hong',
Duration.zero,
'안녕하세요! BTS 팬이에요!',
likes: 0,
comments: 0,
images: const [_photo],
photo: 'assets/figma/avatar-hong.png',
video: const Duration(seconds: 36),
);
/// F3-07 `252:163306` — 사진 세 장 글.
final _ilaPost = _post(
'ILA_WITH',
const Duration(days: 3),
'여러분 지금 미국 컴백 무대 보셨나요?\n사진 공유해드릴게요 모두 온라인 직관하세요',
likes: 8,
comments: 5,
images: const [_photo, _photo, _photo],
);
FpiScore _score(FpiMetric m, int v, int rank, int trend) =>
FpiScore(metric: m, value: v, rank: rank, trend: trend, myTopPercent: 1);
/// 시안 수치 그대로의 행성 · 성운 상세.
class _FigmaPlanet extends SamplePlanetRepository {
const _FigmaPlanet();
@override
Future<PlanetDetail> load({required bool nebula}) async => nebula
? PlanetDetail(
fandomId: 'bts-rm',
name: 'BTS_RM',
isNebula: true,
stage: 0,
totalFpi: 0,
members: 1,
ownerName: 'BTS_Hong',
ownerPhoto: 'assets/figma/avatar-hong.png',
scores: const [],
posts: const [],
)
: PlanetDetail(
fandomId: 'bts',
name: 'BTS',
isNebula: false,
totalFpi: 1220,
members: 850,
ownerName: 'BTS_Maker',
ownerPhoto: 'assets/figma/avatar-maker.png',
scores: [
_score(FpiMetric.bpm, 34200, 2, 1),
_score(FpiMetric.health, 1180000, 4, -1),
_score(FpiMetric.referral, 34200, 3, 0),
_score(FpiMetric.contribution, 450100, 2, 2),
_score(FpiMetric.community, 1000, 4, -2),
],
posts: [
_post(
'arrrmy_',
const Duration(minutes: 3),
'I love BTS sooooo much 😭😭😭',
),
_post(
'AR_NNJO',
const Duration(hours: 3),
'NAMJOON so handsome isn’t it???',
images: const [_photo],
),
_ilaPost,
],
);
@override
Future<List<LoungePost>> morePosts({
required int offset,
int limit = 5,
}) async => const [];
@override
Future<FpiRanking> planetRanking({
required FpiMetric metric,
int limit = 30,
}) async => FpiRanking(
mine: const FpiRankRow(
rank: 24,
id: 'bts',
name: 'BTS',
value: 34200,
change: 12,
isMine: true,
),
rows: _rows(const [
(1, 'Bigbnag', 782200, 1),
(2, 'NewJeans', 703200, 0),
(3, 'Blackpink', 689700, 1),
(5, 'Twice', 531100, -1),
(6, 'ITZY', 527800, 2),
(7, 'Aespa', 422400, 3),
(8, 'Seventeen', 329600, 8),
(9, 'Eighteen', 311200, -1),
(10, 'Nineteen', 134500, 1),
]),
);
@override
Future<FpiRanking> userRanking({
required FpiMetric metric,
required String fandomId,
int limit = 30,
}) async => FpiRanking(
mine: const FpiRankRow(
rank: 82,
id: 'me',
name: 'BTS_Hong',
value: 3,
change: 1,
),
rows: _rows(const [
(1, 'GLAS_SMILE', 3000, 0),
(2, 'Suyom_mo', 2600, 0),
(3, 'Bool_huuu', 1400, 0),
(4, 'Wachooo', 1200, 1),
(5, 'Jeans_Bewn', 1200, 0),
(6, 'pinkyy', 1100, 1),
(7, 'T_T', 1000, -1),
(8, 'Yogi_ITZY', 98, 2),
]),
);
}
List<FpiRankRow> _rows(List<(int, String, int, int)> t) => [
for (final (rank, name, value, change) in t)
FpiRankRow(rank: rank, id: name, name: name, value: value, change: change),
];
Widget _detail({bool nebula = false}) => PlanetDetailScreen(
nebula: nebula,
repository: const _FigmaPlanet(),
eclipse: const NoEclipseRepository(),
);
const _report = ModerationTarget(
authorName: 'BTS_Hong',
title: '공방 신청 꿀팁 공유합니다.',
);
/// 이클립스가 없는 표본 저장소. 탭 화면은 공유 하네스가 저장소를 직접 만들어서
/// 바꿀 수 없으므로, 탭 셸을 통째로 한 번 더 띄운다(하단 탭까지 그려진다).
class _NoEclipseRepos extends Repositories {
_NoEclipseRepos() : super(live: false);
@override
EclipseRepository get eclipse => const NoEclipseRepository();
}
Widget _tab(String path) {
final router = buildRouter(
AuthRepository()..signInWithMockSession(),
repositories: _NoEclipseRepos(),
)..go(path);
return MaterialApp.router(
theme: buildAppTheme(),
debugShowCheckedModeBanner: false,
routerConfig: router,
);
}
final _shots = <base.Shot>[
// F2 갤럭시
base.Shot('F2-01', build: (_) async => _tab('/galaxy')),
base.Shot(
'F2-02',
build: (r) async => GalaxySearchScreen(repository: r.galaxy),
),
// F3 행성/성운 상세
base.Shot('F3-01', h: 1042, build: (_) async => _detail(nebula: true)),
base.Shot(
'F3-02',
build: (_) async => const ReportScreen(
target: ModerationTarget(authorName: 'BTS_Hong', title: 'BTS_RM'),
),
),
base.Shot(
'F3-03',
build: (_) async => _detail(nebula: true),
after: (t) => _overlay(
t,
(c) => confirmBlock(c, 'BTS_Hong', message: '이 성운을 차단할까요?'),
),
),
base.Shot('F3-04', h: 1243, build: (_) async => _detail()),
base.Shot('F3-05', build: (_) async => LoungePostScreen(post: _hongPost)),
base.Shot('F3-06', build: (_) async => const ReportScreen(target: _report)),
base.Shot(
'F3-07',
build: (_) async => LoungePostScreen(post: _ilaPost),
after: (t) => _overlay(t, (c) => confirmBlock(c, 'ILA_WITH')),
),
base.Shot('F3-09', build: (_) async => const LoungeComposeScreen()),
base.Shot(
'F3-10',
build: (_) async => const FpiRankingScreen(
metric: FpiMetric.bpm,
repository: _FigmaPlanet(),
),
),
base.Shot(
'F3-11',
build: (_) async => const FpiUserRankingScreen(
metric: FpiMetric.bpm,
fandomId: 'bts',
planetName: 'BTS',
repository: _FigmaPlanet(),
),
),
base.Shot(
'F3-12',
build: (_) async => _detail(),
after: (t) async {
await _tap(t, find.text('팬덤 라운지'));
await _tap(
t,
find.image(const AssetImage('assets/figma/icon-post-more.png')),
);
},
),
base.Shot('F3-13', build: (_) async => const ReportScreen(target: _report)),
];