|
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