|
8 | 8 | #endif |
9 | 9 | @import XCTest; |
10 | 10 | @import AVFoundation; |
11 | | -#import <OCMock/OCMock.h> |
| 11 | + |
| 12 | +#import "CameraTestUtils.h" |
| 13 | +#import "MockCaptureDeviceController.h" |
| 14 | +#import "MockDeviceOrientationProvider.h" |
12 | 15 |
|
13 | 16 | @interface CameraFocusTests : XCTestCase |
14 | 17 | @property(readonly, nonatomic) FLTCam *camera; |
15 | | -@property(readonly, nonatomic) id mockDevice; |
16 | | -@property(readonly, nonatomic) id mockUIDevice; |
| 18 | +@property(readonly, nonatomic) MockCaptureDeviceController *mockDevice; |
| 19 | +@property(readonly, nonatomic) MockDeviceOrientationProvider *mockDeviceOrientationProvider; |
17 | 20 | @end |
18 | 21 |
|
19 | 22 | @implementation CameraFocusTests |
20 | 23 |
|
21 | 24 | - (void)setUp { |
22 | | - _camera = [[FLTCam alloc] init]; |
23 | | - _mockDevice = OCMClassMock([AVCaptureDevice class]); |
24 | | - _mockUIDevice = OCMPartialMock([UIDevice currentDevice]); |
25 | | -} |
26 | | - |
27 | | -- (void)tearDown { |
28 | | - [_mockDevice stopMocking]; |
29 | | - [_mockUIDevice stopMocking]; |
| 25 | + MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init]; |
| 26 | + _mockDevice = mockDevice; |
| 27 | + _mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init]; |
| 28 | + |
| 29 | + _camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings( |
| 30 | + nil, nil, nil, |
| 31 | + ^id<FLTCaptureDeviceControlling>(void) { |
| 32 | + return mockDevice; |
| 33 | + }, |
| 34 | + _mockDeviceOrientationProvider); |
30 | 35 | } |
31 | 36 |
|
32 | 37 | - (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus { |
33 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
34 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); |
35 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
36 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); |
37 | | - |
38 | | - // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus |
39 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; |
| 38 | + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeContinuousAutoFocus are supported |
| 39 | + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { |
| 40 | + return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; |
| 41 | + }; |
| 42 | + |
| 43 | + __block BOOL setFocusModeContinuousAutoFocusCalled = NO; |
| 44 | + |
| 45 | + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { |
| 46 | + // Don't expect setFocusMode:AVCaptureFocusModeAutoFocus |
| 47 | + if (mode == AVCaptureFocusModeAutoFocus) { |
| 48 | + XCTFail(@"Unexpected call to setFocusMode"); |
| 49 | + } else if (mode == AVCaptureFocusModeContinuousAutoFocus) { |
| 50 | + setFocusModeContinuousAutoFocusCalled = YES; |
| 51 | + } |
| 52 | + }; |
40 | 53 |
|
41 | 54 | // Run test |
42 | 55 | [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; |
43 | 56 |
|
44 | 57 | // Expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus |
45 | | - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus]); |
| 58 | + XCTAssertTrue(setFocusModeContinuousAutoFocusCalled); |
46 | 59 | } |
47 | 60 |
|
48 | 61 | - (void)testAutoFocusWithContinuousModeNotSupported_ShouldSetAutoFocus { |
49 | 62 | // AVCaptureFocusModeContinuousAutoFocus is not supported |
50 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) |
51 | | - .andReturn(false); |
52 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
53 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); |
| 63 | + // AVCaptureFocusModeAutoFocus is supported |
| 64 | + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { |
| 65 | + return mode == AVCaptureFocusModeAutoFocus; |
| 66 | + }; |
| 67 | + |
| 68 | + __block BOOL setFocusModeAutoFocusCalled = NO; |
54 | 69 |
|
55 | 70 | // Don't expect setFocusMode:AVCaptureFocusModeContinuousAutoFocus |
56 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; |
| 71 | + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { |
| 72 | + if (mode == AVCaptureFocusModeContinuousAutoFocus) { |
| 73 | + XCTFail(@"Unexpected call to setFocusMode"); |
| 74 | + } else if (mode == AVCaptureFocusModeAutoFocus) { |
| 75 | + setFocusModeAutoFocusCalled = YES; |
| 76 | + } |
| 77 | + }; |
57 | 78 |
|
58 | 79 | // Run test |
59 | 80 | [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; |
60 | 81 |
|
61 | 82 | // Expect setFocusMode:AVCaptureFocusModeAutoFocus |
62 | | - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]); |
| 83 | + XCTAssertTrue(setFocusModeAutoFocusCalled); |
63 | 84 | } |
64 | 85 |
|
65 | 86 | - (void)testAutoFocusWithNoModeSupported_ShouldSetNothing { |
66 | | - // AVCaptureFocusModeContinuousAutoFocus is not supported |
67 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) |
68 | | - .andReturn(false); |
69 | | - // AVCaptureFocusModeContinuousAutoFocus is not supported |
70 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false); |
| 87 | + // No modes are supported |
| 88 | + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { |
| 89 | + return NO; |
| 90 | + }; |
71 | 91 |
|
72 | 92 | // Don't expect any setFocus |
73 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; |
74 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; |
| 93 | + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { |
| 94 | + XCTFail(@"Unexpected call to setFocusMode"); |
| 95 | + }; |
75 | 96 |
|
76 | 97 | // Run test |
77 | 98 | [_camera applyFocusMode:FCPPlatformFocusModeAuto onDevice:_mockDevice]; |
78 | 99 | } |
79 | 100 |
|
80 | 101 | - (void)testLockedFocusWithModeSupported_ShouldSetModeAutoFocus { |
81 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
82 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); |
83 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
84 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(true); |
85 | | - |
86 | | - // Don't expect any setFocus |
87 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; |
| 102 | + // AVCaptureFocusModeContinuousAutoFocus and AVCaptureFocusModeAutoFocus are supported |
| 103 | + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { |
| 104 | + return mode == AVCaptureFocusModeContinuousAutoFocus || mode == AVCaptureFocusModeAutoFocus; |
| 105 | + }; |
| 106 | + |
| 107 | + __block BOOL setFocusModeAutoFocusCalled = NO; |
| 108 | + |
| 109 | + // Expect only setFocusMode:AVCaptureFocusModeAutoFocus |
| 110 | + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { |
| 111 | + if (mode == AVCaptureFocusModeContinuousAutoFocus) { |
| 112 | + XCTFail(@"Unexpected call to setFocusMode"); |
| 113 | + } else if (mode == AVCaptureFocusModeAutoFocus) { |
| 114 | + setFocusModeAutoFocusCalled = YES; |
| 115 | + } |
| 116 | + }; |
88 | 117 |
|
89 | 118 | // Run test |
90 | 119 | [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; |
91 | 120 |
|
92 | | - // Expect setFocusMode:AVCaptureFocusModeAutoFocus |
93 | | - OCMVerify([_mockDevice setFocusMode:AVCaptureFocusModeAutoFocus]); |
| 121 | + XCTAssertTrue(setFocusModeAutoFocusCalled); |
94 | 122 | } |
95 | 123 |
|
96 | 124 | - (void)testLockedFocusWithModeNotSupported_ShouldSetNothing { |
97 | | - // AVCaptureFocusModeContinuousAutoFocus is supported |
98 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]).andReturn(true); |
99 | | - // AVCaptureFocusModeContinuousAutoFocus is not supported |
100 | | - OCMStub([_mockDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]).andReturn(false); |
| 125 | + _mockDevice.isFocusModeSupportedStub = ^BOOL(AVCaptureFocusMode mode) { |
| 126 | + return mode == AVCaptureFocusModeContinuousAutoFocus; |
| 127 | + }; |
101 | 128 |
|
102 | 129 | // Don't expect any setFocus |
103 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeContinuousAutoFocus]; |
104 | | - [[_mockDevice reject] setFocusMode:AVCaptureFocusModeAutoFocus]; |
| 130 | + _mockDevice.setFocusModeStub = ^(AVCaptureFocusMode mode) { |
| 131 | + XCTFail(@"Unexpected call to setFocusMode"); |
| 132 | + }; |
105 | 133 |
|
106 | 134 | // Run test |
107 | 135 | [_camera applyFocusMode:FCPPlatformFocusModeLocked onDevice:_mockDevice]; |
108 | 136 | } |
109 | 137 |
|
110 | 138 | - (void)testSetFocusPointWithResult_SetsFocusPointOfInterest { |
111 | 139 | // UI is currently in landscape left orientation |
112 | | - OCMStub([(UIDevice *)_mockUIDevice orientation]).andReturn(UIDeviceOrientationLandscapeLeft); |
| 140 | + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; |
113 | 141 | // Focus point of interest is supported |
114 | | - OCMStub([_mockDevice isFocusPointOfInterestSupported]).andReturn(true); |
115 | | - // Set mock device as the current capture device |
116 | | - [_camera setValue:_mockDevice forKey:@"captureDevice"]; |
| 142 | + _mockDevice.focusPointOfInterestSupported = YES; |
| 143 | + |
| 144 | + __block BOOL setFocusPointOfInterestCalled = NO; |
| 145 | + _mockDevice.setFocusPointOfInterestStub = ^(CGPoint point) { |
| 146 | + if (point.x == 1 && point.y == 1) { |
| 147 | + setFocusPointOfInterestCalled = YES; |
| 148 | + } |
| 149 | + }; |
117 | 150 |
|
118 | 151 | // Run test |
119 | 152 | [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] |
120 | 153 | withCompletion:^(FlutterError *_Nullable error){ |
121 | 154 | }]; |
122 | 155 |
|
123 | 156 | // Verify the focus point of interest has been set |
124 | | - OCMVerify([_mockDevice setFocusPointOfInterest:CGPointMake(1, 1)]); |
| 157 | + XCTAssertTrue(setFocusPointOfInterestCalled); |
| 158 | +} |
| 159 | + |
| 160 | +- (void)testSetFocusPoint_WhenNotSupported_ReturnsError { |
| 161 | + // UI is currently in landscape left orientation |
| 162 | + _mockDeviceOrientationProvider.orientation = UIDeviceOrientationLandscapeLeft; |
| 163 | + // Exposure point of interest is not supported |
| 164 | + _mockDevice.focusPointOfInterestSupported = NO; |
| 165 | + |
| 166 | + XCTestExpectation *expectation = [self expectationWithDescription:@"Completion with error"]; |
| 167 | + |
| 168 | + // Run |
| 169 | + [_camera setFocusPoint:[FCPPlatformPoint makeWithX:1 y:1] |
| 170 | + withCompletion:^(FlutterError *_Nullable error) { |
| 171 | + XCTAssertNotNil(error); |
| 172 | + XCTAssertEqualObjects(error.code, @"setFocusPointFailed"); |
| 173 | + XCTAssertEqualObjects(error.message, @"Device does not have focus point capabilities"); |
| 174 | + [expectation fulfill]; |
| 175 | + }]; |
| 176 | + |
| 177 | + // Verify |
| 178 | + [self waitForExpectationsWithTimeout:1 handler:nil]; |
125 | 179 | } |
126 | 180 |
|
127 | 181 | @end |
0 commit comments