// Author: fruit.com.cn import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:video_player/video_player.dart'; import 'package:fruitshorts/pages/player/widgets/player_video_surface.dart'; void main() { testWidgets('should_keep_fallback_visible_before_video_is_ready', ( tester, ) async { await _pumpSurface(tester); expect(_fallbackColor(tester), Colors.black); expect(find.byKey(const Key('player-fallback-cover')), findsNothing); expect(find.byKey(const Key('player-fallback-scrim')), findsNothing); expect(_opacity(tester), 0); expect(find.byKey(const Key('player-debug-video')), findsNothing); }); testWidgets('should_fade_video_in_within_200ms_after_first_frame', ( tester, ) async { final controller = await _pumpSurface(tester); expect(_opacity(tester), 0); controller.value = const VideoPlayerValue( duration: Duration(minutes: 1), size: Size(1280, 720), position: Duration(milliseconds: 1), isInitialized: true, isPlaying: true, ); await tester.pump(); expect(_opacity(tester), 1); expect( tester .widget( find.byKey(const Key('player-video-opacity')), ) .duration, const Duration(milliseconds: 200), ); await tester.pump(const Duration(milliseconds: 100)); final halfway = _fadeValue(tester); expect(halfway, greaterThan(0)); expect(halfway, lessThan(1)); await tester.pump(const Duration(milliseconds: 100)); expect(_fadeValue(tester), 1); expect(_fallbackColor(tester), Colors.black); expect(find.byKey(const Key('player-fallback-cover')), findsNothing); expect(find.byKey(const Key('player-debug-video')), findsNothing); }); testWidgets('should_show_video_error_above_retained_fallback', ( tester, ) async { await _pumpSurface( tester, value: const VideoPlayerValue.erroneous('No route to host'), ); expect(find.byKey(const Key('player-video-error')), findsOneWidget); expect(find.text('No route to host'), findsOneWidget); expect(_fallbackColor(tester), Colors.black); expect(find.byKey(const Key('player-fallback-cover')), findsNothing); expect(_opacity(tester), 0); expect(find.byKey(const Key('player-debug-video')), findsNothing); }); } Future _pumpSurface( WidgetTester tester, { VideoPlayerValue? value, }) async { final controller = VideoPlayerController.networkUrl( Uri.parse('http://192.168.31.187:8081/files/video.mp4'), ); addTearDown(controller.dispose); if (value != null) controller.value = value; await tester.pumpWidget( MaterialApp( home: Scaffold( body: PlayerVideoSurface( controller: controller, videoUrl: controller.dataSource, theater: false, onTap: () {}, ), ), ), ); await tester.pump(); return controller; } Color _fallbackColor(WidgetTester tester) { return tester .widget(find.byKey(const Key('player-fallback-background'))) .color; } double _opacity(WidgetTester tester) { return tester .widget(find.byKey(const Key('player-video-opacity'))) .opacity; } double _fadeValue(WidgetTester tester) { final fade = find.descendant( of: find.byKey(const Key('player-video-opacity')), matching: find.byType(FadeTransition), ); return tester.widget(fade).opacity.value; }