// Author: fruit.com.cn import 'dart:async'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart'; import 'package:fruitshorts/app.dart'; import 'package:fruitshorts/core/config/app_config.dart'; import 'package:fruitshorts/core/data/models/drama.dart'; import 'package:fruitshorts/core/data/models/home_feed.dart'; import 'package:fruitshorts/core/data/repositories/catalog_repository.dart'; import 'package:fruitshorts/core/data/repositories/favorite_repository.dart'; import 'package:fruitshorts/core/data/repositories/playback_repository.dart'; import 'package:fruitshorts/core/data/repositories/watch_history_repository.dart'; import 'package:fruitshorts/core/data/services/catalog_controller.dart'; import 'package:fruitshorts/core/theme/app_theme.dart'; import 'package:fruitshorts/l10n/app_localizations.dart'; import 'package:fruitshorts/pages/home/home_view.dart'; import '../support/fake_catalog.dart'; import '../support/fake_category.dart'; import '../support/fake_haptics.dart'; import '../support/fake_interaction_repositories.dart'; import '../support/fake_notice_repository.dart'; import '../support/widget_player.dart'; void main() { setUp(() { SharedPreferencesAsyncPlatform.instance = InMemorySharedPreferencesAsync.empty(); AppConfig.clearRuntimeBaseUrl(); AppConfig.ready = Future.value(); }); tearDown(() { debugDefaultTargetPlatformOverride = null; AppConfig.clearRuntimeBaseUrl(); AppConfig.ready = Future.value(); }); testWidgets('should_show_platform_startup_image_before_catalog_settles', ( tester, ) async { final controller = CatalogController(_EmptyCatalogRepository()) ..loading = true ..settled = false; addTearDown(controller.dispose); for (final platform in [TargetPlatform.android, TargetPlatform.iOS]) { debugDefaultTargetPlatformOverride = platform; await _pumpHomePage(tester, controller); final image = tester.widget( find.byKey(const Key('startup-splash')), ); final expectedAsset = platform == TargetPlatform.android ? 'assets/icon/splash_logo_android12.png' : 'assets/icon/splash_logo.png'; final expectedSize = platform == TargetPlatform.android ? 288.0 : 384.0; expect( image.image, isA().having( (asset) => asset.assetName, 'assetName', expectedAsset, ), ); expect( tester.getSize(find.byKey(const Key('startup-splash'))), Size.square(expectedSize), ); expect(find.byType(CircularProgressIndicator), findsNothing); } debugDefaultTargetPlatformOverride = null; }); testWidgets('should_show_spinner_when_retry_loads_after_catalog_settled', ( tester, ) async { final controller = CatalogController(_EmptyCatalogRepository()) ..loading = true ..settled = true; addTearDown(controller.dispose); await _pumpHomePage(tester, controller); expect(find.byType(CircularProgressIndicator), findsOneWidget); expect(find.byKey(const Key('startup-splash')), findsNothing); }); testWidgets('should_enter_home_and_remove_startup_image_when_data_is_ready', ( tester, ) async { AppConfig.ready = Future.value(); final catalog = _PendingCatalogRepository(); await tester.pumpWidget( LumaDramaApp( playerFactory: createWidgetPlayer, catalogRepository: catalog, categoryRepository: FakeCategoryRepository(catalog: catalog), watchHistoryRepository: InMemoryWatchHistoryRepository(), favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas), playbackRepository: FakePlaybackRepository(), commentRepository: FakeCommentRepository(), interactionRepository: FakeInteractionRepository(), noticeRepository: FakeNoticeRepository(), haptics: FakeHaptics(), ), ); await tester.pump(); expect(find.byKey(const Key('startup-splash')), findsOneWidget); expect(find.byType(CircularProgressIndicator), findsNothing); catalog.complete(_feed); await tester.pumpAndSettle(); expect(find.byKey(const Key('startup-splash')), findsNothing); expect(find.byKey(const Key('home-feed-title')), findsOneWidget); }); } Future _pumpHomePage( WidgetTester tester, CatalogController controller, ) async { await tester.pumpWidget( ChangeNotifierProvider.value( value: controller, child: MaterialApp( theme: AppTheme.light(), locale: const Locale('en'), supportedLocales: AppLocalizations.supportedLocales, localizationsDelegates: AppLocalizations.localizationsDelegates, home: const HomePage(), ), ), ); await tester.pump(); } final _feed = HomeFeed( sections: [ FeedSection(code: 'hot', title: 'Hot', dramas: [demoDramas.first]), ], ); class _EmptyCatalogRepository implements CatalogRepository { @override Future fetchHomeFeed() async => const HomeFeed(); @override Future fetchDiscoverFeed() async => const HomeFeed(); @override Future fetchDrama(String dramaId) async => _feed.dramas.first; } class _PendingCatalogRepository implements CatalogRepository { final Completer _home = Completer(); List get dramas => _feed.dramas; void complete(HomeFeed feed) { if (!_home.isCompleted) _home.complete(feed); } @override Future fetchHomeFeed() => _home.future; @override Future fetchDiscoverFeed() async => _feed; @override Future fetchDrama(String dramaId) async => _feed.dramas.first; }