| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/services.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'package:video_player_avfoundation/src/messages.g.dart'; |
| import 'package:video_player_avfoundation/video_player_avfoundation.dart'; |
| import 'package:video_player_platform_interface/video_player_platform_interface.dart'; |
| |
| import 'test_api.g.dart'; |
| |
| class _ApiLogger implements TestHostVideoPlayerApi { |
| final List<String> log = <String>[]; |
| int? textureId; |
| CreationOptions? creationOptions; |
| int? position; |
| bool? looping; |
| double? volume; |
| double? playbackSpeed; |
| bool? mixWithOthers; |
| |
| @override |
| int create(CreationOptions options) { |
| log.add('create'); |
| creationOptions = options; |
| return 3; |
| } |
| |
| @override |
| void dispose(int textureId) { |
| log.add('dispose'); |
| this.textureId = textureId; |
| } |
| |
| @override |
| void initialize() { |
| log.add('init'); |
| } |
| |
| @override |
| void pause(int textureId) { |
| log.add('pause'); |
| this.textureId = textureId; |
| } |
| |
| @override |
| void play(int textureId) { |
| log.add('play'); |
| this.textureId = textureId; |
| } |
| |
| @override |
| void setMixWithOthers(bool enabled) { |
| log.add('setMixWithOthers'); |
| mixWithOthers = enabled; |
| } |
| |
| @override |
| int getPosition(int textureId) { |
| log.add('position'); |
| this.textureId = textureId; |
| return 234; |
| } |
| |
| @override |
| Future<void> seekTo(int position, int textureId) async { |
| log.add('seekTo'); |
| this.position = position; |
| this.textureId = textureId; |
| } |
| |
| @override |
| void setLooping(bool loop, int textureId) { |
| log.add('setLooping'); |
| looping = loop; |
| this.textureId = textureId; |
| } |
| |
| @override |
| void setVolume(double volume, int textureId) { |
| log.add('setVolume'); |
| this.volume = volume; |
| this.textureId = textureId; |
| } |
| |
| @override |
| void setPlaybackSpeed(double speed, int textureId) { |
| log.add('setPlaybackSpeed'); |
| playbackSpeed = speed; |
| this.textureId = textureId; |
| } |
| } |
| |
| void main() { |
| TestWidgetsFlutterBinding.ensureInitialized(); |
| |
| test('registration', () async { |
| AVFoundationVideoPlayer.registerWith(); |
| expect(VideoPlayerPlatform.instance, isA<AVFoundationVideoPlayer>()); |
| }); |
| |
| group('$AVFoundationVideoPlayer', () { |
| final AVFoundationVideoPlayer player = AVFoundationVideoPlayer(); |
| late _ApiLogger log; |
| |
| setUp(() { |
| log = _ApiLogger(); |
| TestHostVideoPlayerApi.setUp(log); |
| }); |
| |
| test('init', () async { |
| await player.init(); |
| expect( |
| log.log.last, |
| 'init', |
| ); |
| }); |
| |
| test('dispose', () async { |
| await player.dispose(1); |
| expect(log.log.last, 'dispose'); |
| expect(log.textureId, 1); |
| }); |
| |
| test('create with asset', () async { |
| final int? textureId = await player.create(DataSource( |
| sourceType: DataSourceType.asset, |
| asset: 'someAsset', |
| package: 'somePackage', |
| )); |
| expect(log.log.last, 'create'); |
| expect(log.creationOptions?.asset, 'someAsset'); |
| expect(log.creationOptions?.packageName, 'somePackage'); |
| expect(textureId, 3); |
| }); |
| |
| test('create with incorrect asset throws exception', () async { |
| try { |
| await player.create(DataSource( |
| sourceType: DataSourceType.asset, |
| asset: '/path/to/incorrect_asset', |
| )); |
| fail('should throw PlatformException'); |
| } catch (e) { |
| expect(e, isException); |
| } |
| }); |
| |
| test('create with network', () async { |
| final int? textureId = await player.create(DataSource( |
| sourceType: DataSourceType.network, |
| uri: 'someUri', |
| formatHint: VideoFormat.dash, |
| )); |
| expect(log.log.last, 'create'); |
| expect(log.creationOptions?.asset, null); |
| expect(log.creationOptions?.uri, 'someUri'); |
| expect(log.creationOptions?.packageName, null); |
| expect(log.creationOptions?.formatHint, 'dash'); |
| expect(log.creationOptions?.httpHeaders, <String, String>{}); |
| expect(textureId, 3); |
| }); |
| |
| test('create with network (some headers)', () async { |
| final int? textureId = await player.create(DataSource( |
| sourceType: DataSourceType.network, |
| uri: 'someUri', |
| httpHeaders: <String, String>{'Authorization': 'Bearer token'}, |
| )); |
| expect(log.log.last, 'create'); |
| expect(log.creationOptions?.asset, null); |
| expect(log.creationOptions?.uri, 'someUri'); |
| expect(log.creationOptions?.packageName, null); |
| expect(log.creationOptions?.formatHint, null); |
| expect(log.creationOptions?.httpHeaders, |
| <String, String>{'Authorization': 'Bearer token'}); |
| expect(textureId, 3); |
| }); |
| |
| test('create with file', () async { |
| final int? textureId = await player.create(DataSource( |
| sourceType: DataSourceType.file, |
| uri: 'someUri', |
| )); |
| expect(log.log.last, 'create'); |
| expect(log.creationOptions?.uri, 'someUri'); |
| expect(textureId, 3); |
| }); |
| |
| test('setLooping', () async { |
| await player.setLooping(1, true); |
| expect(log.log.last, 'setLooping'); |
| expect(log.textureId, 1); |
| expect(log.looping, true); |
| }); |
| |
| test('play', () async { |
| await player.play(1); |
| expect(log.log.last, 'play'); |
| expect(log.textureId, 1); |
| }); |
| |
| test('pause', () async { |
| await player.pause(1); |
| expect(log.log.last, 'pause'); |
| expect(log.textureId, 1); |
| }); |
| |
| test('setMixWithOthers', () async { |
| await player.setMixWithOthers(true); |
| expect(log.log.last, 'setMixWithOthers'); |
| expect(log.mixWithOthers, true); |
| |
| await player.setMixWithOthers(false); |
| expect(log.log.last, 'setMixWithOthers'); |
| expect(log.mixWithOthers, false); |
| }); |
| |
| test('setVolume', () async { |
| await player.setVolume(1, 0.7); |
| expect(log.log.last, 'setVolume'); |
| expect(log.textureId, 1); |
| expect(log.volume, 0.7); |
| }); |
| |
| test('setPlaybackSpeed', () async { |
| await player.setPlaybackSpeed(1, 1.5); |
| expect(log.log.last, 'setPlaybackSpeed'); |
| expect(log.textureId, 1); |
| expect(log.playbackSpeed, 1.5); |
| }); |
| |
| test('seekTo', () async { |
| await player.seekTo(1, const Duration(milliseconds: 12345)); |
| expect(log.log.last, 'seekTo'); |
| expect(log.textureId, 1); |
| expect(log.position, 12345); |
| }); |
| |
| test('getPosition', () async { |
| final Duration position = await player.getPosition(1); |
| expect(log.log.last, 'position'); |
| expect(log.textureId, 1); |
| expect(position, const Duration(milliseconds: 234)); |
| }); |
| |
| test('videoEventsFor', () async { |
| const String mockChannel = 'flutter.io/videoPlayer/videoEvents123'; |
| TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger |
| .setMockMessageHandler( |
| mockChannel, |
| (ByteData? message) async { |
| final MethodCall methodCall = |
| const StandardMethodCodec().decodeMethodCall(message); |
| if (methodCall.method == 'listen') { |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'initialized', |
| 'duration': 98765, |
| 'width': 1920, |
| 'height': 1080, |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'completed', |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'bufferingUpdate', |
| 'values': <List<dynamic>>[ |
| <int>[0, 1234], |
| <int>[1235, 4000], |
| ], |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'bufferingStart', |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'bufferingEnd', |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'isPlayingStateUpdate', |
| 'isPlaying': true, |
| }), |
| (ByteData? data) {}); |
| |
| await TestDefaultBinaryMessengerBinding |
| .instance.defaultBinaryMessenger |
| .handlePlatformMessage( |
| mockChannel, |
| const StandardMethodCodec() |
| .encodeSuccessEnvelope(<String, dynamic>{ |
| 'event': 'isPlayingStateUpdate', |
| 'isPlaying': false, |
| }), |
| (ByteData? data) {}); |
| |
| return const StandardMethodCodec().encodeSuccessEnvelope(null); |
| } else if (methodCall.method == 'cancel') { |
| return const StandardMethodCodec().encodeSuccessEnvelope(null); |
| } else { |
| fail('Expected listen or cancel'); |
| } |
| }, |
| ); |
| expect( |
| player.videoEventsFor(123), |
| emitsInOrder(<dynamic>[ |
| VideoEvent( |
| eventType: VideoEventType.initialized, |
| duration: const Duration(milliseconds: 98765), |
| size: const Size(1920, 1080), |
| ), |
| VideoEvent(eventType: VideoEventType.completed), |
| VideoEvent( |
| eventType: VideoEventType.bufferingUpdate, |
| buffered: <DurationRange>[ |
| DurationRange( |
| Duration.zero, |
| const Duration(milliseconds: 1234), |
| ), |
| DurationRange( |
| const Duration(milliseconds: 1235), |
| const Duration(milliseconds: 4000), |
| ), |
| ]), |
| VideoEvent(eventType: VideoEventType.bufferingStart), |
| VideoEvent(eventType: VideoEventType.bufferingEnd), |
| VideoEvent( |
| eventType: VideoEventType.isPlayingStateUpdate, |
| isPlaying: true, |
| ), |
| VideoEvent( |
| eventType: VideoEventType.isPlayingStateUpdate, |
| isPlaying: false, |
| ), |
| ])); |
| }); |
| }); |
| } |