import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/l10n/app_localizations.dart'; import 'package:fruitshorts/pages/discover/widgets/cover_carousel.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); List items(int count) => [ for (var index = 0; index < count; index++) CoverItem( title: 'Banner $index', subtitle: 'Subtitle $index', image: '/files/banner-$index.png', onOpen: _noop, ), ]; testWidgets('should_turn_cube_and_keep_title_on_poster_when_carousel_pages', ( tester, ) async { await tester.pumpWidget( _localizedApp( CoverCarousel( items: [ for (final title in ['The Signal', 'City Lights', 'Vengeance']) CoverItem( title: title, subtitle: 'Mock', image: '/files/poster.png', onOpen: _noop, ), ], ), ), ); await tester.pump(); expect(find.text('The Signal'), findsOneWidget); expect(find.text('Mock'), findsOneWidget); final box = tester.getRect(find.byType(CoverCarousel)); final gesture = await tester.startGesture( Offset(box.right - 40, box.center.dy), ); await gesture.moveBy(const Offset(-500, 0)); await tester.pump(); final turned = tester .widgetList(find.byType(Transform)) .any((transform) => (transform.transform.entry(0, 0) - 1).abs() > 0.15); expect(turned, isTrue); await gesture.moveBy(const Offset(-200, 0)); await gesture.up(); await tester.pump(); await tester.pump(const Duration(milliseconds: 450)); expect(find.text('City Lights'), findsOneWidget); expect(tester.takeException(), isNull); }); testWidgets('should_auto_advance_and_show_dots_when_multiple_items_exist', ( tester, ) async { await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(3)))); await tester.pump(); expect(find.text('Banner 0'), findsOneWidget); expect(find.byKey(const Key('carousel-dot-0')), findsOneWidget); expect(find.byKey(const Key('carousel-dot-1')), findsOneWidget); expect(find.byKey(const Key('carousel-dot-2')), findsOneWidget); await tester.pump(const Duration(milliseconds: 4500)); await tester.pump(const Duration(milliseconds: 500)); expect(find.text('Banner 1'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }); testWidgets('should_not_schedule_auto_advance_when_only_one_item_exists', ( tester, ) async { await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(1)))); await tester.pump(const Duration(seconds: 12)); expect(find.text('Banner 0'), findsOneWidget); expect(find.byKey(const Key('carousel-dot-0')), findsOneWidget); expect(find.byKey(const Key('carousel-dot-1')), findsNothing); }); testWidgets('should_pause_auto_advance_while_pointer_is_down', ( tester, ) async { await tester.pumpWidget(_localizedApp(CoverCarousel(items: items(3)))); await tester.pump(); final box = tester.getRect(find.byType(CoverCarousel)); final gesture = await tester.startGesture(box.center); await tester.pump(const Duration(seconds: 6)); expect(find.text('Banner 0'), findsOneWidget); await gesture.up(); await tester.pump(); await tester.pump(const Duration(milliseconds: 4500)); await tester.pump(const Duration(milliseconds: 500)); expect(find.text('Banner 1'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }); testWidgets('should_pause_when_inactive_and_resume_when_active_again', ( tester, ) async { final active = ValueNotifier(false); await tester.pumpWidget( _localizedApp( ValueListenableBuilder( valueListenable: active, builder: (context, enabled, _) => CoverCarousel(items: items(2), active: enabled), ), ), ); await tester.pump(const Duration(seconds: 6)); expect(find.text('Banner 0'), findsOneWidget); active.value = true; await tester.pump(); await tester.pump(const Duration(milliseconds: 4500)); await tester.pump(const Duration(milliseconds: 500)); expect(find.text('Banner 1'), findsOneWidget); await tester.pumpWidget(const SizedBox.shrink()); }); testWidgets('should_show_icon_fallback_when_banner_image_is_empty', ( tester, ) async { await tester.pumpWidget( _localizedApp( CoverCarousel( items: const [ CoverItem( title: 'Broken image', subtitle: '', image: '', onOpen: _noop, ), ], ), ), ); await tester.pump(); expect(find.byKey(const Key('carousel-image-fallback')), findsOneWidget); }); testWidgets( 'should_keep_existing_open_callback_when_active_poster_is_tapped', (tester) async { var opened = 0; await tester.pumpWidget( _localizedApp( CoverCarousel( items: [ CoverItem( title: 'Tap me', subtitle: '', image: '/files/banner.png', onOpen: () => opened++, ), ...items(1), ], ), ), ); await tester.pump(); await tester.tap(find.text('Tap me')); expect(opened, 1); await tester.pumpWidget(const SizedBox.shrink()); }, ); } void _noop() {} Widget _localizedApp(Widget child) => MaterialApp( locale: const Locale('en'), localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, home: Scaffold(body: child), );