// Author: fruit.com.cn import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/app.dart'; import 'package:fruitshorts/core/data/models/drama.dart'; import 'package:fruitshorts/core/theme/app_colors.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:shared_preferences_platform_interface/in_memory_shared_preferences_async.dart'; import 'package:shared_preferences_platform_interface/shared_preferences_async_platform_interface.dart'; import '../support/fake_catalog.dart'; import '../support/fake_category.dart'; import '../support/fake_haptics.dart'; import '../support/fake_interaction_repositories.dart'; import '../support/widget_player.dart'; void main() { setUp(() { SharedPreferencesAsyncPlatform.instance = InMemorySharedPreferencesAsync.empty(); }); testWidgets('should_open_ranking_sorted_by_views', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-ranking'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('ranking-page')), findsOneWidget); _expectUnifiedHeader(tester, const Key('ranking-back')); expect(find.text('TOP 1'), findsOneWidget); expect( tester.widget(find.byKey(const Key('ranking-title-1'))).data, 'The Signal', ); await tester.tap(find.byKey(const Key('ranking-top-1'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('player-scaffold')), findsOneWidget); }); testWidgets('should_open_new_releases_sorted_by_id', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-new'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('new-releases-page')), findsOneWidget); _expectUnifiedHeader(tester, const Key('new-releases-back')); final newPage = tester.widget( find.byKey(const Key('new-releases-page')), ); expect(newPage.backgroundColor, AppColors.ink); final badge = tester.widget( find.byKey(const Key('new-releases-hero-badge')), ); expect((badge.decoration! as BoxDecoration).color, AppColors.blue); expect(find.byKey(const Key('new-releases-hero')), findsOneWidget); expect(find.text('Vengeance Rising'), findsWidgets); expect( find.byKey(const Key('new-release-card-the-signal-demo')), findsOneWidget, ); expect( find.byKey(const Key('new-release-card-city-lights-demo')), findsOneWidget, ); await tester.tap(find.byKey(const Key('new-releases-hero'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('player-scaffold')), findsOneWidget); }); testWidgets('should_open_reserve_empty_state', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-reserve'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('reserve-page')), findsOneWidget); _expectUnifiedHeader(tester, const Key('reserve-back')); expect(find.byKey(const Key('reserve-week-strip')), findsOneWidget); for (var index = 0; index < 7; index++) { expect(find.byKey(Key('reserve-day-$index')), findsOneWidget); } expect(find.byKey(const Key('reserve-empty')), findsOneWidget); for (var index = 1; index <= 3; index++) { expect(find.byKey(Key('reserve-step-$index')), findsOneWidget); } final todayIndex = DateTime.now().weekday - 1; final today = tester.widget( find.descendant( of: find.byKey(Key('reserve-day-$todayIndex')), matching: find.byType(Container), ), ); expect((today.decoration! as BoxDecoration).color, AppColors.blue); await tester.tap(find.byKey(const Key('reserve-go-new'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('new-releases-page')), findsOneWidget); }); testWidgets('should_render_podium_with_center_on_top', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-ranking'))); await tester.pumpAndSettle(); final top1 = tester.getRect(find.byKey(const Key('ranking-cover-1'))); final top2 = tester.getRect(find.byKey(const Key('ranking-cover-2'))); final top3 = tester.getRect(find.byKey(const Key('ranking-cover-3'))); expect(top1.width, greaterThan(top2.width)); expect(top3.width, closeTo(top2.width, 0.5)); expect(top2.left, closeTo(14, 0.5)); expect(top3.right, closeTo(376, 0.5)); expect(top2.left, lessThan(top1.left)); expect(top3.left, greaterThan(top1.right)); expect(top1.bottom, closeTo(top2.bottom, 0.5)); expect(top1.bottom, closeTo(top3.bottom, 0.5)); expect(find.byKey(const Key('ranking-row-3')), findsNothing); }); testWidgets('should_list_rank_four_and_below', (tester) async { await _pumpTheater(tester, dramas: _rankDramas(5)); await tester.tap(find.byKey(const Key('theater-toolbar-ranking'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('ranking-row-3')), findsOneWidget); expect(find.byKey(const Key('ranking-row-2')), findsNothing); expect(find.byKey(const Key('ranking-top-4')), findsOneWidget); expect( find.descendant( of: find.byKey(const Key('ranking-row-3')), matching: find.text('synopsis'), ), findsOneWidget, ); }); testWidgets('should_truncate_podium_when_less_than_three', (tester) async { await _pumpTheater(tester, dramas: _rankDramas(1)); await tester.tap(find.byKey(const Key('theater-toolbar-ranking'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('ranking-top-1')), findsOneWidget); expect(find.byKey(const Key('ranking-top-2')), findsNothing); expect(find.byKey(const Key('ranking-top-3')), findsNothing); }); testWidgets('should_open_player_from_new_releases_card', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-new'))); await tester.pumpAndSettle(); final card = find.byKey(const Key('new-release-card-the-signal-demo')); await tester.ensureVisible(card); await tester.pumpAndSettle(); await tester.tap(card); await tester.pumpAndSettle(); expect(find.byKey(const Key('player-scaffold')), findsOneWidget); }); testWidgets('should_go_back_to_theater_from_ranking_page', (tester) async { await _pumpTheater(tester); await tester.tap(find.byKey(const Key('theater-toolbar-ranking'))); await tester.pumpAndSettle(); await tester.tap(find.byKey(const Key('ranking-back'))); await tester.pumpAndSettle(); expect(find.byKey(const Key('ranking-page')), findsNothing); expect(find.byKey(const Key('discover-search')), findsOneWidget); }); } Future _pumpTheater(WidgetTester tester, {List? dramas}) async { tester.view.physicalSize = const Size(390, 844); tester.view.devicePixelRatio = 1; addTearDown(tester.view.resetPhysicalSize); addTearDown(tester.view.resetDevicePixelRatio); final catalog = FakeCatalogRepository(dramas: dramas); await tester.pumpWidget( LumaDramaApp( playerFactory: createWidgetPlayer, catalogRepository: catalog, searchRepository: catalog, categoryRepository: FakeCategoryRepository(catalog: catalog), watchHistoryRepository: InMemoryWatchHistoryRepository(), favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas), playbackRepository: FakePlaybackRepository(), commentRepository: FakeCommentRepository(), interactionRepository: FakeInteractionRepository(), haptics: FakeHaptics(), ), ); await tester.pumpAndSettle(); await tester.tap(find.byKey(const Key('tab-theater'))); await tester.pumpAndSettle(); } List _rankDramas(int count) => [ for (var index = 0; index < count; index++) Drama( id: 'rank-$index', title: 'Rank $index', synopsis: 'synopsis', posterUrl: '', totalEpisodes: 10, viewCount: (count - index) * 100, episodes: [ Episode( id: 'rank-$index-1', number: 1, title: 'Episode 1', isFree: true, ), ], ), ]; void _expectUnifiedHeader(WidgetTester tester, Key backKey) { expect(tester.getSize(find.byKey(backKey)), const Size(36, 36)); final title = tester.widget(find.byKey(const Key('subpage-title'))); expect(title.style?.fontSize, 18); expect(title.style?.fontWeight, FontWeight.w800); }