fix(home): 首切频道预取并保留播放画面

This commit is contained in:
Zhou Weidong committed 2026-10-21 17:53:58 +08:00
1 parent dfa79bed88
commit 677e49fa6e
5 files changed
+242 -27

No files matched your search

+79 -4
View File
@@ -1,12 +1,16 @@
// Author: fruit.com.cn
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:fruitshorts/app.dart';
import 'package:fruitshorts/core/data/models/feed_page.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/pages/home/home_feed_channel.dart';
import 'package:fruitshorts/pages/player/player_view.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';
@@ -130,6 +134,44 @@ void main() {
expect(find.byKey(const Key('home-feed-title')), findsOneWidget);
});
testWidgets('should_keep_player_when_first_anime_switch_is_loading', (
tester,
) async {
final catalog = _PendingAnimeCatalog();
await _pumpApp(tester, catalog: catalog);
for (var attempt = 0; attempt < 5 && catalog.animeCalls == 0; attempt++) {
await tester.pump();
}
expect(catalog.animeCalls, 1);
await tester.tap(find.byKey(const Key('home-feed-tab-anime')));
await tester.pump();
expect(find.byType(PlayerPage), findsOneWidget);
expect(find.byKey(const Key('home-feed-channel-loading')), findsOneWidget);
catalog.anime.complete(FeedPage(dramas: [demoDramas[1]]));
await tester.pumpAndSettle();
expect(find.byKey(const Key('home-feed-channel-loading')), findsNothing);
expect(
tester.widget<PlayerPage>(find.byType(PlayerPage)).feedChannel,
HomeFeedChannel.anime,
);
});
testWidgets('should_show_empty_state_when_anime_has_no_dramas', (
tester,
) async {
await _pumpApp(tester, catalog: _EmptyAnimeCatalog());
await tester.tap(find.byKey(const Key('home-feed-tab-anime')));
await tester.pumpAndSettle();
expect(find.byType(PlayerPage), findsNothing);
expect(find.text('No stories available yet.'), findsOneWidget);
});
testWidgets('should_refresh_feed_without_blank_loading', (tester) async {
await _pumpApp(tester);
@@ -446,19 +488,20 @@ bool _hasLightStatusBar(WidgetTester tester) => tester
Future<void> _pumpApp(
WidgetTester tester, {
Size size = const Size(390, 844),
FakeCatalogRepository? catalog,
}) async {
tester.view.physicalSize = size;
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.resetPhysicalSize);
addTearDown(tester.view.resetDevicePixelRatio);
final catalog = FakeCatalogRepository();
final repository = catalog ?? FakeCatalogRepository();
await tester.pumpWidget(
LumaDramaApp(
playerFactory: createWidgetPlayer,
catalogRepository: catalog,
categoryRepository: FakeCategoryRepository(catalog: catalog),
catalogRepository: repository,
categoryRepository: FakeCategoryRepository(catalog: repository),
watchHistoryRepository: InMemoryWatchHistoryRepository(),
favoriteRepository: InMemoryFavoriteRepository(cards: catalog.dramas),
favoriteRepository: InMemoryFavoriteRepository(cards: repository.dramas),
playbackRepository: FakePlaybackRepository(),
commentRepository: FakeCommentRepository(),
interactionRepository: FakeInteractionRepository(),
@@ -467,3 +510,35 @@ Future<void> _pumpApp(
);
await tester.pumpAndSettle();
}
class _PendingAnimeCatalog extends FakeCatalogRepository {
final anime = Completer<FeedPage>();
int animeCalls = 0;
@override
Future<FeedPage> fetchFeed({
List<String> types = const [],
String? cursor,
int size = 10,
}) {
if (types.contains('ANIME')) {
animeCalls++;
return anime.future;
}
return super.fetchFeed(types: types, cursor: cursor, size: size);
}
}
class _EmptyAnimeCatalog extends FakeCatalogRepository {
@override
Future<FeedPage> fetchFeed({
List<String> types = const [],
String? cursor,
int size = 10,
}) {
if (types.contains('ANIME')) {
return Future.value(const FeedPage(dramas: []));
}
return super.fetchFeed(types: types, cursor: cursor, size: size);
}
}