// 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(card).color, AppColors.transparent); expect( tester .widgetList( find.descendant(of: card, matching: find.byType(Container)), ) .map((container) => container.decoration) .whereType() .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( 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(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( 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.navSelected); 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(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(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 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 _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, ), ), ), ), ), ); }