Skip to content

Commit

Permalink
[camera_avfoundation] Migrate tests to Swift - part 1 (#8603)
Browse files Browse the repository at this point in the history
This PR migrates some of Objective-C tests to Swift as a part of Swift migration: [flutter/flutter/issues/119109](flutter/flutter#119109).

I kept the names of test cases the same. I also left most of the implementation comments, although I removed some of them that I considered not very helpful (e.g. "Run test").

Tests migrated in this PR:
- AvailableCamerasTests
- CameraExposureTests
- CameraFocusTests
- CameraPermissionTests
- CameraPreviewPauseTests
- CameraPropertiesTests
- QueueUtilsTests
  • Loading branch information
FirentisTFW authored Feb 12, 2025
1 parent 09888cb commit c6036d8
Show file tree
Hide file tree
Showing 22 changed files with 863 additions and 783 deletions.
4 changes: 4 additions & 0 deletions packages/camera/camera_avfoundation/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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.
Expand Down

Large diffs are not rendered by default.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Loading

0 comments on commit c6036d8

Please sign in to comment.