Skip to content

Commit ff7724c

Browse files
[camera_avfoundation] Tests backfilling - part 3 (#8853)
Backfills tests for the `FLTCam` class as part of flutter/flutter#119109 Adds tests for the `setFlashMode` method of the `FLTCam` class. ## Pre-Review Checklist
1 parent 9cc6f37 commit ff7724c

File tree

5 files changed

+160
-1
lines changed

5 files changed

+160
-1
lines changed

packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
E0CDBAC227CD9729002561D9 /* CameraTestUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */; };
5252
E12C4FF62D68C69000515E70 /* CameraPluginDelegatingMethodTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12C4FF52D68C69000515E70 /* CameraPluginDelegatingMethodTests.swift */; };
5353
E12C4FF82D68E85500515E70 /* MockFLTCameraPermissionManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E12C4FF72D68E85500515E70 /* MockFLTCameraPermissionManager.swift */; };
54+
E1A5F4E32D80259C0005BA64 /* FLTCamSetFlashModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1A5F4E22D80259C0005BA64 /* FLTCamSetFlashModeTests.swift */; };
5455
E1FFEAAD2D6C8DD700B14107 /* MockFLTCam.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FFEAAC2D6C8DD700B14107 /* MockFLTCam.swift */; };
5556
E1FFEAAF2D6CDA8C00B14107 /* CameraPluginCreateCameraTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FFEAAE2D6CDA8C00B14107 /* CameraPluginCreateCameraTests.swift */; };
5657
E1FFEAB12D6CDE5B00B14107 /* CameraPluginInitializeCameraTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1FFEAB02D6CDE5B00B14107 /* CameraPluginInitializeCameraTests.swift */; };
@@ -148,6 +149,7 @@
148149
E0CDBAC127CD9729002561D9 /* CameraTestUtils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraTestUtils.m; sourceTree = "<group>"; };
149150
E12C4FF52D68C69000515E70 /* CameraPluginDelegatingMethodTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPluginDelegatingMethodTests.swift; sourceTree = "<group>"; };
150151
E12C4FF72D68E85500515E70 /* MockFLTCameraPermissionManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFLTCameraPermissionManager.swift; sourceTree = "<group>"; };
152+
E1A5F4E22D80259C0005BA64 /* FLTCamSetFlashModeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FLTCamSetFlashModeTests.swift; sourceTree = "<group>"; };
151153
E1FFEAAC2D6C8DD700B14107 /* MockFLTCam.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockFLTCam.swift; sourceTree = "<group>"; };
152154
E1FFEAAE2D6CDA8C00B14107 /* CameraPluginCreateCameraTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPluginCreateCameraTests.swift; sourceTree = "<group>"; };
153155
E1FFEAB02D6CDE5B00B14107 /* CameraPluginInitializeCameraTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraPluginInitializeCameraTests.swift; sourceTree = "<group>"; };
@@ -206,6 +208,7 @@
206208
E12C4FF52D68C69000515E70 /* CameraPluginDelegatingMethodTests.swift */,
207209
E1FFEAAE2D6CDA8C00B14107 /* CameraPluginCreateCameraTests.swift */,
208210
E1FFEAB02D6CDE5B00B14107 /* CameraPluginInitializeCameraTests.swift */,
211+
E1A5F4E22D80259C0005BA64 /* FLTCamSetFlashModeTests.swift */,
209212
);
210213
path = RunnerTests;
211214
sourceTree = "<group>";
@@ -540,6 +543,7 @@
540543
972CA92D2D5A28C4004B846F /* QueueUtilsTests.swift in Sources */,
541544
E1FFEAB12D6CDE5B00B14107 /* CameraPluginInitializeCameraTests.swift in Sources */,
542545
979B3DFB2D5B6BC7009BDE1A /* ExceptionCatcher.m in Sources */,
546+
E1A5F4E32D80259C0005BA64 /* FLTCamSetFlashModeTests.swift in Sources */,
543547
7FD83D2B2D5BA65B00F4DB7C /* MockCaptureConnection.m in Sources */,
544548
977A25242D5A511600931E34 /* CameraPermissionTests.swift in Sources */,
545549
970ADABE2D6740A900EFDCD9 /* MockWritableData.swift in Sources */,
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright 2013 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import AVFoundation
6+
import XCTest
7+
8+
@testable import camera_avfoundation
9+
10+
final class FLTCamSetFlashModeTests: XCTestCase {
11+
private func createCamera() -> (FLTCam, MockCaptureDevice, MockCapturePhotoOutput) {
12+
let mockDevice = MockCaptureDevice()
13+
let mockCapturePhotoOutput = MockCapturePhotoOutput()
14+
15+
let configuration = FLTCreateTestCameraConfiguration()
16+
configuration.captureDeviceFactory = { mockDevice }
17+
let camera = FLTCreateCamWithConfiguration(configuration)
18+
camera.capturePhotoOutput = mockCapturePhotoOutput
19+
20+
return (camera, mockDevice, mockCapturePhotoOutput)
21+
}
22+
23+
func testSetFlashModeWithTorchMode_setsTrochModeOn() {
24+
let (camera, mockDevice, _) = createCamera()
25+
26+
mockDevice.hasTorch = true
27+
mockDevice.isTorchAvailable = true
28+
29+
var setTorchModeCalled = false
30+
mockDevice.setTorchModeStub = { torchMode in
31+
XCTAssertEqual(torchMode, .on)
32+
setTorchModeCalled = true
33+
}
34+
35+
let expectation = expectation(description: "Call completed")
36+
37+
camera.setFlashMode(.torch) { error in
38+
XCTAssertNil(error)
39+
expectation.fulfill()
40+
}
41+
42+
waitForExpectations(timeout: 30)
43+
44+
XCTAssertTrue(setTorchModeCalled)
45+
}
46+
47+
func testSetFlashModeWithTorchMode_returnError_ifHasNoTorch() {
48+
let (camera, mockDevice, _) = createCamera()
49+
50+
mockDevice.hasTorch = false
51+
52+
let expectation = expectation(description: "Call completed")
53+
54+
camera.setFlashMode(.torch) { error in
55+
XCTAssertNotNil(error)
56+
XCTAssertEqual(error?.code, "setFlashModeFailed")
57+
XCTAssertEqual(error?.message, "Device does not support torch mode")
58+
expectation.fulfill()
59+
}
60+
61+
waitForExpectations(timeout: 30)
62+
}
63+
64+
func testSetFlashModeWithTorchMode_returnError_ifTorchIsNotAvailable() {
65+
let (camera, mockDevice, _) = createCamera()
66+
67+
mockDevice.hasTorch = true
68+
mockDevice.isTorchAvailable = false
69+
70+
let expectation = expectation(description: "Call completed")
71+
72+
camera.setFlashMode(.torch) { error in
73+
XCTAssertNotNil(error)
74+
XCTAssertEqual(error?.code, "setFlashModeFailed")
75+
XCTAssertEqual(error?.message, "Torch mode is currently not available")
76+
expectation.fulfill()
77+
}
78+
79+
waitForExpectations(timeout: 30)
80+
}
81+
82+
func testSetFlashModeWithNonTorchMode_setsTrochModeOff_ifTorchModeIsEnabled() {
83+
let (camera, mockDevice, mockCapturePhotoOutput) = createCamera()
84+
85+
mockCapturePhotoOutput.supportedFlashModes = [
86+
NSNumber(value: AVCaptureDevice.FlashMode.auto.rawValue)
87+
]
88+
89+
mockDevice.hasFlash = true
90+
// Torch mode is enabled
91+
mockDevice.getTorchModeStub = { .on }
92+
93+
var setTorchModeCalled = false
94+
mockDevice.setTorchModeStub = { torchMode in
95+
XCTAssertEqual(torchMode, .off)
96+
setTorchModeCalled = true
97+
}
98+
99+
let expectation = expectation(description: "Call completed")
100+
101+
camera.setFlashMode(.auto) { error in
102+
XCTAssertNil(error)
103+
expectation.fulfill()
104+
}
105+
106+
waitForExpectations(timeout: 30)
107+
108+
XCTAssertTrue(setTorchModeCalled)
109+
}
110+
111+
func testSetFlashModeWithNonTorchMode_returnError_ifHasNoFlash() {
112+
let (camera, mockDevice, _) = createCamera()
113+
114+
mockDevice.hasFlash = false
115+
116+
let expectation = expectation(description: "Call completed")
117+
118+
camera.setFlashMode(.auto) { error in
119+
XCTAssertNotNil(error)
120+
XCTAssertEqual(error?.code, "setFlashModeFailed")
121+
XCTAssertEqual(error?.message, "Device does not have flash capabilities")
122+
expectation.fulfill()
123+
}
124+
125+
waitForExpectations(timeout: 30)
126+
}
127+
128+
func testSetFlashModeWithNonTorchMode_returnError_ifModeIsNotSupported() {
129+
let (camera, mockDevice, mockCapturePhotoOutput) = createCamera()
130+
131+
// No flash modes are supported
132+
mockCapturePhotoOutput.supportedFlashModes = []
133+
134+
mockDevice.hasFlash = true
135+
136+
let expectation = expectation(description: "Call completed")
137+
138+
camera.setFlashMode(.auto) { error in
139+
XCTAssertNotNil(error)
140+
XCTAssertEqual(error?.code, "setFlashModeFailed")
141+
XCTAssertEqual(error?.message, "Device does not support this specific flash mode")
142+
expectation.fulfill()
143+
}
144+
145+
waitForExpectations(timeout: 30)
146+
}
147+
}

packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ NS_ASSUME_NONNULL_BEGIN
3333
/// Overrides the default implementation of setting torch mode.
3434
/// @param mode The torch mode being set
3535
@property(nonatomic, copy) void (^setTorchModeStub)(AVCaptureTorchMode mode);
36+
@property(nonatomic, copy) AVCaptureTorchMode (^getTorchModeStub)(void);
3637
@property(nonatomic, assign) BOOL flashModeSupported;
3738

3839
// Focus

packages/camera/camera_avfoundation/example/ios/RunnerTests/Mocks/MockCaptureDevice.m

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ - (void)setTorchMode:(AVCaptureTorchMode)mode {
3535
}
3636
}
3737

38+
- (AVCaptureTorchMode)torchMode {
39+
if (self.getTorchModeStub) {
40+
return self.getTorchModeStub();
41+
}
42+
return AVCaptureTorchModeOff;
43+
}
44+
3845
- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)mode {
3946
if (self.isFocusModeSupportedStub) {
4047
return self.isFocusModeSupportedStub(mode);

packages/camera/camera_avfoundation/example/ios/RunnerTests/PhotoCaptureTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ final class PhotoCaptureTests: XCTestCase {
157157
let captureDeviceMock = MockCaptureDevice()
158158
captureDeviceMock.hasTorch = true
159159
captureDeviceMock.isTorchAvailable = true
160-
captureDeviceMock.torchMode = .auto
160+
captureDeviceMock.getTorchModeStub = { .auto }
161161
captureDeviceMock.setTorchModeStub = { mode in
162162
if mode == .on {
163163
setTorchExpectation.fulfill()

0 commit comments

Comments
 (0)