Files
ReelShort/test/home/home_card_style_test.dart
Zhou Weidong 1d4ab5e0e6 test: 按新 UI 基线重写过期用例
覆盖 155 条失败与 4 处编译错误:入口改走推荐流 tab、弹框换 AppGlowDialog、
rail 尺寸与底部锚定、子页标题字重 w400、底栏选中品牌红、收藏文案改收藏短剧。
全量 flutter test 775 通过。
2026-10-28 18:48:03 +08:00

223 lines
6.8 KiB
Dart

// Author: fruit.com.cn
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/core/data/models/drama.dart';
import 'package:fruitshorts/core/theme/app_colors.dart';
import 'package:fruitshorts/core/theme/app_dimens.dart';
import 'package:fruitshorts/core/theme/app_theme.dart';
import 'package:fruitshorts/l10n/app_localizations.dart';
import 'package:fruitshorts/pages/home/widgets/home_feed_card.dart';
void main() {
testWidgets('should_render_grid_card_cover_badge_views_title_and_tags', (
tester,
) async {
var taps = 0;
await _pumpCard(
tester,
drama: _drama(
id: 'anime-card',
title: 'A very long home grid drama title that must wrap',
dramaType: 'ANIME',
viewCount: 444500,
tag: '漫剧',
tagLocales: const {'zh': '漫剧', 'en': 'Anime', 'id': 'Anime'},
),
onTap: () => taps++,
);
final card = find.byKey(const Key('home-feed-card-anime-card'));
expect(tester.widget<Material>(card).color, AppColors.transparent);
expect(
tester
.widgetList<Container>(
find.descendant(of: card, matching: find.byType(Container)),
)
.map((container) => container.decoration)
.whereType<BoxDecoration>()
.every((decoration) => decoration.border == null),
isTrue,
);
final cover = find.byKey(const Key('home-feed-cover-anime-card'));
final coverSize = tester.getSize(cover);
expect(
coverSize.height / coverSize.width,
closeTo(1 / AppDimens.cardCoverAspectRatio, 0.02),
);
final coverClip = tester.widget<ClipRRect>(
find.byKey(const Key('home-feed-cover-clip-anime-card')),
);
expect(
coverClip.borderRadius,
BorderRadius.circular(AppDimens.cardCoverRadius),
);
final badge = find.byKey(
const Key('drama-cover-badge-ribbon-anime-card-tag'),
);
expect(badge, findsOneWidget);
expect(
tester
.widget<Text>(find.descendant(of: badge, matching: find.byType(Text)))
.style
?.fontSize,
AppDimens.cardBadgeFont,
);
expect(
tester.getTopRight(badge).dx,
closeTo(tester.getTopRight(cover).dx, 1),
);
expect(
tester.getTopRight(badge).dy,
closeTo(tester.getTopRight(cover).dy, 1),
);
expect(find.text('Anime'), findsOneWidget);
expect(find.byKey(const Key('home-feed-views-anime-card')), findsOneWidget);
final views = find.byKey(const Key('home-feed-views-anime-card'));
final viewsText = tester.widget<Text>(
find.descendant(of: views, matching: find.byType(Text)),
);
expect(viewsText.data, '44.5w');
expect(viewsText.style?.fontSize, AppDimens.cardPlayCountFont);
expect(viewsText.style?.fontWeight, FontWeight.w400);
expect(viewsText.style?.color, AppColors.textPrimary);
expect(
find.descendant(
of: find.byKey(const Key('home-feed-cover-clip-anime-card')),
matching: views,
),
findsOneWidget,
);
expect(
tester.getTopRight(cover).dx - tester.getTopRight(views).dx,
AppDimens.cardPlayCountRight,
);
expect(
tester.getBottomLeft(cover).dy - tester.getBottomLeft(views).dy,
AppDimens.cardPlayCountBottom,
);
expect(
find.descendant(of: views, matching: find.byType(Container)),
findsNothing,
);
expect(
find.descendant(
of: views,
matching: find.byIcon(Icons.local_fire_department_rounded),
),
findsOneWidget,
);
final titleFinder = find.byKey(
const Key('home-feed-title-anime-card'),
);
final title = tester.widget<Text>(titleFinder);
expect(title.maxLines, 2);
expect(title.style?.fontSize, AppDimens.cardTitleFont);
expect(title.style?.fontWeight, FontWeight.w500);
expect(title.style?.height, AppDimens.cardTitleLineHeight);
final tagsFinder = find.byKey(const Key('home-feed-tags-anime-card'));
final tags = tester.widget<Text>(tagsFinder);
expect(tags.data, 'Romance | Urban');
expect(tags.style?.fontSize, AppDimens.cardTagFont);
expect(tags.style?.color, AppColors.textTertiary);
expect(tester.getTopLeft(titleFinder).dx, tester.getTopLeft(cover).dx);
expect(tester.getTopLeft(tagsFinder).dx, tester.getTopLeft(cover).dx);
await tester.tap(card);
expect(taps, 1);
});
testWidgets('should_show_cover_badge_from_tag_locale', (tester) async {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.dark(),
locale: const Locale('en'),
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: Scaffold(
body: Row(
children: [
for (final drama in [
_drama(
id: 'tagged',
title: 'Tagged',
tag: '新剧',
tagLocales: const {'zh': '新剧', 'en': 'New', 'id': 'Baru'},
),
_drama(id: 'plain', title: 'Plain'),
])
SizedBox(
width: 130,
height: 240,
child: HomeFeedCard(drama: drama, onTap: () {}),
),
],
),
),
),
);
await tester.pumpAndSettle();
final badge = find.byKey(const Key('drama-cover-badge-ribbon-tagged-tag'));
expect(badge, findsOneWidget);
expect(find.text('New'), findsOneWidget);
expect(find.byKey(const Key('drama-cover-badge-ribbon-plain-tag')), findsNothing);
});
}
Drama _drama({
required String id,
required String title,
String dramaType = 'LIVE',
int viewCount = 0,
bool isHot = false,
DateTime? createdAt,
String tag = '',
Map<String, String> tagLocales = const {},
}) {
return Drama(
id: id,
title: title,
synopsis: 'synopsis',
posterUrl: '/files/$id.jpg',
genre: 'Romance',
category: 'Urban',
viewCount: viewCount,
isHot: isHot,
dramaType: dramaType,
createdAt: createdAt,
tag: tag,
tagLocales: tagLocales,
);
}
Future<void> _pumpCard(
WidgetTester tester, {
required Drama drama,
required VoidCallback onTap,
}) {
return tester.pumpWidget(
MaterialApp(
theme: AppTheme.dark(),
locale: const Locale('en'),
supportedLocales: AppLocalizations.supportedLocales,
localizationsDelegates: AppLocalizations.localizationsDelegates,
home: Scaffold(
body: Center(
child: SizedBox(
width: 130,
height:
130 / AppDimens.cardCoverAspectRatio +
AppDimens.homeCardBodyExtent,
child: HomeFeedCard(
drama: drama,
onTap: onTap,
),
),
),
),
),
);
}