This repository was archived by the owner on Feb 22, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
[image_picker] Default to gallery instead of camera when picking multiple images on pre-iOS 14 devices. #4718
Merged
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
b1dfdcf
Default to image gallery when picking multiple images
mvanbeusekom 9d15c59
Add additional unit-tests
mvanbeusekom bd955e9
Refactored tests to expose private interface in separate test header.
mvanbeusekom e8333f8
Adds declaration comments.
mvanbeusekom f60f73d
Fix spelling error in changelog
mvanbeusekom 3921f8d
Fix formatting
mvanbeusekom 2b5555a
Merged in unit test refactoring
mvanbeusekom 8707cd8
Applied feedback from PR
mvanbeusekom 441dea1
Refactored tests to expose private interface in separate test header.
mvanbeusekom 6fc92d6
Adds declaration comments.
mvanbeusekom 3a6d1b5
Fix spelling error in changelog
mvanbeusekom 69a41d8
Fix formatting
mvanbeusekom 31442f3
Remove private headers from umbrella
mvanbeusekom 86a2987
Merge branch 'image_picker_test_header' into issue/96903
mvanbeusekom 9b71661
Removes the pickImageWithUIImagePicker trampoline method.
mvanbeusekom 76131a7
Use call.arguments instead of self.arguments.
mvanbeusekom 84abc6f
Merge remote-tracking branch 'upstream/main' into issue/96903
mvanbeusekom 35dc1ab
Merge remote-tracking branch 'upstream/main' into issue/96903
mvanbeusekom 5ea21c7
Apply feedback on PR
mvanbeusekom 134ba8b
Refactored FLTImagePickerPlugin not to be stateful
mvanbeusekom 6bbd53c
Added declaration comments as required by style
mvanbeusekom f9bfe66
Apply fixes for nits
mvanbeusekom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,127 +23,161 @@ - (UIViewController *)presentedViewController { | |
@end | ||
|
||
@interface ImagePickerPluginTests : XCTestCase | ||
@property(readonly, nonatomic) id mockUIImagePicker; | ||
@property(readonly, nonatomic) id mockAVCaptureDevice; | ||
|
||
@end | ||
|
||
@implementation ImagePickerPluginTests | ||
|
||
- (void)setUp { | ||
_mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
_mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); | ||
} | ||
|
||
- (void)testPluginPickImageDeviceBack { | ||
id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); | ||
// UIImagePickerControllerSourceTypeCamera is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
[mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
.andReturn(YES); | ||
|
||
// UIImagePickerControllerCameraDeviceRear is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear])) | ||
[mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear])) | ||
.andReturn(YES); | ||
|
||
// AVAuthorizationStatusAuthorized is supported | ||
OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
.andReturn(AVAuthorizationStatusAuthorized); | ||
|
||
// Run test | ||
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; | ||
FlutterMethodCall *call = | ||
[FlutterMethodCall methodCallWithMethodName:@"pickImage" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
[plugin setImagePickerControllerOverrides:@[ controller ]]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
|
||
XCTAssertEqual([plugin getImagePickerController].cameraDevice, | ||
UIImagePickerControllerCameraDeviceRear); | ||
XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear); | ||
} | ||
|
||
- (void)testPluginPickImageDeviceFront { | ||
id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); | ||
// UIImagePickerControllerSourceTypeCamera is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
[mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
.andReturn(YES); | ||
|
||
// UIImagePickerControllerCameraDeviceFront is supported | ||
OCMStub(ClassMethod([_mockUIImagePicker | ||
isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront])) | ||
OCMStub(ClassMethod( | ||
[mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront])) | ||
.andReturn(YES); | ||
|
||
// AVAuthorizationStatusAuthorized is supported | ||
OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
.andReturn(AVAuthorizationStatusAuthorized); | ||
|
||
// Run test | ||
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; | ||
FlutterMethodCall *call = | ||
[FlutterMethodCall methodCallWithMethodName:@"pickImage" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
[plugin setImagePickerControllerOverrides:@[ controller ]]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
|
||
XCTAssertEqual([plugin getImagePickerController].cameraDevice, | ||
UIImagePickerControllerCameraDeviceFront); | ||
XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront); | ||
} | ||
|
||
- (void)testPluginPickVideoDeviceBack { | ||
id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); | ||
// UIImagePickerControllerSourceTypeCamera is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
[mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
.andReturn(YES); | ||
|
||
// UIImagePickerControllerCameraDeviceRear is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear])) | ||
[mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear])) | ||
.andReturn(YES); | ||
|
||
// AVAuthorizationStatusAuthorized is supported | ||
OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
.andReturn(AVAuthorizationStatusAuthorized); | ||
|
||
// Run test | ||
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; | ||
FlutterMethodCall *call = | ||
[FlutterMethodCall methodCallWithMethodName:@"pickVideo" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(0)}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
[plugin setImagePickerControllerOverrides:@[ controller ]]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
|
||
XCTAssertEqual([plugin getImagePickerController].cameraDevice, | ||
UIImagePickerControllerCameraDeviceRear); | ||
XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceRear); | ||
} | ||
|
||
- (void)testPluginPickVideoDeviceFront { | ||
id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); | ||
|
||
// UIImagePickerControllerSourceTypeCamera is supported | ||
OCMStub(ClassMethod( | ||
[_mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
[mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) | ||
.andReturn(YES); | ||
|
||
// UIImagePickerControllerCameraDeviceFront is supported | ||
OCMStub(ClassMethod([_mockUIImagePicker | ||
isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront])) | ||
OCMStub(ClassMethod( | ||
[mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceFront])) | ||
.andReturn(YES); | ||
|
||
// AVAuthorizationStatusAuthorized is supported | ||
OCMStub([_mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) | ||
.andReturn(AVAuthorizationStatusAuthorized); | ||
|
||
// Run test | ||
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; | ||
FlutterMethodCall *call = | ||
[FlutterMethodCall methodCallWithMethodName:@"pickVideo" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
[plugin setImagePickerControllerOverrides:@[ controller ]]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
|
||
XCTAssertEqual([plugin getImagePickerController].cameraDevice, | ||
UIImagePickerControllerCameraDeviceFront); | ||
XCTAssertEqual(controller.cameraDevice, UIImagePickerControllerCameraDeviceFront); | ||
} | ||
|
||
- (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 { | ||
if (@available(iOS 14, *)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jmagman Relevant to our discussions about test matrixes in this repository: we won't ever actually test this in CI currently. |
||
return; | ||
} | ||
|
||
id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); | ||
id photoLibrary = OCMClassMock([PHPhotoLibrary class]); | ||
OCMStub(ClassMethod([photoLibrary authorizationStatus])) | ||
.andReturn(PHAuthorizationStatusAuthorized); | ||
|
||
FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; | ||
[plugin setImagePickerControllerOverrides:@[ mockUIImagePicker ]]; | ||
FlutterMethodCall *call = [FlutterMethodCall methodCallWithMethodName:@"pickMultiImage" | ||
arguments:@{ | ||
@"maxWidth" : @(100), | ||
@"maxHeight" : @(200), | ||
@"imageQuality" : @(50), | ||
}]; | ||
|
||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
|
||
OCMVerify(times(1), | ||
[mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); | ||
} | ||
|
||
#pragma mark - Test camera devices, no op on simulators | ||
|
@@ -156,15 +190,18 @@ - (void)testPluginPickImageDeviceCancelClickMultipleTimes { | |
FlutterMethodCall *call = | ||
[FlutterMethodCall methodCallWithMethodName:@"pickImage" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(1)}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
plugin.imagePickerControllerOverrides = @[ controller ]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
plugin.result = ^(id result) { | ||
|
||
}; | ||
|
||
// To ensure the flow does not crash by multiple cancel call | ||
[plugin imagePickerControllerDidCancel:[plugin getImagePickerController]]; | ||
[plugin imagePickerControllerDidCancel:[plugin getImagePickerController]]; | ||
[plugin imagePickerControllerDidCancel:controller]; | ||
[plugin imagePickerControllerDidCancel:controller]; | ||
} | ||
|
||
#pragma mark - Test video duration | ||
|
@@ -174,10 +211,12 @@ - (void)testPickingVideoWithDuration { | |
FlutterMethodCall *call = [FlutterMethodCall | ||
methodCallWithMethodName:@"pickVideo" | ||
arguments:@{@"source" : @(0), @"cameraDevice" : @(0), @"maxDuration" : @95}]; | ||
UIImagePickerController *controller = [[UIImagePickerController alloc] init]; | ||
[plugin setImagePickerControllerOverrides:@[ controller ]]; | ||
[plugin handleMethodCall:call | ||
result:^(id _Nullable r){ | ||
}]; | ||
XCTAssertEqual([plugin getImagePickerController].videoMaximumDuration, 95); | ||
XCTAssertEqual(controller.videoMaximumDuration, 95); | ||
} | ||
|
||
- (void)testViewController { | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.