44
55import 'dart:async' ;
66import 'dart:io' ;
7+
78import 'package:flutter/foundation.dart' ;
89import 'package:flutter/services.dart' ;
910import 'package:flutter/widgets.dart' ;
10- import 'package:video_player/video_player.dart' ;
1111import 'package:flutter_test/flutter_test.dart' ;
12+ import 'package:video_player/video_player.dart' ;
1213
1314class FakeController extends ValueNotifier <VideoPlayerValue >
1415 implements VideoPlayerController {
@@ -24,23 +25,31 @@ class FakeController extends ValueNotifier<VideoPlayerValue>
2425
2526 @override
2627 String get dataSource => '' ;
28+
2729 @override
2830 DataSourceType get dataSourceType => DataSourceType .file;
31+
2932 @override
3033 String get package => null ;
34+
3135 @override
3236 Future <Duration > get position async => value.position;
3337
3438 @override
3539 Future <void > seekTo (Duration moment) async {}
40+
3641 @override
3742 Future <void > setVolume (double volume) async {}
43+
3844 @override
3945 Future <void > initialize () async {}
46+
4047 @override
4148 Future <void > pause () async {}
49+
4250 @override
4351 Future <void > play () async {}
52+
4453 @override
4554 Future <void > setLooping (bool looping) async {}
4655
@@ -139,6 +148,20 @@ void main() {
139148 'uri' : 'file://a.avi' ,
140149 });
141150 });
151+
152+ test ('capture video initialization errors' , () async {
153+ final VideoPlayerController controller =
154+ VideoPlayerController .network ('http://testing.com/invalid_url' );
155+ try {
156+ dynamic error;
157+ fakeVideoPlayerPlatform.forceInitError = true ;
158+ await controller.initialize ().catchError ((dynamic e) => error = e);
159+ final PlatformException platformEx = error;
160+ expect (platformEx.code, equals ('VideoError' ));
161+ } finally {
162+ fakeVideoPlayerPlatform.forceInitError = false ;
163+ }
164+ });
142165 });
143166}
144167
@@ -149,32 +172,40 @@ class FakeVideoPlayerPlatform {
149172
150173 final MethodChannel _channel = const MethodChannel ('flutter.io/videoPlayer' );
151174
152- Completer <bool > initialized = Completer <bool >();
153- List <Map <String , dynamic >> dataSourceDescriptions = < Map <String , dynamic >> [];
154- int nextTextureId = 0 ;
175+ final Completer <bool > initialized = Completer <bool >();
176+ final List <Map <String , dynamic >> dataSourceDescriptions =
177+ < Map <String , dynamic >> [];
178+
179+ bool forceInitError = false ;
180+
181+ int _nextTextureId = 0 ;
155182
156183 Future <dynamic > onMethodCall (MethodCall call) {
157184 switch (call.method) {
158185 case 'init' :
159186 initialized.complete (true );
160187 break ;
161188 case 'create' :
162- FakeVideoEventStream (
163- nextTextureId, 100 , 100 , const Duration (seconds: 1 ));
164- final Map <dynamic , dynamic > dataSource = call.arguments;
165- dataSourceDescriptions.add (dataSource.cast <String , dynamic >());
166- return Future <Map <String , int >>.sync (() {
167- return < String , int > {
168- 'textureId' : nextTextureId++ ,
169- };
170- });
189+ {
190+ FakeVideoEventStream (_nextTextureId, 100 , 100 ,
191+ const Duration (seconds: 1 ), forceInitError);
192+ final Map <dynamic , dynamic > dataSource = call.arguments;
193+ dataSourceDescriptions.add (dataSource.cast <String , dynamic >());
194+ return Future <Map <String , int >>.sync (() {
195+ return < String , int > {
196+ 'textureId' : _nextTextureId++ ,
197+ };
198+ });
199+ }
171200 break ;
172201 case 'setLooping' :
173202 break ;
174203 case 'setVolume' :
175204 break ;
176205 case 'pause' :
177206 break ;
207+ case 'dispose' :
208+ break ;
178209 default :
179210 throw UnimplementedError (
180211 '${call .method } is not implemented by the FakeVideoPlayerPlatform' );
@@ -184,54 +215,78 @@ class FakeVideoPlayerPlatform {
184215}
185216
186217class FakeVideoEventStream {
187- FakeVideoEventStream (this .textureId, this .width, this .height, this .duration) {
188- eventsChannel = FakeEventsChannel (
189- 'flutter.io/videoPlayer/videoEvents$textureId ' , onListen);
218+ FakeVideoEventStream (this .textureId, this .width, this .height, this .duration,
219+ this .initWithError) {
220+ _eventsChannel = FakeEventsChannel (
221+ 'flutter.io/videoPlayer/videoEvents$textureId ' , onListen, onCancel);
190222 }
191223
192- int textureId;
193- int width;
194- int height;
195- Duration duration;
196- FakeEventsChannel eventsChannel;
224+ FakeEventsChannel _eventsChannel;
225+ final int textureId;
226+ final int width;
227+ final int height;
228+ final Duration duration;
229+ final bool initWithError;
197230
198231 void onListen () {
199- final Map <String , dynamic > initializedEvent = < String , dynamic > {
200- 'event' : 'initialized' ,
201- 'duration' : duration.inMilliseconds,
202- 'width' : width,
203- 'height' : height,
204- };
205- eventsChannel.sendEvent (initializedEvent);
232+ if (! initWithError) {
233+ _eventsChannel.sendEvent (< String , dynamic > {
234+ 'event' : 'initialized' ,
235+ 'duration' : duration.inMilliseconds,
236+ 'width' : width,
237+ 'height' : height,
238+ });
239+ } else {
240+ _eventsChannel.sendError ('VideoError' , 'Video player had error XYZ' );
241+ }
242+ }
243+
244+ void onCancel () {
245+ //
206246 }
207247}
208248
209249class FakeEventsChannel {
210- FakeEventsChannel (String name, this .onListen) {
250+ FakeEventsChannel (String name, this .onListen, this .onCancel ) {
211251 eventsMethodChannel = MethodChannel (name);
212252 eventsMethodChannel.setMockMethodCallHandler (onMethodCall);
213253 }
214254
215255 MethodChannel eventsMethodChannel;
216256 VoidCallback onListen;
257+ VoidCallback onCancel;
217258
218259 Future <dynamic > onMethodCall (MethodCall call) {
219260 switch (call.method) {
220261 case 'listen' :
221262 onListen ();
222263 break ;
264+ case 'cancel' :
265+ eventsMethodChannel.setMockMethodCallHandler (null );
266+ onCancel ();
267+ break ;
223268 }
224269 return Future <void >.sync (() {});
225270 }
226271
227272 void sendEvent (dynamic event) {
273+ _sendMessage (const StandardMethodCodec ().encodeSuccessEnvelope (event));
274+ }
275+
276+ void sendError (String code, [String message, dynamic details]) {
277+ _sendMessage (const StandardMethodCodec ().encodeErrorEnvelope (
278+ code: code,
279+ message: message,
280+ details: details,
281+ ));
282+ }
283+
284+ void _sendMessage (ByteData data) {
228285 // TODO(jackson): This has been deprecated and should be replaced
229286 // with `ServicesBinding.instance.defaultBinaryMessenger` when it's
230287 // available on all the versions of Flutter that we test.
231288 // ignore: deprecated_member_use
232289 defaultBinaryMessenger.handlePlatformMessage (
233- eventsMethodChannel.name,
234- const StandardMethodCodec ().encodeSuccessEnvelope (event),
235- (ByteData data) {});
290+ eventsMethodChannel.name, data, (ByteData data) {});
236291 }
237292}
0 commit comments