| // Copyright 2017 The Chromium 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 'dart:async'; |
| import 'dart:ui'; |
| |
| import 'package:camera/camera.dart'; |
| import 'package:camera_platform_interface/camera_platform_interface.dart'; |
| import 'package:flutter/services.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:flutter_test/flutter_test.dart'; |
| import 'package:mockito/mockito.dart'; |
| import 'package:plugin_platform_interface/plugin_platform_interface.dart'; |
| |
| get mockAvailableCameras => [ |
| CameraDescription( |
| name: 'camBack', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| CameraDescription( |
| name: 'camFront', |
| lensDirection: CameraLensDirection.front, |
| sensorOrientation: 180), |
| ]; |
| |
| get mockInitializeCamera => 13; |
| |
| get mockOnCameraInitializedEvent => CameraInitializedEvent(13, 75, 75); |
| |
| get mockOnCameraClosingEvent => null; |
| |
| get mockOnCameraErrorEvent => CameraErrorEvent(13, 'closing'); |
| |
| XFile mockTakePicture = XFile('foo/bar.png'); |
| |
| get mockVideoRecordingXFile => null; |
| |
| bool mockPlatformException = false; |
| |
| void main() { |
| WidgetsFlutterBinding.ensureInitialized(); |
| |
| group('camera', () { |
| test('debugCheckIsDisposed should not throw assertion error when disposed', |
| () { |
| final MockCameraDescription description = MockCameraDescription(); |
| final CameraController controller = CameraController( |
| description, |
| ResolutionPreset.low, |
| ); |
| |
| controller.dispose(); |
| |
| expect(controller.debugCheckIsDisposed, returnsNormally); |
| }); |
| |
| test('debugCheckIsDisposed should throw assertion error when not disposed', |
| () { |
| final MockCameraDescription description = MockCameraDescription(); |
| final CameraController controller = CameraController( |
| description, |
| ResolutionPreset.low, |
| ); |
| |
| expect( |
| () => controller.debugCheckIsDisposed(), |
| throwsAssertionError, |
| ); |
| }); |
| |
| test('availableCameras() has camera', () async { |
| CameraPlatform.instance = MockCameraPlatform(); |
| |
| var camList = await availableCameras(); |
| |
| expect(camList, equals(mockAvailableCameras)); |
| }); |
| }); |
| |
| group('$CameraController', () { |
| setUpAll(() { |
| CameraPlatform.instance = MockCameraPlatform(); |
| }); |
| |
| test('Can be initialized', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| expect(cameraController.value.aspectRatio, 1); |
| expect(cameraController.value.previewSize, Size(75, 75)); |
| expect(cameraController.value.isInitialized, isTrue); |
| }); |
| |
| test('can be disposed', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| expect(cameraController.value.aspectRatio, 1); |
| expect(cameraController.value.previewSize, Size(75, 75)); |
| expect(cameraController.value.isInitialized, isTrue); |
| |
| await cameraController.dispose(); |
| |
| verify(CameraPlatform.instance.dispose(13)).called(1); |
| }); |
| |
| test('initialize() throws CameraException when disposed', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| expect(cameraController.value.aspectRatio, 1); |
| expect(cameraController.value.previewSize, Size(75, 75)); |
| expect(cameraController.value.isInitialized, isTrue); |
| |
| await cameraController.dispose(); |
| |
| verify(CameraPlatform.instance.dispose(13)).called(1); |
| |
| expect( |
| cameraController.initialize, |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'Error description', |
| 'initialize was called on a disposed CameraController', |
| ))); |
| }); |
| |
| test('initialize() throws $CameraException on $PlatformException ', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| |
| mockPlatformException = true; |
| |
| expect( |
| cameraController.initialize, |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'foo', |
| 'bar', |
| ))); |
| mockPlatformException = false; |
| }); |
| |
| test('prepareForVideoRecording() calls $CameraPlatform ', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| await cameraController.prepareForVideoRecording(); |
| |
| verify(CameraPlatform.instance.prepareForVideoRecording()).called(1); |
| }); |
| |
| test('takePicture() throws $CameraException when uninitialized ', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| expect( |
| cameraController.takePicture(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'Uninitialized CameraController.', |
| 'takePicture was called on uninitialized CameraController', |
| ))); |
| }); |
| |
| test('takePicture() throws $CameraException when takePicture is true', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| cameraController.value = |
| cameraController.value.copyWith(isTakingPicture: true); |
| expect( |
| cameraController.takePicture(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'Previous capture has not returned yet.', |
| 'takePicture was called before the previous capture returned.', |
| ))); |
| }); |
| |
| test('takePicture() returns $XFile', () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| XFile xFile = await cameraController.takePicture(); |
| |
| expect(xFile.path, mockTakePicture.path); |
| }); |
| |
| test('takePicture() throws $CameraException on $PlatformException', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| await cameraController.initialize(); |
| |
| mockPlatformException = true; |
| expect( |
| cameraController.takePicture(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'foo', |
| 'bar', |
| ))); |
| mockPlatformException = false; |
| }); |
| |
| test('startVideoRecording() throws $CameraException when uninitialized', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| |
| expect( |
| cameraController.startVideoRecording(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'Uninitialized CameraController', |
| 'startVideoRecording was called on uninitialized CameraController', |
| ))); |
| }); |
| test('startVideoRecording() throws $CameraException when recording videos', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| |
| await cameraController.initialize(); |
| |
| cameraController.value = |
| cameraController.value.copyWith(isRecordingVideo: true); |
| |
| expect( |
| cameraController.startVideoRecording(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'A video recording is already started.', |
| 'startVideoRecording was called when a recording is already started.', |
| ))); |
| }); |
| |
| test( |
| 'startVideoRecording() throws $CameraException when already streaming images', |
| () async { |
| CameraController cameraController = CameraController( |
| CameraDescription( |
| name: 'cam', |
| lensDirection: CameraLensDirection.back, |
| sensorOrientation: 90), |
| ResolutionPreset.max); |
| |
| await cameraController.initialize(); |
| |
| cameraController.value = |
| cameraController.value.copyWith(isStreamingImages: true); |
| |
| expect( |
| cameraController.startVideoRecording(), |
| throwsA(isA<CameraException>().having( |
| (error) => error.description, |
| 'A camera has started streaming images.', |
| 'startVideoRecording was called while a camera was streaming images.', |
| ))); |
| }); |
| }); |
| } |
| |
| class MockCameraPlatform extends Mock |
| with MockPlatformInterfaceMixin |
| implements CameraPlatform { |
| @override |
| Future<List<CameraDescription>> availableCameras() => |
| Future.value(mockAvailableCameras); |
| |
| @override |
| Future<int> createCamera( |
| CameraDescription description, |
| ResolutionPreset resolutionPreset, { |
| bool enableAudio, |
| }) => |
| mockPlatformException |
| ? throw PlatformException(code: 'foo', message: 'bar') |
| : Future.value(mockInitializeCamera); |
| |
| @override |
| Stream<CameraInitializedEvent> onCameraInitialized(int cameraId) => |
| Stream.value(mockOnCameraInitializedEvent); |
| |
| @override |
| Stream<CameraClosingEvent> onCameraClosing(int cameraId) => |
| Stream.value(mockOnCameraClosingEvent); |
| |
| @override |
| Stream<CameraErrorEvent> onCameraError(int cameraId) => |
| Stream.value(mockOnCameraErrorEvent); |
| |
| @override |
| Future<XFile> takePicture(int cameraId) => mockPlatformException |
| ? throw PlatformException(code: 'foo', message: 'bar') |
| : Future.value(mockTakePicture); |
| |
| @override |
| Future<XFile> startVideoRecording(int cameraId) => |
| Future.value(mockVideoRecordingXFile); |
| } |
| |
| class MockCameraDescription extends CameraDescription { |
| @override |
| CameraLensDirection get lensDirection => CameraLensDirection.back; |
| |
| @override |
| String get name => 'back'; |
| } |