// 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, ), onTap: () => taps++, ); final card = find.byKey(const Key('home-feed-card-anime-card')); final container = tester.widget(card); final decoration = container.decoration! as BoxDecoration; expect(decoration.color, AppColors.contentCard); expect(decoration.boxShadow, isNull); expect( decoration.borderRadius, BorderRadius.circular(AppDimens.homeCardRadius), ); expect((decoration.border! as Border).top.width, 1); expect((decoration.border! as Border).top.color, AppColors.contentBorder); final cover = find.byKey(const Key('home-feed-cover-anime-card')); final coverSize = tester.getSize(cover); expect(coverSize.height / coverSize.width, closeTo(6 / 5, 0.02)); expect( find.byKey(const Key('home-feed-badge-anime-anime-card')), findsOneWidget, ); 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, startsWith('44.')); expect( tester .widget(find.byKey(const Key('home-feed-title-anime-card'))) .maxLines, 2, ); expect(find.byKey(const Key('home-feed-tag-anime-card-0')), findsOneWidget); expect(find.byKey(const Key('home-feed-tag-anime-card-1')), findsOneWidget); expect(find.text('Romance'), findsOneWidget); expect(find.text('Urban'), findsOneWidget); await tester.tap(card); expect(taps, 1); }); testWidgets('should_choose_anime_new_and_hot_badges_from_real_data', ( tester, ) async { final now = DateTime(2026, 10, 22, 12); 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: 'anime', title: 'Anime', dramaType: 'ANIME'), _drama( id: 'new', title: 'New', createdAt: now.subtract(const Duration(days: 2)), ), _drama(id: 'hot', title: 'Hot', isHot: true), ]) SizedBox( width: 130, height: 240, child: HomeFeedCard(drama: drama, onTap: () {}, now: now), ), ], ), ), ), ); await tester.pumpAndSettle(); expect( find.byKey(const Key('home-feed-badge-anime-anime')), findsOneWidget, ); expect( find.byKey(const Key('home-feed-badge-newRelease-new')), findsOneWidget, ); expect(find.byKey(const Key('home-feed-badge-hot-hot')), findsOneWidget); }); } Drama _drama({ required String id, required String title, String dramaType = 'LIVE', int viewCount = 0, bool isHot = false, DateTime? createdAt, }) { return Drama( id: id, title: title, synopsis: 'synopsis', posterUrl: '/files/$id.jpg', genre: 'Romance', category: 'Urban', viewCount: viewCount, isHot: isHot, dramaType: dramaType, createdAt: createdAt, ); } 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: 240, child: HomeFeedCard( drama: drama, onTap: onTap, now: DateTime(2026, 10, 22, 12), ), ), ), ), ), ); }