Skip to content

Commit

Permalink
[file_selector] Remove OCMock from iOS implementation (flutter#6503)
Browse files Browse the repository at this point in the history
To aid in future conversion to Swift, remove the use of OCMock in favor of a protocol and an explicit stub.
  • Loading branch information
stuartmorgan authored and TecHaxter committed May 22, 2024
1 parent 71ab378 commit caee446
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 36 deletions.
3 changes: 2 additions & 1 deletion packages/file_selector/file_selector_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 0 additions & 2 deletions packages/file_selector/file_selector_ios/example/ios/Podfile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@
C71AE4B2281C6A090086307A /* Sources */,
C71AE4B3281C6A090086307A /* Frameworks */,
C71AE4B4281C6A090086307A /* Resources */,
5BE5886DAAA885227DE0796D /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
Expand All @@ -215,7 +214,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,19 @@
@import file_selector_ios.Test;
@import XCTest;

#import <OCMock/OCMock.h>
@interface TestPresenter : NSObject <FFSViewPresenter>
@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

Expand All @@ -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<NSString *> *paths, FlutterError *error){
}];

XCTAssertEqualObjects(picker.delegate, plugin);
OCMVerify(times(1), [mockPresentingVC presentViewController:picker
animated:[OCMArg any]
completion:[OCMArg any]]);
XCTAssertEqualObjects(presenter.presentedController, picker);
}

- (void)testReturnsPickedFiles {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,34 @@

#import <objc/runtime.h>

// TODO(stuartmorgan): When migrating to Swift, eliminate this in favor of
// adding FFSViewPresenter conformance to UIViewController.
@interface FFSPresentingViewController : NSObject <FFSViewPresenter>
- (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
Expand All @@ -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<FFSViewPresenter> 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."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 <NSObject>
/// 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 () <FFSFileSelectorApi, UIDocumentPickerDelegate>

/// Overrides the view controller used for presenting the document picker.
@property(nonatomic) UIViewController *_Nullable presentingViewControllerOverride;
@property(nonatomic) id<FFSViewPresenter> _Nullable viewPresenterOverride;

/// Overrides the UIDocumentPickerViewController used for file picking.
@property(nonatomic) UIDocumentPickerViewController *_Nullable documentPickerViewControllerOverride;
Expand Down
2 changes: 1 addition & 1 deletion packages/file_selector/file_selector_ios/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit caee446

Please sign in to comment.