diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 2388f101e24d..6b2e63ff95e1 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.9.18+5 + +* Migrates unit tests to Swift. + ## 0.9.18+4 * Refactors implementations to reduce usage of OCMock in internal testing. diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 75716ac04cf2..9a20f50f0972 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -8,13 +8,11 @@ /* Begin PBXBuildFile section */ 033B94BE269C40A200B4DF97 /* CameraMethodChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */; }; - 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BB766A2665316900CE5A93 /* CameraFocusTests.m */; }; 1000364CB781922C6D6AAA4A /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9DDC4CE84A8B378AE4A8CD9C /* libPods-RunnerTests.a */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 334733EA2668111C00DCC49E /* CameraOrientationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 408D7A792C3C9CD000B71F9A /* OCMock in Frameworks */ = {isa = PBXBuildFile; productRef = 408D7A782C3C9CD000B71F9A /* OCMock */; }; - 43ED1537282570DE00EB00DE /* AvailableCamerasTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */; }; 54D650172516862D30686934 /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = ECAF63F924EFA2D68883BA85 /* libPods-Runner.a */; }; 788A065A27B0E02900533D74 /* StreamingTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 788A065927B0E02900533D74 /* StreamingTest.m */; }; 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; @@ -22,31 +20,33 @@ 7F29EB222D269ED500740257 /* MockEventChannel.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F29EB212D269ED500740257 /* MockEventChannel.m */; }; 7F29EB292D26A59000740257 /* MockCameraDeviceDiscoverer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F29EB282D26A59000740257 /* MockCameraDeviceDiscoverer.m */; }; 7F29EB412D281C7E00740257 /* MockCaptureSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F29EB402D281C7E00740257 /* MockCaptureSession.m */; }; - 7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; }; 7F8FD2292D4BFABF001AF2C1 /* MockGlobalEventApi.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F8FD2282D4BFABF001AF2C1 /* MockGlobalEventApi.m */; }; 7F8FD22C2D4D07DD001AF2C1 /* MockFlutterTextureRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F8FD22B2D4D07DD001AF2C1 /* MockFlutterTextureRegistry.m */; }; 7F8FD22F2D4D0B88001AF2C1 /* MockFlutterBinaryMessenger.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F8FD22E2D4D0B88001AF2C1 /* MockFlutterBinaryMessenger.m */; }; - 7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA99E582D22C75300582559 /* CameraExposureTests.m */; }; 7FCEDD352D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEDD342D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m */; }; 7FCEDD362D43C2B900EA1CA8 /* MockCaptureDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FCEDD322D43C2B900EA1CA8 /* MockCaptureDevice.m */; }; - 7FD582352D57D97C003B1200 /* MockCaptureDeviceFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */; }; 7FD582122D579650003B1200 /* MockWritableData.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582112D579650003B1200 /* MockWritableData.m */; }; 7FD582202D579ECC003B1200 /* MockCapturePhotoOutput.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD5821F2D579ECC003B1200 /* MockCapturePhotoOutput.m */; }; + 7FD582352D57D97C003B1200 /* MockCaptureDeviceFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */; }; + 972CA92B2D5A1D8C004B846F /* CameraPropertiesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CA92A2D5A1D8C004B846F /* CameraPropertiesTests.swift */; }; + 972CA92D2D5A28C4004B846F /* QueueUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CA92C2D5A28C4004B846F /* QueueUtilsTests.swift */; }; + 972CA9312D5A366C004B846F /* CameraExposureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 972CA9302D5A366C004B846F /* CameraExposureTests.swift */; }; + 977A25202D5A439300931E34 /* AvailableCamerasTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 977A251F2D5A439300931E34 /* AvailableCamerasTests.swift */; }; + 977A25222D5A49EC00931E34 /* CameraFocusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 977A25212D5A49EC00931E34 /* CameraFocusTests.swift */; }; + 977A25242D5A511600931E34 /* CameraPermissionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 977A25232D5A511600931E34 /* CameraPermissionTests.swift */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; + 979B3DFB2D5B6BC7009BDE1A /* ExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 979B3DFA2D5B6BC7009BDE1A /* ExceptionCatcher.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + 97DB234D2D566D0700CEFE66 /* CameraPreviewPauseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 97DB234C2D566D0700CEFE66 /* CameraPreviewPauseTests.swift */; }; CEF6611A2B5E36A500D33FD4 /* CameraSessionPresetsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */; }; - E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */; }; - E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */; }; E04F108627A87CA600573D0C /* FLTSavePhotoDelegateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */; }; E071CF7227B3061B006EF3BA /* FLTCamPhotoCaptureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */; }; E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */; }; E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */; }; E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */; }; - E0F95E3D27A32AB900699390 /* CameraPropertiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */; }; - E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E487C85F26D686A10034AC92 /* CameraPreviewPauseTests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -75,13 +75,11 @@ /* Begin PBXFileReference section */ 033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraMethodChannelTests.m; sourceTree = ""; }; 03BB76682665316900CE5A93 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 03BB766A2665316900CE5A93 /* CameraFocusTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraFocusTests.m; sourceTree = ""; }; 03BB766C2665316900CE5A93 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraOrientationTests.m; sourceTree = ""; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AvailableCamerasTest.m; sourceTree = ""; }; 4A191381C3593DF1AC4E7559 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 788A065927B0E02900533D74 /* StreamingTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StreamingTest.m; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; @@ -100,40 +98,44 @@ 7F8FD22B2D4D07DD001AF2C1 /* MockFlutterTextureRegistry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockFlutterTextureRegistry.m; sourceTree = ""; }; 7F8FD22D2D4D0B73001AF2C1 /* MockFlutterBinaryMessenger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockFlutterBinaryMessenger.h; sourceTree = ""; }; 7F8FD22E2D4D0B88001AF2C1 /* MockFlutterBinaryMessenger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockFlutterBinaryMessenger.m; sourceTree = ""; }; - 7FA99E582D22C75300582559 /* CameraExposureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraExposureTests.m; sourceTree = ""; }; 7FCEDD312D43C2B900EA1CA8 /* MockCaptureDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDevice.h; sourceTree = ""; }; 7FCEDD322D43C2B900EA1CA8 /* MockCaptureDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDevice.m; sourceTree = ""; }; 7FCEDD332D43C2B900EA1CA8 /* MockDeviceOrientationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockDeviceOrientationProvider.h; sourceTree = ""; }; 7FCEDD342D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockDeviceOrientationProvider.m; sourceTree = ""; }; - 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDeviceFormat.m; sourceTree = ""; }; - 7FD582362D57D989003B1200 /* MockCaptureDeviceFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceFormat.h; sourceTree = ""; }; 7FD582112D579650003B1200 /* MockWritableData.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockWritableData.m; sourceTree = ""; }; 7FD582132D57965A003B1200 /* MockWritableData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockWritableData.h; sourceTree = ""; }; 7FD5821F2D579ECC003B1200 /* MockCapturePhotoOutput.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCapturePhotoOutput.m; sourceTree = ""; }; 7FD582212D579ED9003B1200 /* MockCapturePhotoOutput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCapturePhotoOutput.h; sourceTree = ""; }; + 7FD582342D57D97C003B1200 /* MockCaptureDeviceFormat.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockCaptureDeviceFormat.m; sourceTree = ""; }; + 7FD582362D57D989003B1200 /* MockCaptureDeviceFormat.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceFormat.h; sourceTree = ""; }; + 972CA92A2D5A1D8C004B846F /* CameraPropertiesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPropertiesTests.swift; sourceTree = ""; }; + 972CA92C2D5A28C4004B846F /* QueueUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueueUtilsTests.swift; sourceTree = ""; }; + 972CA9302D5A366C004B846F /* CameraExposureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraExposureTests.swift; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 977A251F2D5A439300931E34 /* AvailableCamerasTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvailableCamerasTests.swift; sourceTree = ""; }; + 977A25212D5A49EC00931E34 /* CameraFocusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraFocusTests.swift; sourceTree = ""; }; + 977A25232D5A511600931E34 /* CameraPermissionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPermissionTests.swift; sourceTree = ""; }; + 979B3DF92D5B6BA2009BDE1A /* ExceptionCatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExceptionCatcher.h; sourceTree = ""; }; + 979B3DFA2D5B6BC7009BDE1A /* ExceptionCatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExceptionCatcher.m; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 97DB234B2D566D0600CEFE66 /* RunnerTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "RunnerTests-Bridging-Header.h"; sourceTree = ""; }; + 97DB234C2D566D0700CEFE66 /* CameraPreviewPauseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPreviewPauseTests.swift; sourceTree = ""; }; 9DDC4CE84A8B378AE4A8CD9C /* libPods-RunnerTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-RunnerTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; A8F314CD1C64E9257EBC811D /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; B61D98BBC8FB276D1C4A7BB2 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */ = {isa = PBXFileReference; indentWidth = 2; lastKnownFileType = sourcecode.c.objc; path = CameraSessionPresetsTests.m; sourceTree = ""; }; - E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = QueueUtilsTests.m; sourceTree = ""; }; - E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CameraCaptureSessionQueueRaceConditionTests.m; sourceTree = ""; }; E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTSavePhotoDelegateTests.m; sourceTree = ""; }; E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FLTCamPhotoCaptureTests.m; sourceTree = ""; }; E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLTCamSampleBufferTests.m; sourceTree = ""; }; - E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPermissionTests.m; sourceTree = ""; }; E0C6E1FF2770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThreadSafeEventChannelTests.m; sourceTree = ""; }; E0CDBAC027CD9729002561D9 /* CameraTestUtils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CameraTestUtils.h; sourceTree = ""; }; E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraTestUtils.m; sourceTree = ""; }; - E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPropertiesTests.m; sourceTree = ""; }; - E487C85F26D686A10034AC92 /* CameraPreviewPauseTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraPreviewPauseTests.m; sourceTree = ""; }; E67C6DBF6478BE708993169F /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; ECAF63F924EFA2D68883BA85 /* libPods-Runner.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Runner.a"; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -165,8 +167,6 @@ children = ( 7F29EB3F2D281C6D00740257 /* Mocks */, 7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */, - 03BB766A2665316900CE5A93 /* CameraFocusTests.m */, - 7FA99E582D22C75300582559 /* CameraExposureTests.m */, 03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */, 03BB766C2665316900CE5A93 /* Info.plist */, 033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */, @@ -174,16 +174,20 @@ E04F108527A87CA600573D0C /* FLTSavePhotoDelegateTests.m */, E071CF7127B3061B006EF3BA /* FLTCamPhotoCaptureTests.m */, E071CF7327B31DE4006EF3BA /* FLTCamSampleBufferTests.m */, - E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */, - E01EE4A72799F3A5008C1950 /* QueueUtilsTests.m */, E0CDBAC027CD9729002561D9 /* CameraTestUtils.h */, E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */, - E487C85F26D686A10034AC92 /* CameraPreviewPauseTests.m */, - E032F24F279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m */, - E0F95E3C27A32AB900699390 /* CameraPropertiesTests.m */, 788A065927B0E02900533D74 /* StreamingTest.m */, - 43ED1536282570DE00EB00DE /* AvailableCamerasTest.m */, CEF661192B5E36A500D33FD4 /* CameraSessionPresetsTests.m */, + 97DB234B2D566D0600CEFE66 /* RunnerTests-Bridging-Header.h */, + 97DB234C2D566D0700CEFE66 /* CameraPreviewPauseTests.swift */, + 972CA92A2D5A1D8C004B846F /* CameraPropertiesTests.swift */, + 972CA92C2D5A28C4004B846F /* QueueUtilsTests.swift */, + 972CA9302D5A366C004B846F /* CameraExposureTests.swift */, + 977A251F2D5A439300931E34 /* AvailableCamerasTests.swift */, + 977A25212D5A49EC00931E34 /* CameraFocusTests.swift */, + 977A25232D5A511600931E34 /* CameraPermissionTests.swift */, + 979B3DF92D5B6BA2009BDE1A /* ExceptionCatcher.h */, + 979B3DFA2D5B6BC7009BDE1A /* ExceptionCatcher.m */, ); path = RunnerTests; sourceTree = ""; @@ -354,6 +358,7 @@ TargetAttributes = { 03BB76672665316900CE5A93 = { CreatedOnToolsVersion = 12.5; + LastSwiftMigration = 1540; ProvisioningStyle = Automatic; TestTargetID = 97C146ED1CF9000F007C117D; }; @@ -512,30 +517,30 @@ buildActionMask = 2147483647; files = ( 033B94BE269C40A200B4DF97 /* CameraMethodChannelTests.m in Sources */, + 972CA92D2D5A28C4004B846F /* QueueUtilsTests.swift in Sources */, + 979B3DFB2D5B6BC7009BDE1A /* ExceptionCatcher.m in Sources */, E071CF7227B3061B006EF3BA /* FLTCamPhotoCaptureTests.m in Sources */, - 7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */, - E0F95E3D27A32AB900699390 /* CameraPropertiesTests.m in Sources */, - 03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */, + 977A25242D5A511600931E34 /* CameraPermissionTests.swift in Sources */, 7D5FCCD42AEF9D0200FB7108 /* CameraSettingsTests.m in Sources */, 7F8FD2292D4BFABF001AF2C1 /* MockGlobalEventApi.m in Sources */, - 7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */, - E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */, E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */, 7FD582352D57D97C003B1200 /* MockCaptureDeviceFormat.m in Sources */, 7F29EB222D269ED500740257 /* MockEventChannel.m in Sources */, 7F8FD22F2D4D0B88001AF2C1 /* MockFlutterBinaryMessenger.m in Sources */, E04F108627A87CA600573D0C /* FLTSavePhotoDelegateTests.m in Sources */, - 43ED1537282570DE00EB00DE /* AvailableCamerasTest.m in Sources */, + 972CA92B2D5A1D8C004B846F /* CameraPropertiesTests.swift in Sources */, E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */, 334733EA2668111C00DCC49E /* CameraOrientationTests.m in Sources */, 7FD582202D579ECC003B1200 /* MockCapturePhotoOutput.m in Sources */, + 97DB234D2D566D0700CEFE66 /* CameraPreviewPauseTests.swift in Sources */, + 977A25202D5A439300931E34 /* AvailableCamerasTests.swift in Sources */, CEF6611A2B5E36A500D33FD4 /* CameraSessionPresetsTests.m in Sources */, - E032F250279F5E94009E9028 /* CameraCaptureSessionQueueRaceConditionTests.m in Sources */, + 972CA9312D5A366C004B846F /* CameraExposureTests.swift in Sources */, 7F29EB292D26A59000740257 /* MockCameraDeviceDiscoverer.m in Sources */, 788A065A27B0E02900533D74 /* StreamingTest.m in Sources */, E0C6E2022770F01A00EA6AA3 /* ThreadSafeEventChannelTests.m in Sources */, + 977A25222D5A49EC00931E34 /* CameraFocusTests.swift in Sources */, 7F29EB412D281C7E00740257 /* MockCaptureSession.m in Sources */, - E01EE4A82799F3A5008C1950 /* QueueUtilsTests.m in Sources */, 7FD582122D579650003B1200 /* MockWritableData.m in Sources */, 7FCEDD352D43C2B900EA1CA8 /* MockDeviceOrientationProvider.m in Sources */, 7FCEDD362D43C2B900EA1CA8 /* MockCaptureDevice.m in Sources */, @@ -590,6 +595,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; @@ -607,6 +613,9 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.cameraExample.camera-exampleTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; @@ -619,6 +628,7 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; @@ -635,6 +645,8 @@ MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.cameraExample.camera-exampleTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "RunnerTests/RunnerTests-Bridging-Header.h"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTest.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTest.m deleted file mode 100644 index 516cd3c49585..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTest.m +++ /dev/null @@ -1,151 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import XCTest; -@import AVFoundation; - -#import "MockCameraDeviceDiscoverer.h" -#import "MockCaptureDevice.h" -#import "MockCaptureSession.h" -#import "MockFlutterBinaryMessenger.h" -#import "MockFlutterTextureRegistry.h" -#import "MockGlobalEventApi.h" - -@interface AvailableCamerasTest : XCTestCase - -@end - -@implementation AvailableCamerasTest - -- (CameraPlugin *)createCameraPluginWithDeviceDiscoverer: - (MockCameraDeviceDiscoverer *)deviceDiscoverer { - return [[CameraPlugin alloc] initWithRegistry:[[MockFlutterTextureRegistry alloc] init] - messenger:[[MockFlutterBinaryMessenger alloc] init] - globalAPI:[[MockGlobalEventApi alloc] init] - deviceDiscoverer:deviceDiscoverer - deviceFactory:^NSObject *(NSString *name) { - return [[MockCaptureDevice alloc] init]; - } - captureSessionFactory:^NSObject * { - return [[MockCaptureSession alloc] init]; - } - captureDeviceInputFactory:[[MockCaptureDeviceInputFactory alloc] init]]; -} - -- (void)testAvailableCamerasShouldReturnAllCamerasOnMultiCameraIPhone { - MockCameraDeviceDiscoverer *mockDeviceDiscoverer = [[MockCameraDeviceDiscoverer alloc] init]; - CameraPlugin *cameraPlugin = [self createCameraPluginWithDeviceDiscoverer:mockDeviceDiscoverer]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Result finished"]; - - // iPhone 13 Cameras: - MockCaptureDevice *wideAngleCamera = [[MockCaptureDevice alloc] init]; - wideAngleCamera.uniqueID = @"0"; - wideAngleCamera.position = AVCaptureDevicePositionBack; - - MockCaptureDevice *frontFacingCamera = [[MockCaptureDevice alloc] init]; - frontFacingCamera.uniqueID = @"1"; - frontFacingCamera.position = AVCaptureDevicePositionFront; - - MockCaptureDevice *ultraWideCamera = [[MockCaptureDevice alloc] init]; - ultraWideCamera.uniqueID = @"2"; - ultraWideCamera.position = AVCaptureDevicePositionBack; - - MockCaptureDevice *telephotoCamera = [[MockCaptureDevice alloc] init]; - telephotoCamera.uniqueID = @"3"; - telephotoCamera.position = AVCaptureDevicePositionBack; - - NSMutableArray *requiredTypes = - [@[ AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInTelephotoCamera ] - mutableCopy]; - if (@available(iOS 13.0, *)) { - [requiredTypes addObject:AVCaptureDeviceTypeBuiltInUltraWideCamera]; - } - - NSMutableArray *cameras = [NSMutableArray array]; - [cameras addObjectsFromArray:@[ wideAngleCamera, frontFacingCamera, telephotoCamera ]]; - if (@available(iOS 13.0, *)) { - [cameras addObject:ultraWideCamera]; - } - - mockDeviceDiscoverer.discoverySessionStub = ^NSArray *> *_Nullable( - NSArray *_Nonnull deviceTypes, AVMediaType _Nonnull mediaType, - AVCaptureDevicePosition position) { - XCTAssertEqualObjects(deviceTypes, requiredTypes); - XCTAssertEqual(mediaType, AVMediaTypeVideo); - XCTAssertEqual(position, AVCaptureDevicePositionUnspecified); - return cameras; - }; - - __block NSArray *resultValue; - [cameraPlugin - availableCamerasWithCompletion:^(NSArray *_Nullable result, - FlutterError *_Nullable error) { - XCTAssertNil(error); - resultValue = result; - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; - - // Verify the result - if (@available(iOS 13.0, *)) { - XCTAssertEqual(resultValue.count, 4); - } else { - XCTAssertEqual(resultValue.count, 3); - } -} -- (void)testAvailableCamerasShouldReturnOneCameraOnSingleCameraIPhone { - MockCameraDeviceDiscoverer *mockDeviceDiscoverer = [[MockCameraDeviceDiscoverer alloc] init]; - CameraPlugin *cameraPlugin = [self createCameraPluginWithDeviceDiscoverer:mockDeviceDiscoverer]; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Result finished"]; - - // iPhone 8 Cameras: - MockCaptureDevice *wideAngleCamera = [[MockCaptureDevice alloc] init]; - wideAngleCamera.uniqueID = @"0"; - wideAngleCamera.position = AVCaptureDevicePositionBack; - - MockCaptureDevice *frontFacingCamera = [[MockCaptureDevice alloc] init]; - frontFacingCamera.uniqueID = @"1"; - frontFacingCamera.position = AVCaptureDevicePositionFront; - - NSMutableArray *requiredTypes = - [@[ AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInTelephotoCamera ] - mutableCopy]; - if (@available(iOS 13.0, *)) { - [requiredTypes addObject:AVCaptureDeviceTypeBuiltInUltraWideCamera]; - } - - NSMutableArray *cameras = [NSMutableArray array]; - [cameras addObjectsFromArray:@[ wideAngleCamera, frontFacingCamera ]]; - - mockDeviceDiscoverer.discoverySessionStub = ^NSArray *> *_Nullable( - NSArray *_Nonnull deviceTypes, AVMediaType _Nonnull mediaType, - AVCaptureDevicePosition position) { - XCTAssertEqualObjects(deviceTypes, requiredTypes); - XCTAssertEqual(mediaType, AVMediaTypeVideo); - XCTAssertEqual(position, AVCaptureDevicePositionUnspecified); - return cameras; - }; - - __block NSArray *resultValue; - [cameraPlugin - availableCamerasWithCompletion:^(NSArray *_Nullable result, - FlutterError *_Nullable error) { - XCTAssertNil(error); - resultValue = result; - [expectation fulfill]; - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; - - // Verify the result - XCTAssertEqual(resultValue.count, 2); - ; -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift new file mode 100644 index 000000000000..436ab08bf6d8 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/AvailableCamerasTests.swift @@ -0,0 +1,120 @@ +// 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 AVFoundation +import XCTest + +@testable import camera_avfoundation + +final class AvailableCamerasTest: XCTestCase { + private func createCameraPlugin(with deviceDiscoverer: MockCameraDeviceDiscoverer) -> CameraPlugin + { + return CameraPlugin( + registry: MockFlutterTextureRegistry(), + messenger: MockFlutterBinaryMessenger(), + globalAPI: MockGlobalEventApi(), + deviceDiscoverer: deviceDiscoverer, + deviceFactory: { _ in MockCaptureDevice() }, + captureSessionFactory: { MockCaptureSession() }, + captureDeviceInputFactory: MockCaptureDeviceInputFactory() + ) + } + + func testAvailableCamerasShouldReturnAllCamerasOnMultiCameraIPhone() { + let mockDeviceDiscoverer = MockCameraDeviceDiscoverer() + let cameraPlugin = createCameraPlugin(with: mockDeviceDiscoverer) + let expectation = self.expectation(description: "Result finished") + + // iPhone 13 Cameras: + let wideAngleCamera = MockCaptureDevice() + wideAngleCamera.uniqueID = "0" + wideAngleCamera.position = .back + + let frontFacingCamera = MockCaptureDevice() + frontFacingCamera.uniqueID = "1" + frontFacingCamera.position = .front + + let ultraWideCamera = MockCaptureDevice() + ultraWideCamera.uniqueID = "2" + ultraWideCamera.position = .back + + let telephotoCamera = MockCaptureDevice() + telephotoCamera.uniqueID = "3" + telephotoCamera.position = .back + + var requiredTypes: [AVCaptureDevice.DeviceType] = [ + .builtInWideAngleCamera, .builtInTelephotoCamera, + ] + if #available(iOS 13.0, *) { + requiredTypes.append(.builtInUltraWideCamera) + } + var cameras: [MockCaptureDevice] = [wideAngleCamera, frontFacingCamera, telephotoCamera] + if #available(iOS 13.0, *) { + cameras.append(ultraWideCamera) + } + + mockDeviceDiscoverer.discoverySessionStub = { deviceTypes, mediaType, position in + XCTAssertEqual(deviceTypes, requiredTypes) + XCTAssertEqual(mediaType, .video) + XCTAssertEqual(position, .unspecified) + return cameras + } + + var resultValue: [FCPPlatformCameraDescription]? + cameraPlugin.availableCameras { result, error in + XCTAssertNil(error) + resultValue = result + expectation.fulfill() + } + waitForExpectations(timeout: 30, handler: nil) + + // Verify the result. + if #available(iOS 13.0, *) { + XCTAssertEqual(resultValue?.count, 4) + } else { + XCTAssertEqual(resultValue?.count, 3) + } + } + + func testAvailableCamerasShouldReturnOneCameraOnSingleCameraIPhone() { + let mockDeviceDiscoverer = MockCameraDeviceDiscoverer() + let cameraPlugin = createCameraPlugin(with: mockDeviceDiscoverer) + let expectation = self.expectation(description: "Result finished") + + // iPhone 8 Cameras: + let wideAngleCamera = MockCaptureDevice() + wideAngleCamera.uniqueID = "0" + wideAngleCamera.position = .back + + let frontFacingCamera = MockCaptureDevice() + frontFacingCamera.uniqueID = "1" + frontFacingCamera.position = .front + + var requiredTypes: [AVCaptureDevice.DeviceType] = [ + .builtInWideAngleCamera, .builtInTelephotoCamera, + ] + if #available(iOS 13.0, *) { + requiredTypes.append(.builtInUltraWideCamera) + } + let cameras: [MockCaptureDevice] = [wideAngleCamera, frontFacingCamera] + + mockDeviceDiscoverer.discoverySessionStub = { deviceTypes, mediaType, position in + XCTAssertEqual(deviceTypes, requiredTypes) + XCTAssertEqual(mediaType, .video) + XCTAssertEqual(position, .unspecified) + return cameras + } + + var resultValue: [FCPPlatformCameraDescription]? + cameraPlugin.availableCameras { result, error in + XCTAssertNil(error) + resultValue = result + expectation.fulfill() + } + waitForExpectations(timeout: 30, handler: nil) + + // Verify the result. + XCTAssertEqual(resultValue?.count, 2) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.swift new file mode 100644 index 000000000000..b3d62d6b0aa0 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraExposureTests.swift @@ -0,0 +1,66 @@ +// 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 AVFoundation +import XCTest + +@testable import camera_avfoundation + +final class CameraExposureTests: XCTestCase { + private func createSutAndMocks() -> (FLTCam, MockCaptureDevice, MockDeviceOrientationProvider) { + let mockDevice = MockCaptureDevice() + let mockDeviceOrientationProvider = MockDeviceOrientationProvider() + + let configuration = FLTCreateTestCameraConfiguration() + configuration.captureDeviceFactory = { mockDevice } + configuration.deviceOrientationProvider = mockDeviceOrientationProvider + let camera = FLTCreateCamWithConfiguration(configuration) + + return (camera, mockDevice, mockDeviceOrientationProvider) + } + + func testSetExposurePointWithResult_SetsExposurePointOfInterest() { + let (camera, mockDevice, mockDeviceOrientationProvider) = createSutAndMocks() + // UI is currently in landscape left orientation. + mockDeviceOrientationProvider.orientation = .landscapeLeft + // Exposure point of interest is supported. + mockDevice.exposurePointOfInterestSupported = true + + // Verify the focus point of interest has been set. + var setPoint = CGPoint.zero + mockDevice.setExposurePointOfInterestStub = { point in + if point == CGPoint(x: 1, y: 1) { + setPoint = point + } + } + + let completionExpectation = expectation(description: "Completion called") + camera.setExposurePoint(FCPPlatformPoint.makeWith(x: 1, y: 1)) { error in + XCTAssertNil(error) + completionExpectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + XCTAssertEqual(setPoint, CGPoint(x: 1.0, y: 1.0)) + } + + func testSetExposurePoint_WhenNotSupported_ReturnsError() { + let (camera, mockDevice, mockDeviceOrientationProvider) = createSutAndMocks() + // UI is currently in landscape left orientation. + mockDeviceOrientationProvider.orientation = .landscapeLeft + // Exposure point of interest is not supported. + mockDevice.exposurePointOfInterestSupported = false + + let expectation = self.expectation(description: "Completion with error") + + camera.setExposurePoint(FCPPlatformPoint.makeWith(x: 1, y: 1)) { error in + XCTAssertNotNil(error) + XCTAssertEqual(error?.code, "setExposurePointFailed") + XCTAssertEqual(error?.message, "Device does not have exposure point capabilities") + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m deleted file mode 100644 index fab96850a3a5..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.m +++ /dev/null @@ -1,179 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import XCTest; -@import AVFoundation; - -#import "CameraTestUtils.h" -#import "MockCaptureDevice.h" -#import "MockDeviceOrientationProvider.h" - -@interface CameraFocusTests : XCTestCase -@property(readonly, nonatomic) FLTCam *camera; -@property(readonly, nonatomic) MockCaptureDevice *mockDevice; -@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider; -@end - -@implementation CameraFocusTests - -- (void)setUp { - MockCaptureDevice *mockDevice = [[MockCaptureDevice alloc] init]; - _mockDevice = mockDevice; - _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; - - FLTCamConfiguration *configuration = FLTCreateTestCameraConfiguration(); - configuration.captureDeviceFactory = ^NSObject *_Nonnull { return mockDevice; }; - configuration.deviceOrientationProvider = _mockDeviceOrientationProvider; - _camera = FLTCreateCamWithConfiguration(configuration); -} - -- (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { - // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeContinuousAutoFocus are supported - _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { - return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; - }; - - __block BOOL setFocusModeContinuousAutoFocusCalled = NO; - - _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus - if (mode == AVCaptureFocusModeAutoFocus) { - XCTFail(@"Unexpected call to setFocusMode"); - } else if (mode == AVCaptureFocusModeContinuousAutoFocus) { - setFocusModeContinuousAutoFocusCalled = YES; - } - }; - - // Run test - [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; - - // Expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus - XCTAssertTrue(setFocusModeContinuousAutoFocusCalled); -} - -- (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus { - // AVCaptureFocusModeContinuousAutoFocus is not supported - // AVCaptureFocusModeAutoFocus is supported - _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { - return mode == AVCaptureFocusModeAutoFocus; - }; - - __block BOOL setFocusModeAutoFocusCalled = NO; - - // Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus - _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - if (mode == AVCaptureFocusModeContinuousAutoFocus) { - XCTFail(@"Unexpected call to setFocusMode"); - } else if (mode == AVCaptureFocusModeAutoFocus) { - setFocusModeAutoFocusCalled = YES; - } - }; - - // Run test - [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; - - // Expect setFocusMode:AVCaptureFocusModeAutoFocus - XCTAssertTrue(setFocusModeAutoFocusCalled); -} - -- (void)testAutoFocusWithNoModeSupported_ShouldSetNothing { - // No modes are supported - _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { - return NO; - }; - - // Don't expect any setFocus - _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - XCTFail(@"Unexpected call to setFocusMode"); - }; - - // Run test - [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; -} - -- (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus { - // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported - _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { - return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; - }; - - __block BOOL setFocusModeAutoFocusCalled = NO; - - // Expect only setFocusMode:AVCaptureFocusModeAutoFocus - _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - if (mode == AVCaptureFocusModeContinuousAutoFocus) { - XCTFail(@"Unexpected call to setFocusMode"); - } else if (mode == AVCaptureFocusModeAutoFocus) { - setFocusModeAutoFocusCalled = YES; - } - }; - - // Run test - [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; - - XCTAssertTrue(setFocusModeAutoFocusCalled); -} - -- (void)testLockedFocusWithModeNotSupported_ShouldSetNothing { - _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { - return mode == AVCaptureFocusModeContinuousAutoFocus; - }; - - // Don't expect any setFocus - _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { - XCTFail(@"Unexpected call to setFocusMode"); - }; - - // Run test - [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; -} - -- (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { - // UI is currently in landscape left orientation - _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; - // Focus point of interest is supported - _mockDevice.focusPointOfInterestSupported = YES; - - __block BOOL setFocusPointOfInterestCalled = NO; - _mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) { - if (point.x == 1 && point.y == 1) { - setFocusPointOfInterestCalled = YES; - } - }; - - // Run test - [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] - withCompletion:^(FlutterError *_Nullable error){ - }]; - - // Verify the focus point of interest has been set - XCTAssertTrue(setFocusPointOfInterestCalled); -} - -- (void)testSetFocusPoint_WhenNotSupported_ReturnsError { - // UI is currently in landscape left orientation - _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; - // Exposure point of interest is not supported - _mockDevice.focusPointOfInterestSupported = NO; - - XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; - - // Run - [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] - withCompletion:^(FlutterError *_Nullable error) { - XCTAssertNotNil(error); - XCTAssertEqualObjects(error.code, @"setFocusPointFailed"); - XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities"); - [expectation fulfill]; - }]; - - // Verify - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.swift new file mode 100644 index 000000000000..b275a8bc9a6f --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraFocusTests.swift @@ -0,0 +1,161 @@ +// 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 AVFoundation +import XCTest + +@testable import camera_avfoundation + +final class CameraFocusTests: XCTestCase { + private func createSutAndMocks() -> (FLTCam, MockCaptureDevice, MockDeviceOrientationProvider) { + let mockDevice = MockCaptureDevice() + let mockDeviceOrientationProvider = MockDeviceOrientationProvider() + + let configuration = FLTCreateTestCameraConfiguration() + configuration.captureDeviceFactory = { mockDevice } + configuration.deviceOrientationProvider = mockDeviceOrientationProvider + let camera = FLTCreateCamWithConfiguration(configuration) + + return (camera, mockDevice, mockDeviceOrientationProvider) + } + + func testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus() { + let (camera, mockDevice, _) = createSutAndMocks() + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported. + mockDevice.isFocusModeSupportedStub = { mode in + mode == .continuousAutoFocus || mode == .autoFocus + } + + var setFocusModeContinuousAutoFocusCalled = false + + mockDevice.setFocusModeStub = { mode in + // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus. + if mode == .autoFocus { + XCTFail("Unexpected call to setFocusMode") + } else if mode == .continuousAutoFocus { + setFocusModeContinuousAutoFocusCalled = true + } + } + + camera.applyFocusMode(.auto, on: mockDevice) + + XCTAssertTrue(setFocusModeContinuousAutoFocusCalled) + } + + func testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus() { + let (camera, mockDevice, _) = createSutAndMocks() + // AVCaptureFocusModeContinuousAutoFocus is not supported. + // AVCaptureFocusModeAutoFocus is supported. + mockDevice.isFocusModeSupportedStub = { mode in + mode == .autoFocus + } + + var setFocusModeAutoFocusCalled = false + + // Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus. + mockDevice.setFocusModeStub = { mode in + if mode == .continuousAutoFocus { + XCTFail("Unexpected call to setFocusMode") + } else if mode == .autoFocus { + setFocusModeAutoFocusCalled = true + } + } + + camera.applyFocusMode(.auto, on: mockDevice) + + XCTAssertTrue(setFocusModeAutoFocusCalled) + } + + func testAutoFocusWithNoModeSupported_ShouldSetNothing() { + let (camera, mockDevice, _) = createSutAndMocks() + // No modes are supported. + mockDevice.isFocusModeSupportedStub = { _ in + false + } + + // Don't expect any setFocus. + mockDevice.setFocusModeStub = { + _ in XCTFail("Unexpected call to setFocusMode") + } + + camera.applyFocusMode(.auto, on: mockDevice) + } + + func testLockedFocusWithModeSupported_ShouldSetModeAutoFocus() { + let (camera, mockDevice, _) = createSutAndMocks() + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported. + mockDevice.isFocusModeSupportedStub = { mode in + mode == .continuousAutoFocus || mode == .autoFocus + } + + var setFocusModeAutoFocusCalled = false + + // Expect only setFocusMode:AVCaptureFocusModeAutoFocus. + mockDevice.setFocusModeStub = { mode in + if mode == .continuousAutoFocus { + XCTFail("Unexpected call to setFocusMode") + } else if mode == .autoFocus { + setFocusModeAutoFocusCalled = true + } + } + + camera.applyFocusMode(.locked, on: mockDevice) + + XCTAssertTrue(setFocusModeAutoFocusCalled) + } + + func testLockedFocusWithModeNotSupported_ShouldSetNothing() { + let (camera, mockDevice, _) = createSutAndMocks() + mockDevice.isFocusModeSupportedStub = { mode in + mode == .continuousAutoFocus + } + + // Don't expect any setFocus. + mockDevice.setFocusModeStub = { _ in + XCTFail("Unexpected call to setFocusMode") + } + + camera.applyFocusMode(.locked, on: mockDevice) + } + + func testSetFocusPointWithResult_SetsFocusPointOfInterest() { + let (camera, mockDevice, mockDeviceOrientationProvider) = createSutAndMocks() + // UI is currently in landscape left orientation. + mockDeviceOrientationProvider.orientation = .landscapeLeft + // Focus point of interest is supported. + mockDevice.focusPointOfInterestSupported = true + + var setFocusPointOfInterestCalled = false + mockDevice.setFocusPointOfInterestStub = { point in + if point == CGPoint(x: 1.0, y: 1.0) { + setFocusPointOfInterestCalled = true + } + } + + camera.setFocusPoint(FCPPlatformPoint.makeWith(x: 1, y: 1)) { error in + XCTAssertNil(error) + } + + XCTAssertTrue(setFocusPointOfInterestCalled) + } + + func testSetFocusPoint_WhenNotSupported_ReturnsError() { + let (camera, mockDevice, mockDeviceOrientationProvider) = createSutAndMocks() + // UI is currently in landscape left orientation. + mockDeviceOrientationProvider.orientation = .landscapeLeft + // Focus point of interest is not supported. + mockDevice.focusPointOfInterestSupported = false + + let expectation = self.expectation(description: "Completion with error") + + camera.setFocusPoint(FCPPlatformPoint.makeWith(x: 1, y: 1)) { error in + XCTAssertNotNil(error) + XCTAssertEqual(error?.code, "setFocusPointFailed") + XCTAssertEqual(error?.message, "Device does not have focus point capabilities") + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.m deleted file mode 100644 index 095b0453298e..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.m +++ /dev/null @@ -1,271 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import AVFoundation; -@import XCTest; - -#import "CameraTestUtils.h" - -@interface MockPermissionService : NSObject -@property(nonatomic, copy) AVAuthorizationStatus (^authorizationStatusStub)(AVMediaType mediaType); -@property(nonatomic, copy) void (^requestAccessStub)(AVMediaType mediaType, void (^handler)(BOOL)); -@end - -@implementation MockPermissionService -- (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType { - return self.authorizationStatusStub ? self.authorizationStatusStub(mediaType) - : AVAuthorizationStatusNotDetermined; -} - -- (void)requestAccessForMediaType:(AVMediaType)mediaType completionHandler:(void (^)(BOOL))handler { - if (self.requestAccessStub) { - self.requestAccessStub(mediaType, handler); - } -} -@end - -@interface FLTCameraPermissionManagerTests : XCTestCase -@property(nonatomic, strong) FLTCameraPermissionManager *permissionManager; -@property(nonatomic, strong) MockPermissionService *mockService; -@end - -@implementation FLTCameraPermissionManagerTests - -- (void)setUp { - [super setUp]; - self.mockService = [[MockPermissionService alloc] init]; - self.permissionManager = - [[FLTCameraPermissionManager alloc] initWithPermissionService:self.mockService]; -} - -#pragma mark - camera permissions - -- (void)testRequestCameraPermission_completeWithoutErrorIfPreviouslyAuthorized { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Must copmlete without error if camera access was previously authorized."]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - return AVAuthorizationStatusAuthorized; - }; - - [self.permissionManager requestCameraPermissionWithCompletionHandler:^(FlutterError *error) { - if (error == nil) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} -- (void)testRequestCameraPermission_completeWithErrorIfPreviouslyDenied { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Must complete with error if camera access was previously denied."]; - FlutterError *expectedError = - [FlutterError errorWithCode:@"CameraAccessDeniedWithoutPrompt" - message:@"User has previously denied the camera access request. Go to " - @"Settings to enable camera access." - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - return AVAuthorizationStatusDenied; - }; - - [self.permissionManager requestCameraPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestCameraPermission_completeWithErrorIfRestricted { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Must complete with error if camera access is restricted."]; - FlutterError *expectedError = [FlutterError errorWithCode:@"CameraAccessRestricted" - message:@"Camera access is restricted. " - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - return AVAuthorizationStatusRestricted; - }; - - [self.permissionManager requestCameraPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestCameraPermission_completeWithoutErrorIfUserGrantAccess { - XCTestExpectation *grantedExpectation = [self - expectationWithDescription:@"Must complete without error if user choose to grant access"]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - return AVAuthorizationStatusNotDetermined; - }; - - // Mimic user choosing "allow" in permission dialog. - self.mockService.requestAccessStub = ^(AVMediaType mediaType, void (^handler)(BOOL)) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - handler(YES); - }; - - [self.permissionManager requestCameraPermissionWithCompletionHandler:^(FlutterError *error) { - if (error == nil) { - [grantedExpectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestCameraPermission_completeWithErrorIfUserDenyAccess { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Must complete with error if user choose to deny access"]; - FlutterError *expectedError = - [FlutterError errorWithCode:@"CameraAccessDenied" - message:@"User denied the camera access request." - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - return AVAuthorizationStatusNotDetermined; - }; - - // Mimic user choosing "deny" in permission dialog. - self.mockService.requestAccessStub = ^(AVMediaType mediaType, void (^handler)(BOOL)) { - XCTAssertEqualObjects(mediaType, AVMediaTypeVideo); - handler(NO); - }; - - [self.permissionManager requestCameraPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -#pragma mark - audio permissions - -- (void)testRequestAudioPermission_completeWithoutErrorIfPrevoiuslyAuthorized { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Must copmlete without error if audio access was previously authorized."]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - return AVAuthorizationStatusAuthorized; - }; - - [self.permissionManager requestAudioPermissionWithCompletionHandler:^(FlutterError *error) { - if (error == nil) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestAudioPermission_completeWithErrorIfPreviouslyDenied { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Must complete with error if audio access was previously denied."]; - FlutterError *expectedError = - [FlutterError errorWithCode:@"AudioAccessDeniedWithoutPrompt" - message:@"User has previously denied the audio access request. Go to " - @"Settings to enable audio access." - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - return AVAuthorizationStatusDenied; - }; - - [self.permissionManager requestAudioPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestAudioPermission_completeWithErrorIfRestricted { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Must complete with error if audio access is restricted."]; - FlutterError *expectedError = [FlutterError errorWithCode:@"AudioAccessRestricted" - message:@"Audio access is restricted. " - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - return AVAuthorizationStatusRestricted; - }; - - [self.permissionManager requestAudioPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestAudioPermission_completeWithoutErrorIfUserGrantAccess { - XCTestExpectation *grantedExpectation = [self - expectationWithDescription:@"Must complete without error if user choose to grant access"]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - return AVAuthorizationStatusNotDetermined; - }; - - // Mimic user choosing "allow" in permission dialog. - self.mockService.requestAccessStub = ^(AVMediaType mediaType, void (^handler)(BOOL)) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - handler(YES); - }; - - [self.permissionManager requestAudioPermissionWithCompletionHandler:^(FlutterError *error) { - if (error == nil) { - [grantedExpectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testRequestAudioPermission_completeWithErrorIfUserDenyAccess { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Must complete with error if user choose to deny access"]; - FlutterError *expectedError = [FlutterError errorWithCode:@"AudioAccessDenied" - message:@"User denied the audio access request." - details:nil]; - - self.mockService.authorizationStatusStub = ^AVAuthorizationStatus(AVMediaType mediaType) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - return AVAuthorizationStatusNotDetermined; - }; - - // Mimic user choosing "deny" in permission dialog. - self.mockService.requestAccessStub = ^(AVMediaType mediaType, void (^handler)(BOOL)) { - XCTAssertEqualObjects(mediaType, AVMediaTypeAudio); - handler(NO); - }; - - [self.permissionManager requestAudioPermissionWithCompletionHandler:^(FlutterError *error) { - if ([error isEqual:expectedError]) { - [expectation fulfill]; - } - }]; - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift new file mode 100644 index 000000000000..511e6b6a152f --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPermissionTests.swift @@ -0,0 +1,250 @@ +// 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 AVFoundation +import XCTest + +@testable import camera_avfoundation + +private final class MockPermissionService: NSObject, FLTPermissionServicing { + var authorizationStatusStub: ((AVMediaType) -> AVAuthorizationStatus)? + var requestAccessStub: ((AVMediaType, @escaping (Bool) -> Void) -> Void)? + + func authorizationStatus(for mediaType: AVMediaType) -> AVAuthorizationStatus { + return authorizationStatusStub?(mediaType) ?? .notDetermined + } + + func requestAccess(for mediaType: AVMediaType, completion: @escaping (Bool) -> Void) { + requestAccessStub?(mediaType, completion) + } +} + +final class CameraPermissionManagerTests: XCTestCase { + private func createSutAndMocks() -> (FLTCameraPermissionManager, MockPermissionService) { + let mockPermissionService = MockPermissionService() + let permissionManager = FLTCameraPermissionManager(permissionService: mockPermissionService) + + return (permissionManager, mockPermissionService) + } + + // MARK: - Camera permissions + + func testRequestCameraPermission_completeWithoutErrorIfPreviouslyAuthorized() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete without error if camera access was previously authorized.") + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .video) + return .authorized + } + permissionManager.requestCameraPermission { error in + XCTAssertNil(error) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestCameraPermission_completeWithErrorIfPreviouslyDenied() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if camera access was previously denied.") + let expectedError = FlutterError( + code: "CameraAccessDeniedWithoutPrompt", + message: + "User has previously denied the camera access request. Go to Settings to enable camera access.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .video) + return .denied + } + permissionManager.requestCameraPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestCameraPermission_completeWithErrorIfRestricted() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if camera access is restricted.") + let expectedError = FlutterError( + code: "CameraAccessRestricted", + message: "Camera access is restricted.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .video) + return .restricted + } + permissionManager.requestCameraPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestCameraPermission_completeWithoutErrorIfUserGrantAccess() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete without error if user granted access.") + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .video) + return .notDetermined + } + mockPermissionService.requestAccessStub = { mediaType, handler in + XCTAssertEqual(mediaType, .video) + // Grant access. + handler(true) + } + permissionManager.requestCameraPermission { error in + XCTAssertNil(error) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestCameraPermission_completeWithErrorIfUserDenyAccess() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if user denied access.") + let expectedError = FlutterError( + code: "CameraAccessDenied", + message: "User denied the camera access request.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .video) + return .notDetermined + } + mockPermissionService.requestAccessStub = { mediaType, handler in + XCTAssertEqual(mediaType, .video) + // Deny access. + handler(false) + } + permissionManager.requestCameraPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + // MARK: - Audio permissions + + func testRequestAudioPermission_completeWithoutErrorIfPreviouslyAuthorized() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete without error if audio access was previously authorized.") + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .audio) + return .authorized + } + permissionManager.requestAudioPermission { error in + XCTAssertNil(error) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestAudioPermission_completeWithErrorIfPreviouslyDenied() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if audio access was previously denied.") + let expectedError = FlutterError( + code: "AudioAccessDeniedWithoutPrompt", + message: + "User has previously denied the audio access request. Go to Settings to enable audio access.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .audio) + return .denied + } + permissionManager.requestAudioPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestAudioPermission_completeWithErrorIfRestricted() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if audio access is restricted.") + let expectedError = FlutterError( + code: "AudioAccessRestricted", + message: "Audio access is restricted.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .audio) + return .restricted + } + permissionManager.requestAudioPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestAudioPermission_completeWithoutErrorIfUserGrantAccess() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete without error if user granted access.") + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .audio) + return .notDetermined + } + mockPermissionService.requestAccessStub = { mediaType, handler in + XCTAssertEqual(mediaType, .audio) + // Grant access. + handler(true) + } + permissionManager.requestAudioPermission { error in + XCTAssertNil(error) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } + + func testRequestAudioPermission_completeWithErrorIfUserDenyAccess() { + let (permissionManager, mockPermissionService) = createSutAndMocks() + let expectation = self.expectation( + description: "Must complete with error if user denied access") + let expectedError = FlutterError( + code: "AudioAccessDenied", + message: "User denied the audio access request.", + details: nil) + + mockPermissionService.authorizationStatusStub = { mediaType in + XCTAssertEqual(mediaType, .audio) + return .notDetermined + } + mockPermissionService.requestAccessStub = { mediaType, handler in + XCTAssertEqual(mediaType, .audio) + // Deny access. + handler(false) + } + permissionManager.requestAudioPermission { error in + XCTAssertEqual(error, expectedError) + expectation.fulfill() + } + + waitForExpectations(timeout: 30, handler: nil) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m deleted file mode 100644 index 60dfca541683..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.m +++ /dev/null @@ -1,31 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import XCTest; -@import AVFoundation; - -@interface CameraPreviewPauseTests : XCTestCase -@end - -@implementation CameraPreviewPauseTests - -- (void)testPausePreviewWithResult_shouldPausePreview { - FLTCam *camera = [[FLTCam alloc] init]; - - [camera pausePreview]; - XCTAssertTrue(camera.isPreviewPaused); -} - -- (void)testResumePreviewWithResult_shouldResumePreview { - FLTCam *camera = [[FLTCam alloc] init]; - - [camera resumePreview]; - XCTAssertFalse(camera.isPreviewPaused); -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.swift new file mode 100644 index 000000000000..e9934b931775 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPreviewPauseTests.swift @@ -0,0 +1,26 @@ +// 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 AVFoundation +import XCTest + +@testable import camera_avfoundation + +final class CameraPreviewPauseTests: XCTestCase { + func testPausePreviewWithResult_shouldPausePreview() { + let camera = FLTCam() + + camera.pausePreview() + + XCTAssertTrue(camera.isPreviewPaused) + } + + func testResumePreviewWithResult_shouldResumePreview() { + let camera = FLTCam() + + camera.resumePreview() + + XCTAssertFalse(camera.isPreviewPaused) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m deleted file mode 100644 index 6778efb4132f..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m +++ /dev/null @@ -1,69 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import AVFoundation; -@import XCTest; - -@interface CameraPropertiesTests : XCTestCase - -@end - -@implementation CameraPropertiesTests - -#pragma mark - flash mode tests - -- (void)testFCPGetAVCaptureFlashModeForPigeonFlashMode { - XCTAssertEqual(AVCaptureFlashModeOff, - FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashModeOff)); - XCTAssertEqual(AVCaptureFlashModeAuto, - FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashModeAuto)); - XCTAssertEqual(AVCaptureFlashModeOn, - FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashModeAlways)); - XCTAssertThrows(FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashModeTorch)); -} - -#pragma mark - video format tests - -- (void)testFCPGetPixelFormatForPigeonFormat { - XCTAssertEqual(kCVPixelFormatType_32BGRA, - FCPGetPixelFormatForPigeonFormat(FCPPlatformImageFormatGroupBgra8888)); - XCTAssertEqual(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, - FCPGetPixelFormatForPigeonFormat(FCPPlatformImageFormatGroupYuv420)); -} - -#pragma mark - device orientation tests - -- (void)testFCPGetUIDeviceOrientationForPigeonDeviceOrientation { - XCTAssertEqual(UIDeviceOrientationPortraitUpsideDown, - FCPGetUIDeviceOrientationForPigeonDeviceOrientation( - FCPPlatformDeviceOrientationPortraitDown)); - XCTAssertEqual(UIDeviceOrientationLandscapeLeft, - FCPGetUIDeviceOrientationForPigeonDeviceOrientation( - FCPPlatformDeviceOrientationLandscapeLeft)); - XCTAssertEqual(UIDeviceOrientationLandscapeRight, - FCPGetUIDeviceOrientationForPigeonDeviceOrientation( - FCPPlatformDeviceOrientationLandscapeRight)); - XCTAssertEqual(UIDeviceOrientationPortrait, FCPGetUIDeviceOrientationForPigeonDeviceOrientation( - FCPPlatformDeviceOrientationPortraitUp)); -} - -- (void)testFLTGetStringForUIDeviceOrientation { - XCTAssertEqual( - FCPPlatformDeviceOrientationPortraitDown, - FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationPortraitUpsideDown)); - XCTAssertEqual(FCPPlatformDeviceOrientationLandscapeLeft, - FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationLandscapeLeft)); - XCTAssertEqual(FCPPlatformDeviceOrientationLandscapeRight, - FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationLandscapeRight)); - XCTAssertEqual(FCPPlatformDeviceOrientationPortraitUp, - FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientationPortrait)); - XCTAssertEqual(FCPPlatformDeviceOrientationPortraitUp, - FCPGetPigeonDeviceOrientationForOrientation(-1)); -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.swift new file mode 100644 index 000000000000..86de424ea21e --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.swift @@ -0,0 +1,81 @@ +// 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 AVFoundation +import Foundation +import XCTest + +@testable import camera_avfoundation + +final class CameraPropertiesTests: XCTestCase { + // MARK: - Flash Mode Tests + + func testGetAVCaptureFlashModeForPigeonFlashMode() { + XCTAssertEqual( + AVCaptureDevice.FlashMode.off, + FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashMode.off)) + XCTAssertEqual( + AVCaptureDevice.FlashMode.auto, + FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashMode.auto)) + XCTAssertEqual( + AVCaptureDevice.FlashMode.on, + FCPGetAVCaptureFlashModeForPigeonFlashMode(FCPPlatformFlashMode.always)) + + // TODO(FirentisTFW): Migrate implementation to throw Swift error in this case. + let exception = ExceptionCatcher.catchException { + _ = FCPGetAVCaptureFlashModeForPigeonFlashMode(.torch) + } + XCTAssertNotNil(exception) + } + + // MARK: - Video Format Tests + + func testGetPixelFormatForPigeonFormat() { + XCTAssertEqual( + kCVPixelFormatType_32BGRA, + FCPGetPixelFormatForPigeonFormat(FCPPlatformImageFormatGroup.bgra8888)) + XCTAssertEqual( + kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, + FCPGetPixelFormatForPigeonFormat(FCPPlatformImageFormatGroup.yuv420)) + } + + // MARK: - Device Orientation Tests + + func testGetUIDeviceOrientationForPigeonDeviceOrientation() { + XCTAssertEqual( + UIDeviceOrientation.portraitUpsideDown, + FCPGetUIDeviceOrientationForPigeonDeviceOrientation(FCPPlatformDeviceOrientation.portraitDown) + ) + XCTAssertEqual( + UIDeviceOrientation.landscapeLeft, + FCPGetUIDeviceOrientationForPigeonDeviceOrientation( + FCPPlatformDeviceOrientation.landscapeLeft)) + XCTAssertEqual( + UIDeviceOrientation.landscapeRight, + FCPGetUIDeviceOrientationForPigeonDeviceOrientation( + FCPPlatformDeviceOrientation.landscapeRight)) + XCTAssertEqual( + UIDeviceOrientation.portrait, + FCPGetUIDeviceOrientationForPigeonDeviceOrientation(FCPPlatformDeviceOrientation.portraitUp)) + } + + func testGetPigeonDeviceOrientationForUIDeviceOrientation() { + XCTAssertEqual( + FCPPlatformDeviceOrientation.portraitDown, + FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientation.portraitUpsideDown)) + XCTAssertEqual( + FCPPlatformDeviceOrientation.landscapeLeft, + FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientation.landscapeLeft)) + XCTAssertEqual( + FCPPlatformDeviceOrientation.landscapeRight, + FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientation.landscapeRight)) + XCTAssertEqual( + FCPPlatformDeviceOrientation.portraitUp, + FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientation.portrait)) + // Test default case. + XCTAssertEqual( + FCPPlatformDeviceOrientation.portraitUp, + FCPGetPigeonDeviceOrientationForOrientation(UIDeviceOrientation.unknown)) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.h new file mode 100644 index 000000000000..ae5417d2c692 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.h @@ -0,0 +1,23 @@ +// 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. + +// TODO(FirentisTFW): Remove this file when the plugin code that uses it is migrated to Swift. +// After the migration, the code should throw Swift errors instead of Objective-C exceptions, thus +// this file will not be needed. + +#import + +NS_ASSUME_NONNULL_BEGIN + +/// A utility class for catching Objective-C exceptions. +/// +/// It allows to execute a block of code and catch any exceptions that are thrown during its +/// execution. This is useful for bridging between Objective-C and Swift code, as Swift does not +/// support catching Objective-C exceptions directly. +@interface ExceptionCatcher : NSObject +/// Executes a block of code and catches any exceptions that are thrown. ++ (nullable NSException *)catchException:(void (^)(void))tryBlock; +@end + +NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.m new file mode 100644 index 000000000000..b5b29c36a0cc --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/ExceptionCatcher.m @@ -0,0 +1,17 @@ +// 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 "ExceptionCatcher.h" + +@implementation ExceptionCatcher ++ (nullable NSException *)catchException:(void (^)(void))tryBlock { + @try { + tryBlock(); + // No exception occurred. + return nil; + } @catch (NSException *exception) { + return exception; + } +} +@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.m deleted file mode 100644 index 8bcf50457874..000000000000 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.m +++ /dev/null @@ -1,41 +0,0 @@ -// 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 camera_avfoundation; -#if __has_include() -@import camera_avfoundation.Test; -#endif -@import XCTest; - -@interface QueueUtilsTests : XCTestCase - -@end - -@implementation QueueUtilsTests - -- (void)testShouldStayOnMainQueueIfCalledFromMainQueue { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Block must be run on the main queue."]; - FLTEnsureToRunOnMainQueue(^{ - if (NSThread.isMainThread) { - [expectation fulfill]; - } - }); - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -- (void)testShouldDispatchToMainQueueIfCalledFromBackgroundQueue { - XCTestExpectation *expectation = - [self expectationWithDescription:@"Block must be run on the main queue."]; - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - FLTEnsureToRunOnMainQueue(^{ - if (NSThread.isMainThread) { - [expectation fulfill]; - } - }); - }); - [self waitForExpectationsWithTimeout:30 handler:nil]; -} - -@end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.swift b/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.swift new file mode 100644 index 000000000000..1153f7239990 --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/QueueUtilsTests.swift @@ -0,0 +1,35 @@ +// 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 XCTest + +@testable import camera_avfoundation + +final class QueueUtilsTests: XCTestCase { + func testShouldStayOnMainQueueIfCalledFromMainQueue() { + let expectation = expectation(description: "Block must be run on the main queue") + + FLTEnsureToRunOnMainQueue { + if Thread.isMainThread { + expectation.fulfill() + } + } + + waitForExpectations(timeout: 30) + } + + func testShouldDispatchToMainQueueIfCalledFromBackgroundQueue() { + let expectation = expectation(description: "Block must be run on the main queue") + + DispatchQueue.global(qos: .default).async { + FLTEnsureToRunOnMainQueue { + if Thread.isMainThread { + expectation.fulfill() + } + } + } + + waitForExpectations(timeout: 30) + } +} diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/RunnerTests-Bridging-Header.h b/packages/camera/camera_avfoundation/example/ios/RunnerTests/RunnerTests-Bridging-Header.h new file mode 100644 index 000000000000..5a3f4609c5dd --- /dev/null +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/RunnerTests-Bridging-Header.h @@ -0,0 +1,24 @@ +// 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. + +// Sources. +#import "camera_avfoundation/CameraPlugin.h" +#import "camera_avfoundation/CameraPlugin_Test.h" +#import "camera_avfoundation/FLTCam.h" +#import "camera_avfoundation/FLTCamConfiguration.h" +#import "camera_avfoundation/FLTThreadSafeEventChannel.h" + +// Mocks, protocols. +#import "MockCameraDeviceDiscoverer.h" +#import "MockCaptureDevice.h" +#import "MockCaptureSession.h" +#import "MockDeviceOrientationProvider.h" +#import "MockEventChannel.h" +#import "MockFlutterBinaryMessenger.h" +#import "MockFlutterTextureRegistry.h" +#import "MockGlobalEventApi.h" + +// Utils. +#import "CameraTestUtils.h" +#import "ExceptionCatcher.h" diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCameraPermissionManager.m b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCameraPermissionManager.m index 013326a0de32..c028a98a778c 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCameraPermissionManager.m +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/FLTCameraPermissionManager.m @@ -61,11 +61,11 @@ - (void)requestPermissionForAudio:(BOOL)forAudio FlutterError *flutterError; if (forAudio) { flutterError = [FlutterError errorWithCode:@"AudioAccessRestricted" - message:@"Audio access is restricted. " + message:@"Audio access is restricted." details:nil]; } else { flutterError = [FlutterError errorWithCode:@"CameraAccessRestricted" - message:@"Camera access is restricted. " + message:@"Camera access is restricted." details:nil]; } handler(flutterError); diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h index 6e22ad5b1ac1..e7dd92a7b833 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTCam.h @@ -101,7 +101,8 @@ NS_ASSUME_NONNULL_BEGIN /// /// If @c point is nil, the focus point will reset to the center. - (void)setFocusPoint:(nullable FCPPlatformPoint *)point - withCompletion:(void (^)(FlutterError *_Nullable))completion; + withCompletion:(void (^)(FlutterError *_Nullable))completion + NS_SWIFT_NAME(setFocusPoint(_:completion:)); - (void)setExposureOffset:(double)offset; - (void)startImageStreamWithMessenger:(NSObject *)messenger; - (void)stopImageStream; diff --git a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTPermissionServicing.h b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTPermissionServicing.h index 2e65568baf83..bdec5fcb1e2f 100644 --- a/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTPermissionServicing.h +++ b/packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/include/camera_avfoundation/FLTPermissionServicing.h @@ -8,9 +8,11 @@ NS_ASSUME_NONNULL_BEGIN @protocol FLTPermissionServicing -- (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType; +- (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType + NS_SWIFT_NAME(authorizationStatus(for:)); - (void)requestAccessForMediaType:(AVMediaType)mediaType - completionHandler:(void (^)(BOOL granted))handler; + completionHandler:(void (^)(BOOL granted))handler + NS_SWIFT_NAME(requestAccess(for:completion:)); @end @interface FLTDefaultPermissionService : NSObject diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 56cd44cc6ac9..2b858f7e30b3 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.18+4 +version: 0.9.18+5 environment: sdk: ^3.4.0