From 1895baf6e1034e5bd6e66f5f018406f49501d611 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 11 Apr 2024 13:22:05 -0400 Subject: [PATCH 1/2] [file_selector] Remove OCMock from iOS implementation To aid in future conversion to Swift, remove the use of OCMock in favor of a protocol and an explicit stub. --- .../file_selector_ios/CHANGELOG.md | 3 +- .../file_selector_ios/example/ios/Podfile | 2 - .../ios/Runner.xcodeproj/project.pbxproj | 20 +--------- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- .../ios/RunnerTests/FileSelectorTests.m | 22 +++++++--- .../ios/Classes/FFSFileSelectorPlugin.m | 40 ++++++++++++++++--- .../ios/Classes/FFSFileSelectorPlugin_Test.h | 13 +++++- .../file_selector_ios/pubspec.yaml | 2 +- 8 files changed, 68 insertions(+), 36 deletions(-) diff --git a/packages/file_selector/file_selector_ios/CHANGELOG.md b/packages/file_selector/file_selector_ios/CHANGELOG.md index 0206ef358ac..50615cbce70 100644 --- a/packages/file_selector/file_selector_ios/CHANGELOG.md +++ b/packages/file_selector/file_selector_ios/CHANGELOG.md @@ -1,5 +1,6 @@ -## NEXT +## 0.5.1+9 +* Adjusts implementation for testabiity. * Updates minimum iOS version to 12.0 and minimum Flutter version to 3.16.6. ## 0.5.1+8 diff --git a/packages/file_selector/file_selector_ios/example/ios/Podfile b/packages/file_selector/file_selector_ios/example/ios/Podfile index b724e44451b..d97f17e223f 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Podfile +++ b/packages/file_selector/file_selector_ios/example/ios/Podfile @@ -34,8 +34,6 @@ target 'Runner' do flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) target 'RunnerTests' do inherit! :search_paths - # Pods for testing - pod 'OCMock', '~> 3.8.1' end end diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj index 966827bd239..f6d350beac6 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -197,7 +197,6 @@ C71AE4B2281C6A090086307A /* Sources */, C71AE4B3281C6A090086307A /* Frameworks */, C71AE4B4281C6A090086307A /* Resources */, - 5BE5886DAAA885227DE0796D /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -215,7 +214,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1510; ORGANIZATIONNAME = ""; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -285,23 +284,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; }; - 5BE5886DAAA885227DE0796D /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RunnerTests/Pods-RunnerTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-RunnerTests/Pods-RunnerTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-RunnerTests/Pods-RunnerTests-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; diff --git a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 0e96d52279e..828f48e73f8 100644 --- a/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/file_selector/file_selector_ios/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ +@interface TestPresenter : NSObject +@property(nonatomic) UIViewController *presentedController; +@end + +@implementation TestPresenter +- (void)presentViewController:(UIViewController *)viewControllerToPresent + animated:(BOOL)animated + completion:(void (^__nullable)(void))completion { + self.presentedController = viewControllerToPresent; +} +@end + +#pragma mark - @interface FileSelectorTests : XCTestCase @@ -19,18 +31,16 @@ - (void)testPickerPresents { UIDocumentPickerViewController *picker = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:@[] inMode:UIDocumentPickerModeImport]; - id mockPresentingVC = OCMClassMock([UIViewController class]); + TestPresenter *presenter = [[TestPresenter alloc] init]; plugin.documentPickerViewControllerOverride = picker; - plugin.presentingViewControllerOverride = mockPresentingVC; + plugin.viewPresenterOverride = presenter; [plugin openFileSelectorWithConfig:[FFSFileSelectorConfig makeWithUtis:@[] allowMultiSelection:NO] completion:^(NSArray *paths, FlutterError *error){ }]; XCTAssertEqualObjects(picker.delegate, plugin); - OCMVerify(times(1), [mockPresentingVC presentViewController:picker - animated:[OCMArg any] - completion:[OCMArg any]]); + XCTAssertEqual(presenter.presentedController, picker); } - (void)testReturnsPickedFiles { diff --git a/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin.m b/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin.m index ee9b840d5c4..e17469c636b 100644 --- a/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin.m +++ b/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin.m @@ -8,6 +8,34 @@ #import +// TODO(stuartmorgan): When migrating to Swift, eliminate this in favor of +// adding FFSViewPresenter conformance to UIViewController. +@interface FFSPresentingViewController : NSObject +- (instancetype)initWithViewController:(nullable UIViewController *)controller; +// The wrapped controller. +@property(nonatomic) UIViewController *controller; +@end + +@implementation FFSPresentingViewController +- (instancetype)initWithViewController:(nullable UIViewController *)controller { + self = [super init]; + if (self) { + _controller = controller; + } + return self; +} + +- (void)presentViewController:(UIViewController *)viewControllerToPresent + animated:(BOOL)animated + completion:(void (^__nullable)(void))completion { + [self.controller presentViewController:viewControllerToPresent + animated:animated + completion:completion]; +} +@end + +#pragma mark - + @implementation FFSFileSelectorPlugin #pragma mark - FFSFileSelectorApi @@ -23,13 +51,15 @@ - (void)openFileSelectorWithConfig:(FFSFileSelectorConfig *)config documentPicker.delegate = self; documentPicker.allowsMultipleSelection = config.allowMultiSelection; - UIViewController *presentingVC = - self.presentingViewControllerOverride - ?: UIApplication.sharedApplication.delegate.window.rootViewController; - if (presentingVC) { + id presenter = + self.viewPresenterOverride + ?: [[FFSPresentingViewController alloc] + initWithViewController:UIApplication.sharedApplication.delegate.window + .rootViewController]; + if (presenter) { objc_setAssociatedObject(documentPicker, @selector(openFileSelectorWithConfig:completion:), completion, OBJC_ASSOCIATION_COPY_NONATOMIC); - [presentingVC presentViewController:documentPicker animated:YES completion:nil]; + [presenter presentViewController:documentPicker animated:YES completion:nil]; } else { completion(nil, [FlutterError errorWithCode:@"error" message:@"Missing root view controller." diff --git a/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin_Test.h b/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin_Test.h index 5935f037f6c..a5e2040fc63 100644 --- a/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin_Test.h +++ b/packages/file_selector/file_selector_ios/ios/Classes/FFSFileSelectorPlugin_Test.h @@ -4,13 +4,24 @@ #import "FFSFileSelectorPlugin.h" +@import UIKit; + #import "messages.g.h" +/// Interface for presenting a view controller, to allow injecting an alternate +/// test implementation. +@protocol FFSViewPresenter +/// Wrapper for -[UIViewController presentViewController:animated:completion:]. +- (void)presentViewController:(UIViewController *_Nonnull)viewControllerToPresent + animated:(BOOL)animated + completion:(void (^__nullable)(void))completion; +@end + // This header is available in the Test module. Import via "@import file_selector_ios.Test;". @interface FFSFileSelectorPlugin () /// Overrides the view controller used for presenting the document picker. -@property(nonatomic) UIViewController *_Nullable presentingViewControllerOverride; +@property(nonatomic) id _Nullable viewPresenterOverride; /// Overrides the UIDocumentPickerViewController used for file picking. @property(nonatomic) UIDocumentPickerViewController *_Nullable documentPickerViewControllerOverride; diff --git a/packages/file_selector/file_selector_ios/pubspec.yaml b/packages/file_selector/file_selector_ios/pubspec.yaml index d8e3ec07b52..cae1f78b840 100644 --- a/packages/file_selector/file_selector_ios/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: file_selector_ios description: iOS implementation of the file_selector plugin. repository: https://github.com/flutter/packages/tree/main/packages/file_selector/file_selector_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+file_selector%22 -version: 0.5.1+8 +version: 0.5.1+9 environment: sdk: ^3.2.3 From cf10e07405651dcc3b242a3a1b9d57bbcb52b6c1 Mon Sep 17 00:00:00 2001 From: stuartmorgan Date: Thu, 11 Apr 2024 16:16:56 -0400 Subject: [PATCH 2/2] EqualObjects Co-authored-by: Jenn Magder --- .../example/ios/RunnerTests/FileSelectorTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/file_selector/file_selector_ios/example/ios/RunnerTests/FileSelectorTests.m b/packages/file_selector/file_selector_ios/example/ios/RunnerTests/FileSelectorTests.m index 0fd88e65133..f7f613b9cd5 100644 --- a/packages/file_selector/file_selector_ios/example/ios/RunnerTests/FileSelectorTests.m +++ b/packages/file_selector/file_selector_ios/example/ios/RunnerTests/FileSelectorTests.m @@ -40,7 +40,7 @@ - (void)testPickerPresents { }]; XCTAssertEqualObjects(picker.delegate, plugin); - XCTAssertEqual(presenter.presentedController, picker); + XCTAssertEqualObjects(presenter.presentedController, picker); } - (void)testReturnsPickedFiles {