Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use DI for mocking dependencies
  • Loading branch information
mchudy committed Jan 14, 2025
commit c0b986c26a7107a5ce93b8501f43be15d737f92c
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+1

* Introduces new protocols `FLTCaptureDeviceControlling` and `FLTDeviceOrientationProviding`

## 0.9.18

* Adds API support query for image streaming.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
7F56D0382D1EDDCE005676A5 /* CameraPermissionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E0B0D2BA27DFF2AF00E71E4B /* CameraPermissionTests.m */; };
7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */; };
7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */; };
7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7FA99E582D22C75300582559 /* CameraExposureTests.m */; };
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
Expand Down Expand Up @@ -82,6 +83,7 @@
7F87E8032D02FF8C00A3549C /* MockCaptureDeviceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockCaptureDeviceController.h; sourceTree = "<group>"; };
7F87E80A2D0325B200A3549C /* MockDeviceOrientationProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockDeviceOrientationProvider.h; sourceTree = "<group>"; };
7F87E80B2D0325D700A3549C /* MockDeviceOrientationProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockDeviceOrientationProvider.m; sourceTree = "<group>"; };
7FA99E582D22C75300582559 /* CameraExposureTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CameraExposureTests.m; sourceTree = "<group>"; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -140,6 +142,7 @@
7F87E8012D01FD5600A3549C /* MockCaptureDeviceController.m */,
7D5FCCD32AEF9D0200FB7108 /* CameraSettingsTests.m */,
03BB766A2665316900CE5A93 /* CameraFocusTests.m */,
7FA99E582D22C75300582559 /* CameraExposureTests.m */,
03BB767226653ABE00CE5A93 /* CameraOrientationTests.m */,
03BB766C2665316900CE5A93 /* Info.plist */,
033B94BD269C40A200B4DF97 /* CameraMethodChannelTests.m */,
Expand Down Expand Up @@ -462,6 +465,7 @@
03BB766B2665316900CE5A93 /* CameraFocusTests.m in Sources */,
7F87E8022D01FD6F00A3549C /* MockCaptureDeviceController.m in Sources */,
7D5FCCD42AEF9D0200FB7108 /* CameraSettingsTests.m in Sources */,
7FA99E592D22C75300582559 /* CameraExposureTests.m in Sources */,
E487C86026D686A10034AC92 /* CameraPreviewPauseTests.m in Sources */,
7F87E80C2D0325D900A3549C /* MockDeviceOrientationProvider.m in Sources */,
E071CF7427B31DE4006EF3BA /* FLTCamSampleBufferTests.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
@import XCTest;
@import AVFoundation;

#import "CameraTestUtils.h"
#import "MockCaptureDeviceController.h"
#import "MockDeviceOrientationProvider.h"

Expand All @@ -18,12 +19,16 @@ @interface CameraExposureTests : XCTestCase
@implementation CameraExposureTests

- (void)setUp {
_camera = [[FLTCam alloc] init];
_mockDevice = [[MockCaptureDeviceController alloc] init];
MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init];
_mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init];
_mockDevice = mockDevice;

[_camera setValue:_mockDevice forKey:@"captureDevice"];
[_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"];
_camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
nil, nil, nil,
^id<FLTCaptureDeviceControlling>(void) {
return mockDevice;
},
_mockDeviceOrientationProvider);
}

- (void)testSetExposurePointWithResult_SetsExposurePointOfInterest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@import XCTest;
@import AVFoundation;

#import "CameraTestUtils.h"
#import "MockCaptureDeviceController.h"
#import "MockDeviceOrientationProvider.h"

Expand All @@ -21,12 +22,16 @@ @interface CameraFocusTests : XCTestCase
@implementation CameraFocusTests

- (void)setUp {
_camera = [[FLTCam alloc] init];
_mockDevice = [[MockCaptureDeviceController alloc] init];
MockCaptureDeviceController *mockDevice = [[MockCaptureDeviceController alloc] init];
_mockDevice = mockDevice;
_mockDeviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init];

[_camera setValue:_mockDevice forKey:@"captureDevice"];
[_camera setValue:_mockDeviceOrientationProvider forKey:@"deviceOrientationProvider"];
_camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
nil, nil, nil,
^id<FLTCaptureDeviceControlling>(void) {
return mockDevice;
},
_mockDeviceOrientationProvider);
}

- (void)testAutoFocusWithContinuousModeSupported_ShouldSetContinuousAutoFocus {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ - (void)testSettings_shouldPassConfigurationToCameraDeviceAndWriter {
[[TestMediaSettingsAVWrapper alloc] initWithTestCase:self];

FLTCam *camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
dispatch_queue_create("test", NULL), settings, injectedWrapper, nil);
dispatch_queue_create("test", NULL), settings, injectedWrapper, nil, nil);

// Expect FPS configuration is passed to camera device.
[self waitForExpectations:@[
Expand Down Expand Up @@ -211,7 +211,7 @@ - (void)testSettings_ShouldSelectFormatWhichSupports60FPS {
enableAudio:gTestEnableAudio];

FLTCam *camera = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
dispatch_queue_create("test", NULL), settings, nil, nil);
dispatch_queue_create("test", NULL), settings, nil, nil, nil);

AVFrameRateRange *range = camera.captureDevice.activeFormat.videoSupportedFrameRateRanges[0];
XCTAssertLessThanOrEqual(range.minFrameRate, 60);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ extern FLTCam *_Nullable FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
dispatch_queue_t _Nullable captureSessionQueue,
FCPPlatformMediaSettings *_Nullable mediaSettings,
FLTCamMediaSettingsAVWrapper *_Nullable mediaSettingsAVWrapper,
CaptureDeviceFactory _Nullable captureDeviceFactory);
CaptureDeviceFactory _Nullable captureDeviceFactory,
id<FLTDeviceOrientationProviding> _Nullable deviceOrientationProvider);

extern FLTCam *FLTCreateCamWithCaptureSessionQueue(dispatch_queue_t captureSessionQueue);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
@import AVFoundation;
@import camera_avfoundation;

#import "MockDeviceOrientationProvider.h"

static FCPPlatformMediaSettings *FCPGetDefaultMediaSettings(
FCPPlatformResolutionPreset resolutionPreset) {
return [FCPPlatformMediaSettings makeWithResolutionPreset:resolutionPreset
Expand All @@ -18,13 +20,14 @@
}

FLTCam *FLTCreateCamWithCaptureSessionQueue(dispatch_queue_t captureSessionQueue) {
return FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, nil);
return FLTCreateCamWithCaptureSessionQueueAndMediaSettings(captureSessionQueue, nil, nil, nil,
nil);
}

FLTCam *FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
dispatch_queue_t captureSessionQueue, FCPPlatformMediaSettings *mediaSettings,
FLTCamMediaSettingsAVWrapper *mediaSettingsAVWrapper,
CaptureDeviceFactory captureDeviceFactory) {
FLTCamMediaSettingsAVWrapper *mediaSettingsAVWrapper, CaptureDeviceFactory captureDeviceFactory,
id<FLTDeviceOrientationProviding> deviceOrientationProvider) {
if (!mediaSettings) {
mediaSettings = FCPGetDefaultMediaSettings(FCPPlatformResolutionPresetMedium);
}
Expand All @@ -33,6 +36,10 @@
mediaSettingsAVWrapper = [[FLTCamMediaSettingsAVWrapper alloc] init];
}

if (!deviceOrientationProvider) {
deviceOrientationProvider = [[MockDeviceOrientationProvider alloc] init];
}

id inputMock = OCMClassMock([AVCaptureDeviceInput class]);
OCMStub([inputMock deviceInputWithDevice:[OCMArg any] error:[OCMArg setTo:nil]])
.andReturn(inputMock);
Expand Down Expand Up @@ -94,6 +101,7 @@
videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) {
return CMVideoFormatDescriptionGetDimensions(format.formatDescription);
}
deviceOrientationProvider:deviceOrientationProvider
error:nil];

id captureVideoDataOutputMock = [OCMockObject niceMockForClass:[AVCaptureVideoDataOutput class]];
Expand Down Expand Up @@ -156,17 +164,18 @@
OCMStub([audioSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);

return [[FLTCam alloc]
initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset)
mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init]
orientation:UIDeviceOrientationPortrait
videoCaptureSession:captureSession
audioCaptureSession:audioSessionMock
captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL)
captureDeviceFactory:^id<FLTCaptureDeviceControlling>(void) {
return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice];
}
videoDimensionsForFormat:videoDimensionsForFormat
error:nil];
initWithMediaSettings:FCPGetDefaultMediaSettings(resolutionPreset)
mediaSettingsAVWrapper:[[FLTCamMediaSettingsAVWrapper alloc] init]
orientation:UIDeviceOrientationPortrait
videoCaptureSession:captureSession
audioCaptureSession:audioSessionMock
captureSessionQueue:dispatch_queue_create("capture_session_queue", NULL)
captureDeviceFactory:^id<FLTCaptureDeviceControlling>(void) {
return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDevice];
}
videoDimensionsForFormat:videoDimensionsForFormat
deviceOrientationProvider:[[MockDeviceOrientationProvider alloc] init]
error:nil];
}

CMSampleBufferRef FLTCreateTestSampleBuffer(void) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,9 +188,11 @@ - (void)testCaptureToFile_handlesTorchMode {
(void *)FLTCaptureSessionQueueSpecific, NULL);

FLTCam *cam = FLTCreateCamWithCaptureSessionQueueAndMediaSettings(
captureSessionQueue, nil, nil, ^id<FLTCaptureDeviceControlling>(void) {
captureSessionQueue, nil, nil,
^id<FLTCaptureDeviceControlling>(void) {
return [[FLTDefaultCaptureDeviceController alloc] initWithDevice:captureDeviceMock];
});
},
nil);

AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings];
id mockSettings = OCMClassMock([AVCapturePhotoSettings class]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName
videoDimensionsForFormat:^CMVideoDimensions(AVCaptureDeviceFormat *format) {
return CMVideoFormatDescriptionGetDimensions(format.formatDescription);
}
deviceOrientationProvider:[[FLTDefaultDeviceOrientationProvider alloc] init]
error:error];
}

Expand Down Expand Up @@ -217,6 +218,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory
videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat
deviceOrientationProvider:(id<FLTDeviceOrientationProviding>)deviceOrientationProvider
error:(NSError **)error {
self = [super init];
NSAssert(self, @"super init cannot be nil");
Expand Down Expand Up @@ -268,7 +270,7 @@ - (instancetype)initWithMediaSettings:(FCPPlatformMediaSettings *)mediaSettings
_motionManager = [[CMMotionManager alloc] init];
[_motionManager startAccelerometerUpdates];

_deviceOrientationProvider = [[FLTDefaultDeviceOrientationProvider alloc] init];
_deviceOrientationProvider = deviceOrientationProvider;

if (_mediaSettings.framesPerSecond) {
// The frame rate can be changed only on a locked for configuration device.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#import "FLTCam.h"
#import "FLTCaptureDeviceControlling.h"
#import "FLTDeviceOrientationProviding.h"
#import "FLTSavePhotoDelegate.h"

/// Determines the video dimensions (width and height) for a given capture device format.
Expand Down Expand Up @@ -75,6 +76,7 @@ typedef id<FLTCaptureDeviceControlling> (^CaptureDeviceFactory)(void);
captureSessionQueue:(dispatch_queue_t)captureSessionQueue
captureDeviceFactory:(CaptureDeviceFactory)captureDeviceFactory
videoDimensionsForFormat:(VideoDimensionsForFormat)videoDimensionsForFormat
deviceOrientationProvider:(id<FLTDeviceOrientationProviding>)deviceOrientationProvider
error:(NSError **)error;

/// Start streaming images.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
NS_ASSUME_NONNULL_BEGIN

/// Queue-specific context data to be associated with the capture session queue.
extern const char *FLTCaptureSessionQueueSpecific;
extern const char* FLTCaptureSessionQueueSpecific;

/// Ensures the given block to be run on the main queue.
/// If caller site is already on the main queue, the block will be run
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_avfoundation/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
version: 0.9.18+1

environment:
sdk: ^3.4.0
Expand Down