From 39ce72f054a1f753d4cd9754690f6c2a1cf20533 Mon Sep 17 00:00:00 2001 From: Victor Gomez Date: Thu, 20 Aug 2026 10:56:49 -0600 Subject: [PATCH 1/2] [image_picker_ios] Add native tests for pick results, camera access, and presentation. --- .../ios/RunnerTests/ImagePickerPluginTests.m | 416 ++++++++++++++++++ 1 file changed, 416 insertions(+) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index 89366a0a15af..a1e584f8ddad 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -17,6 +17,9 @@ @interface FLTImagePickerPlugin (Testing) @property(nonatomic, strong) UIWindow *interactionBlockerWindow; @property(nonatomic, weak) UIWindow *previousKeyWindow; - (void)removeInteractionBlocker; +- (void)showCamera:(UIImagePickerControllerCameraDevice)device + withImagePicker:(UIImagePickerController *)imagePickerController; +- (UIViewController *)presentingViewControllerForImagePickerInNewWindow; @end @interface MockViewController : UIViewController @@ -815,4 +818,417 @@ - (void)testPickVideoSetsCurrentRepresentationMode API_AVAILABLE(ios(14)) { OCMVerifyAll(mockPickerViewController); } +- (void)testPickImageInvalidResultWhenMultiplePathsReturned { + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"invalid_result"]; + __block NSInteger completionCount = 0; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeGallery + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:NO + completion:^(NSString *result, FlutterError *error) { + completionCount += 1; + if (completionCount == 1) { + // Current behavior: the invalid_result error is sent, then the adapter + // also forwards paths.firstObject. + XCTAssertNil(result); + XCTAssertEqualObjects(error.code, @"invalid_result"); + } else { + XCTAssertEqualObjects(result, @"a"); + [resultExpectation fulfill]; + } + }]; + [plugin sendCallResultWithSavedPathList:@[ @"a", @"b" ]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; + XCTAssertEqual(completionCount, 2); +} + +- (void)testPickVideoInvalidResultWhenMultiplePathsReturned { + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"invalid_result"]; + __block NSInteger completionCount = 0; + [plugin pickVideoWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeGallery + camera:FLTSourceCameraRear] + maxDuration:nil + completion:^(NSString *result, FlutterError *error) { + completionCount += 1; + if (completionCount == 1) { + XCTAssertNil(result); + XCTAssertEqualObjects(error.code, @"invalid_result"); + } else { + XCTAssertEqualObjects(result, @"a"); + [resultExpectation fulfill]; + } + }]; + [plugin sendCallResultWithSavedPathList:@[ @"a", @"b" ]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; + XCTAssertEqual(completionCount, 2); +} + +- (void)testPHPickerCancelSendsEmptyPathList API_AVAILABLE(ios(14)) { + id mockPickerViewController = OCMClassMock([PHPickerViewController class]); + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"cancelled"]; + plugin.callContext = [[FLTImagePickerMethodCallContext alloc] + initWithResult:^(NSArray *result, FlutterError *error) { + XCTAssertEqualObjects(result, @[]); + XCTAssertNil(error); + [resultExpectation fulfill]; + }]; + [plugin picker:mockPickerViewController didFinishPicking:@[]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testPresentationControllerDidDismissSendsEmptyPathList { + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"dismissed"]; + plugin.callContext = [[FLTImagePickerMethodCallContext alloc] + initWithResult:^(NSArray *result, FlutterError *error) { + XCTAssertEqualObjects(result, @[]); + XCTAssertNil(error); + [resultExpectation fulfill]; + }]; + id mockPresentationController = OCMClassMock([UIPresentationController class]); + [plugin presentationControllerDidDismiss:mockPresentationController]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testDesiredImageQualityClampsOutOfRangeValues API_AVAILABLE(ios(14)) { + id mockPickerViewController = OCMClassMock([PHPickerViewController class]); + NSURL *pngURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage" + withExtension:@"png"]; + NSItemProvider *pngItemProvider = [[NSItemProvider alloc] initWithContentsOfURL:pngURL]; + PHPickerResult *pngResult = OCMClassMock([PHPickerResult class]); + OCMStub([pngResult itemProvider]).andReturn(pngItemProvider); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"saved"]; + plugin.callContext = [[FLTImagePickerMethodCallContext alloc] + initWithResult:^(NSArray *result, FlutterError *error) { + XCTAssertEqual(result.count, 1); + XCTAssertNil(error); + [resultExpectation fulfill]; + }]; + plugin.callContext.imageQuality = @(-1); + [plugin picker:mockPickerViewController didFinishPicking:@[ pngResult ]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testDesiredImageQualityScalesValidPercent API_AVAILABLE(ios(14)) { + id mockPickerViewController = OCMClassMock([PHPickerViewController class]); + NSURL *pngURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage" + withExtension:@"png"]; + NSItemProvider *pngItemProvider = [[NSItemProvider alloc] initWithContentsOfURL:pngURL]; + PHPickerResult *pngResult = OCMClassMock([PHPickerResult class]); + OCMStub([pngResult itemProvider]).andReturn(pngItemProvider); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"saved"]; + plugin.callContext = [[FLTImagePickerMethodCallContext alloc] + initWithResult:^(NSArray *result, FlutterError *error) { + XCTAssertEqual(result.count, 1); + XCTAssertNil(error); + [resultExpectation fulfill]; + }]; + plugin.callContext.imageQuality = @50; + plugin.callContext.maxSize = [FLTMaxSize makeWithWidth:@3 height:@2]; + [plugin picker:mockPickerViewController didFinishPicking:@[ pngResult ]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testDesiredImageQualityOver100IsClamped API_AVAILABLE(ios(14)) { + id mockPickerViewController = OCMClassMock([PHPickerViewController class]); + NSURL *pngURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage" + withExtension:@"png"]; + NSItemProvider *pngItemProvider = [[NSItemProvider alloc] initWithContentsOfURL:pngURL]; + PHPickerResult *pngResult = OCMClassMock([PHPickerResult class]); + OCMStub([pngResult itemProvider]).andReturn(pngItemProvider); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"saved"]; + plugin.callContext = [[FLTImagePickerMethodCallContext alloc] + initWithResult:^(NSArray *result, FlutterError *error) { + XCTAssertEqual(result.count, 1); + [resultExpectation fulfill]; + }]; + plugin.callContext.imageQuality = @150; + [plugin picker:mockPickerViewController didFinishPicking:@[ pngResult ]]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testCameraAccessDeniedReturnsError { + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusDenied); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"denied"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertEqualObjects(error.code, @"camera_access_denied"); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testCameraAccessRestrictedReturnsError { + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusRestricted); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"restricted"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertEqualObjects(error.code, @"camera_access_restricted"); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testCameraAccessNotDeterminedDenied { + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusNotDetermined); + OCMStub([mockAVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo + completionHandler:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + void (^handler)(BOOL granted); + [invocation getArgument:&handler atIndex:3]; + handler(NO); + }); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"request denied"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertEqualObjects(error.code, @"camera_access_denied"); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testCameraAccessNotDeterminedGrantedPresentsCamera { + id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub(ClassMethod( + [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) + .andReturn(YES); + OCMStub(ClassMethod( + [mockUIImagePicker isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear])) + .andReturn(YES); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusNotDetermined); + OCMStub([mockAVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo + completionHandler:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + void (^handler)(BOOL granted); + [invocation getArgument:&handler atIndex:3]; + handler(YES); + }); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + UIImagePickerController *controller = [[UIImagePickerController alloc] init]; + [plugin setImagePickerControllerOverrides:@[ controller ]]; + + XCTestExpectation *presented = [self expectationWithDescription:@"camera presented"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error){ + }]; + dispatch_async(dispatch_get_main_queue(), ^{ + XCTAssertEqual(controller.sourceType, UIImagePickerControllerSourceTypeCamera); + [presented fulfill]; + }); + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testShowCameraWhenUnavailableSendsNilPathList { + id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub(ClassMethod( + [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) + .andReturn(NO); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusAuthorized); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"unavailable"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertNil(result); + XCTAssertNil(error); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testShowCameraReturnsEarlyWhenAlreadyBeingPresented { + id mockPicker = OCMClassMock([UIImagePickerController class]); + OCMStub([mockPicker isBeingPresented]).andReturn(YES); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin showCamera:UIImagePickerControllerCameraDeviceRear withImagePicker:mockPicker]; + OCMVerify(times(0), [mockPicker setSourceType:UIImagePickerControllerSourceTypeCamera]); +} + +- (void)testCameraAccessUnknownStatusTreatedAsDenied { + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn((AVAuthorizationStatus)999); + + FLTImagePickerPlugin *plugin = + [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] init]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"unknown denied"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertEqualObjects(error.code, @"camera_access_denied"); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; +} + +- (void)testShowCameraUnavailableAlertOKHandler { + id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); + id mockAVCaptureDevice = OCMClassMock([AVCaptureDevice class]); + OCMStub(ClassMethod( + [mockUIImagePicker isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera])) + .andReturn(NO); + OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) + .andReturn(AVAuthorizationStatusAuthorized); + + UIWindowScene *scene = + (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; + UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; + window.frame = scene.coordinateSpace.bounds; + UIViewController *rootViewController = [[UIViewController alloc] init]; + window.rootViewController = rootViewController; + [rootViewController loadViewIfNeeded]; + [window makeKeyAndVisible]; + + FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] + initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; + [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; + + XCTestExpectation *resultExpectation = [self expectationWithDescription:@"unavailable"]; + [plugin pickImageWithSource:[FLTSourceSpecification makeWithType:FLTSourceTypeCamera + camera:FLTSourceCameraRear] + maxSize:[[FLTMaxSize alloc] init] + quality:nil + fullMetadata:YES + completion:^(NSString *result, FlutterError *error) { + XCTAssertNil(result); + [resultExpectation fulfill]; + }]; + [self waitForExpectationsWithTimeout:30 handler:nil]; + + UIAlertController *alert = (UIAlertController *)rootViewController.presentedViewController; + XCTAssertTrue([alert isKindOfClass:[UIAlertController class]]); + void (^handler)(UIAlertAction *) = [alert.actions.firstObject valueForKey:@"handler"]; + if (handler) { + handler(alert.actions.firstObject); + } +} + +- (void)testPresentingViewControllerWithoutWindowReturnsHostController { + UIViewController *host = [[UIViewController alloc] init]; + FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] + initWithViewProvider:[[StubViewProvider alloc] initWithViewController:host]]; + UIViewController *presented = [plugin presentingViewControllerForImagePickerInNewWindow]; + XCTAssertEqual(presented, host); +} + +- (void)testPresentingViewControllerReusesExistingBlockerWindow { + UIWindowScene *scene = + (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; + UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; + window.frame = scene.coordinateSpace.bounds; + UIViewController *rootViewController = [[UIViewController alloc] init]; + window.rootViewController = rootViewController; + [rootViewController loadViewIfNeeded]; + [window makeKeyAndVisible]; + + FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] + initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; + UIViewController *first = [plugin presentingViewControllerForImagePickerInNewWindow]; + UIViewController *second = [plugin presentingViewControllerForImagePickerInNewWindow]; + XCTAssertEqual(first, second); + [plugin removeInteractionBlocker]; +} + +- (void)testPresentingViewControllerWithoutWindowSceneUsesFrame { + UIWindowScene *scene = + (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; + UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; + window.frame = scene.coordinateSpace.bounds; + UIViewController *rootViewController = [[UIViewController alloc] init]; + window.rootViewController = rootViewController; + [rootViewController loadViewIfNeeded]; + [window makeKeyAndVisible]; + + id mockWindow = OCMPartialMock(window); + OCMStub([mockWindow windowScene]).andReturn(nil); + + FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] + initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; + XCTAssertNotNil([plugin presentingViewControllerForImagePickerInNewWindow]); + [plugin removeInteractionBlocker]; + [mockWindow stopMocking]; +} + +- (void)testDefaultViewProviderReturnsRegistrarViewController { + UIViewController *host = [[UIViewController alloc] init]; + id registrar = OCMProtocolMock(@protocol(FlutterPluginRegistrar)); + OCMStub([registrar viewController]).andReturn(host); + FIPDefaultViewProvider *provider = [[FIPDefaultViewProvider alloc] initWithRegistrar:registrar]; + XCTAssertEqual(provider.viewController, host); +} + @end From c8a1451befafc4fbf87407d51cb5c2afda7d53c6 Mon Sep 17 00:00:00 2001 From: Victor Gomez Date: Fri, 21 Aug 2026 13:03:12 -0600 Subject: [PATCH 2/2] [image_picker_ios] Refactor ImagePickerPluginTests to use mock view controller for alert presentation --- .../ios/RunnerTests/ImagePickerPluginTests.m | 35 ++++++------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index a1e584f8ddad..93df6016c24e 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -1144,17 +1144,17 @@ - (void)testShowCameraUnavailableAlertOKHandler { OCMStub([mockAVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) .andReturn(AVAuthorizationStatusAuthorized); - UIWindowScene *scene = - (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; - UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; - window.frame = scene.coordinateSpace.bounds; - UIViewController *rootViewController = [[UIViewController alloc] init]; - window.rootViewController = rootViewController; - [rootViewController loadViewIfNeeded]; - [window makeKeyAndVisible]; + id mockViewController = OCMClassMock([UIViewController class]); + __block UIAlertController *alert = nil; + OCMStub([mockViewController presentViewController:[OCMArg any] animated:YES completion:nil]) + .andDo(^(NSInvocation *invocation) { + __unsafe_unretained UIAlertController *presented = nil; + [invocation getArgument:&presented atIndex:2]; + alert = presented; + }); FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] - initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; + initWithViewProvider:[[StubViewProvider alloc] initWithViewController:mockViewController]]; [plugin setImagePickerControllerOverrides:@[ [[UIImagePickerController alloc] init] ]]; XCTestExpectation *resultExpectation = [self expectationWithDescription:@"unavailable"]; @@ -1169,7 +1169,6 @@ - (void)testShowCameraUnavailableAlertOKHandler { }]; [self waitForExpectationsWithTimeout:30 handler:nil]; - UIAlertController *alert = (UIAlertController *)rootViewController.presentedViewController; XCTAssertTrue([alert isKindOfClass:[UIAlertController class]]); void (^handler)(UIAlertAction *) = [alert.actions.firstObject valueForKey:@"handler"]; if (handler) { @@ -1186,14 +1185,10 @@ - (void)testPresentingViewControllerWithoutWindowReturnsHostController { } - (void)testPresentingViewControllerReusesExistingBlockerWindow { - UIWindowScene *scene = - (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; - UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; - window.frame = scene.coordinateSpace.bounds; + UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; UIViewController *rootViewController = [[UIViewController alloc] init]; window.rootViewController = rootViewController; [rootViewController loadViewIfNeeded]; - [window makeKeyAndVisible]; FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; @@ -1204,23 +1199,15 @@ - (void)testPresentingViewControllerReusesExistingBlockerWindow { } - (void)testPresentingViewControllerWithoutWindowSceneUsesFrame { - UIWindowScene *scene = - (UIWindowScene *)UIApplication.sharedApplication.connectedScenes.allObjects.firstObject; - UIWindow *window = [[UIWindow alloc] initWithWindowScene:scene]; - window.frame = scene.coordinateSpace.bounds; + UIWindow *window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; UIViewController *rootViewController = [[UIViewController alloc] init]; window.rootViewController = rootViewController; [rootViewController loadViewIfNeeded]; - [window makeKeyAndVisible]; - - id mockWindow = OCMPartialMock(window); - OCMStub([mockWindow windowScene]).andReturn(nil); FLTImagePickerPlugin *plugin = [[FLTImagePickerPlugin alloc] initWithViewProvider:[[StubViewProvider alloc] initWithViewController:rootViewController]]; XCTAssertNotNil([plugin presentingViewControllerForImagePickerInNewWindow]); [plugin removeInteractionBlocker]; - [mockWindow stopMocking]; } - (void)testDefaultViewProviderReturnsRegistrarViewController {