From 39815959ade8f9115f6a6a9347d31c596253f0f5 Mon Sep 17 00:00:00 2001 From: chrisdlangham Date: Mon, 11 Sep 2023 08:29:19 -0500 Subject: [PATCH] [url_launcher] migrating iOS tests from objc to swift (#4758) This PR converts the iOS test of the url_launcher plugin from objc to swift. *List which issues are fixed by this PR. You must list at least one issue.* https://github.com/flutter/flutter/issues/119102 --- .../ios/Runner.xcodeproj/project.pbxproj | 58 +++++-- .../ios/RunnerTests/URLLauncherTests.m | 157 ------------------ .../ios/RunnerTests/URLLauncherTests.swift | 137 +++++++++++++++ .../ios/RunnerUITests/URLLauncherUITests.m | 42 ----- .../RunnerUITests/URLLauncherUITests.swift | 37 +++++ .../ios/url_launcher_ios.podspec | 6 +- 6 files changed, 221 insertions(+), 216 deletions(-) delete mode 100644 packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.m create mode 100644 packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.swift delete mode 100644 packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.m create mode 100644 packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.swift diff --git a/packages/url_launcher/url_launcher_ios/example/ios/Runner.xcodeproj/project.pbxproj b/packages/url_launcher/url_launcher_ios/example/ios/Runner.xcodeproj/project.pbxproj index d61abc724469..e40cd34be9d7 100644 --- a/packages/url_launcher/url_launcher_ios/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/url_launcher/url_launcher_ios/example/ios/Runner.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 1D9FF3342A90170000F89C85 /* URLLauncherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1D9FF3332A90170000F89C85 /* URLLauncherTests.swift */; }; + 1DBE6EDE2A92479000B6525C /* URLLauncherUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1DBE6EDD2A92479000B6525C /* URLLauncherUITests.swift */; }; 2D92223F1EC1DA93007564B0 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D92223E1EC1DA93007564B0 /* GeneratedPluginRegistrant.m */; }; 2E37D9A274B2EACB147AC51B /* libPods-Runner.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 856D0913184F79C678A42603 /* libPods-Runner.a */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; @@ -16,8 +18,6 @@ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; B8140773523F70A044426500 /* libPods-RunnerTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 487A1B5A2ECB3E406FD62FE3 /* libPods-RunnerTests.a */; }; - F7151F4B26604CFB0028CB91 /* URLLauncherTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F4A26604CFB0028CB91 /* URLLauncherTests.m */; }; - F7151F5926604D060028CB91 /* URLLauncherUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = F7151F5826604D060028CB91 /* URLLauncherUITests.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -51,6 +51,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1D9FF3332A90170000F89C85 /* URLLauncherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLLauncherTests.swift; sourceTree = ""; }; + 1DBE6EDD2A92479000B6525C /* URLLauncherUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLLauncherUITests.swift; sourceTree = ""; }; 2D92223D1EC1DA93007564B0 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = GeneratedPluginRegistrant.h; path = Runner/GeneratedPluginRegistrant.h; sourceTree = ""; }; 2D92223E1EC1DA93007564B0 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GeneratedPluginRegistrant.m; path = Runner/GeneratedPluginRegistrant.m; sourceTree = ""; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; @@ -72,10 +74,8 @@ A84BFEE343F54B983D1B67EB /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; D25C434271ACF6555E002440 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; F7151F4826604CFB0028CB91 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - F7151F4A26604CFB0028CB91 /* URLLauncherTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = URLLauncherTests.m; sourceTree = ""; }; F7151F4C26604CFB0028CB91 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; F7151F5626604D060028CB91 /* RunnerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - F7151F5826604D060028CB91 /* URLLauncherUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = URLLauncherUITests.m; sourceTree = ""; }; F7151F5A26604D060028CB91 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ @@ -187,8 +187,8 @@ F7151F4926604CFB0028CB91 /* RunnerTests */ = { isa = PBXGroup; children = ( - F7151F4A26604CFB0028CB91 /* URLLauncherTests.m */, F7151F4C26604CFB0028CB91 /* Info.plist */, + 1D9FF3332A90170000F89C85 /* URLLauncherTests.swift */, ); path = RunnerTests; sourceTree = ""; @@ -196,8 +196,8 @@ F7151F5726604D060028CB91 /* RunnerUITests */ = { isa = PBXGroup; children = ( - F7151F5826604D060028CB91 /* URLLauncherUITests.m */, F7151F5A26604D060028CB91 /* Info.plist */, + 1DBE6EDD2A92479000B6525C /* URLLauncherUITests.swift */, ); path = RunnerUITests; sourceTree = ""; @@ -351,7 +351,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; @@ -366,7 +366,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; AB1344B0443C71CD721E1BB7 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -425,7 +425,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - F7151F4B26604CFB0028CB91 /* URLLauncherTests.m in Sources */, + 1D9FF3342A90170000F89C85 /* URLLauncherTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -433,7 +433,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - F7151F5926604D060028CB91 /* URLLauncherUITests.m in Sources */, + 1DBE6EDE2A92479000B6525C /* URLLauncherUITests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -589,7 +589,10 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -610,7 +613,10 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -627,10 +633,15 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = RunnerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; name = Debug; @@ -642,10 +653,15 @@ BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = RunnerTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/Runner"; }; name = Release; @@ -655,10 +671,15 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = RunnerUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; TEST_TARGET_NAME = Runner; }; name = Debug; @@ -668,10 +689,15 @@ buildSettings = { CODE_SIGN_STYLE = Automatic; INFOPLIST_FILE = RunnerUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = dev.flutter.plugins.RunnerUITests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; TEST_TARGET_NAME = Runner; }; name = Release; diff --git a/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.m b/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.m deleted file mode 100644 index 64a17994b6fa..000000000000 --- a/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.m +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import Flutter; -@import url_launcher_ios; -@import XCTest; - -@interface FULFakeLauncher : NSObject -@property(copy, nonatomic) NSDictionary *passedOptions; -@end - -@implementation FULFakeLauncher -- (BOOL)canOpenURL:(NSURL *)url { - return [url.scheme isEqualToString:@"good"]; -} - -- (void)openURL:(NSURL *)url - options:(NSDictionary *)options - completionHandler:(void (^__nullable)(BOOL success))completion { - self.passedOptions = options; - completion([url.scheme isEqualToString:@"good"]); -} -@end - -#pragma mark - - -@interface URLLauncherTests : XCTestCase -@end - -@implementation URLLauncherTests - -- (void)testCanLaunchSuccess { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - - FlutterError *error; - NSNumber *result = [plugin canLaunchURL:@"good://url" error:&error]; - - XCTAssertTrue(result.boolValue); - XCTAssertNil(error); -} - -- (void)testCanLaunchFailure { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - - FlutterError *error; - NSNumber *result = [plugin canLaunchURL:@"bad://url" error:&error]; - - XCTAssertNotNil(result); - XCTAssertFalse(result.boolValue); - XCTAssertNil(error); -} - -- (void)testCanLaunchInvalidURL { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - - FlutterError *error; - NSNumber *result = [plugin canLaunchURL:@"urls can't have spaces" error:&error]; - - XCTAssertNil(result); - XCTAssertEqualObjects(error.code, @"argument_error"); - XCTAssertEqualObjects(error.message, @"Unable to parse URL"); - XCTAssertEqualObjects(error.details, @"Provided URL: urls can't have spaces"); -} - -- (void)testLaunchSuccess { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - XCTestExpectation *resultExpectation = [self expectationWithDescription:@"result"]; - - [plugin launchURL:@"good://url" - universalLinksOnly:@NO - completion:^(NSNumber *_Nullable result, FlutterError *_Nullable error) { - XCTAssertTrue(result.boolValue); - XCTAssertNil(error); - [resultExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5 handler:nil]; -} - -- (void)testLaunchFailure { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - XCTestExpectation *resultExpectation = [self expectationWithDescription:@"result"]; - - [plugin launchURL:@"bad://url" - universalLinksOnly:@NO - completion:^(NSNumber *_Nullable result, FlutterError *_Nullable error) { - XCTAssertNotNil(result); - XCTAssertFalse(result.boolValue); - XCTAssertNil(error); - [resultExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5 handler:nil]; -} - -- (void)testLaunchInvalidURL { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - XCTestExpectation *resultExpectation = [self expectationWithDescription:@"result"]; - - [plugin launchURL:@"urls can't have spaces" - universalLinksOnly:@NO - completion:^(NSNumber *_Nullable result, FlutterError *_Nullable error) { - XCTAssertNil(result); - XCTAssertNotNil(error); - XCTAssertEqualObjects(error.code, @"argument_error"); - XCTAssertEqualObjects(error.message, @"Unable to parse URL"); - XCTAssertEqualObjects(error.details, @"Provided URL: urls can't have spaces"); - [resultExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5 handler:nil]; -} - -- (void)testLaunchWithoutUniversalLinks { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - XCTestExpectation *resultExpectation = [self expectationWithDescription:@"result"]; - - FlutterError *error; - [plugin launchURL:@"good://url" - universalLinksOnly:@NO - completion:^(NSNumber *_Nullable result, FlutterError *_Nullable error) { - [resultExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5 handler:nil]; - XCTAssertNil(error); - XCTAssertFalse( - ((NSNumber *)launcher.passedOptions[UIApplicationOpenURLOptionUniversalLinksOnly]).boolValue); -} - -- (void)testLaunchWithUniversalLinks { - FULFakeLauncher *launcher = [[FULFakeLauncher alloc] init]; - FLTURLLauncherPlugin *plugin = [[FLTURLLauncherPlugin alloc] initWithLauncher:launcher]; - XCTestExpectation *resultExpectation = [self expectationWithDescription:@"result"]; - - FlutterError *error; - [plugin launchURL:@"good://url" - universalLinksOnly:@YES - completion:^(NSNumber *_Nullable result, FlutterError *_Nullable error) { - [resultExpectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5 handler:nil]; - XCTAssertNil(error); - XCTAssertTrue( - ((NSNumber *)launcher.passedOptions[UIApplicationOpenURLOptionUniversalLinksOnly]).boolValue); -} - -@end diff --git a/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.swift b/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.swift new file mode 100644 index 000000000000..a0f8f6fb74cf --- /dev/null +++ b/packages/url_launcher/url_launcher_ios/example/ios/RunnerTests/URLLauncherTests.swift @@ -0,0 +1,137 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import Flutter +import XCTest + +@testable import url_launcher_ios + +final class URLLauncherTests: XCTestCase { + + private func createPlugin() -> FLTURLLauncherPlugin { + let launcher = FakeLauncher() + return FLTURLLauncherPlugin(launcher: launcher) + } + + private func createPlugin(launcher: FakeLauncher) -> FLTURLLauncherPlugin { + FLTURLLauncherPlugin(launcher: launcher) + } + + func testCanLaunchSuccess() { + var error: FlutterError? + let result = createPlugin().canLaunchURL("good://url", error: &error) + + XCTAssertNotNil(result) + XCTAssertTrue(result?.boolValue ?? false) + XCTAssertNil(error) + } + + func testCanLaunchFailure() { + var error: FlutterError? + let result = createPlugin().canLaunchURL("bad://url", error: &error) + + XCTAssertNotNil(result) + XCTAssertFalse(result?.boolValue ?? true) + } + + func testCanLaunchFailureWithInvalidURL() { + var error: FlutterError? + let result = createPlugin().canLaunchURL("urls can't have spaces", error: &error) + + XCTAssertNil(result) + XCTAssertNotNil(error) + XCTAssertEqual(error?.code, "argument_error") + XCTAssertEqual(error?.message, "Unable to parse URL") + XCTAssertEqual(error?.details as? String, "Provided URL: urls can't have spaces") + } + + func testLaunchSuccess() { + let expectation = XCTestExpectation(description: "completion called") + createPlugin().launchURL("good://url", universalLinksOnly: false) { result, error in + XCTAssertNotNil(result) + XCTAssertTrue(result?.boolValue ?? false) + XCTAssertNil(error) + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + } + + func testLaunchFailure() { + let expectation = XCTestExpectation(description: "completion called") + + createPlugin().launchURL("bad://url", universalLinksOnly: false) { result, error in + XCTAssertNotNil(result) + XCTAssertFalse(result?.boolValue ?? true) + XCTAssertNil(error) + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + } + + func testLaunchFailureWithInvalidURL() { + let expectation = XCTestExpectation(description: "completion called") + + createPlugin().launchURL("urls can't have spaces", universalLinksOnly: false) { result, error in + XCTAssertNil(result) + XCTAssertNotNil(error) + XCTAssertEqual(error?.code, "argument_error") + XCTAssertEqual(error?.message, "Unable to parse URL") + XCTAssertEqual(error?.details as? String, "Provided URL: urls can't have spaces") + + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + } + + func testLaunchWithoutUniversalLinks() { + let launcher = FakeLauncher() + let plugin = createPlugin(launcher: launcher) + + let expectation = XCTestExpectation(description: "completion called") + plugin.launchURL("good://url", universalLinksOnly: false) { result, error in + XCTAssertNil(error) + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + + XCTAssertEqual(launcher.passedOptions?[.universalLinksOnly] as? Bool, false) + } + + func testLaunchWithUniversalLinks() { + let launcher = FakeLauncher() + let plugin = createPlugin(launcher: launcher) + + let expectation = XCTestExpectation(description: "completion called") + + plugin.launchURL("good://url", universalLinksOnly: true) { result, error in + XCTAssertNil(error) + expectation.fulfill() + } + + wait(for: [expectation], timeout: 1) + + XCTAssertEqual(launcher.passedOptions?[.universalLinksOnly] as? Bool, true) + } + +} + +final private class FakeLauncher: NSObject, FULLauncher { + var passedOptions: [UIApplication.OpenExternalURLOptionsKey: Any]? + + func canOpen(_ url: URL) -> Bool { + return url.scheme == "good" + } + + func open( + _ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any] = [:], + completionHandler: ((Bool) -> Void)? = nil + ) { + self.passedOptions = options + completionHandler?(url.scheme == "good") + } +} diff --git a/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.m b/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.m deleted file mode 100644 index b6d3bceff039..000000000000 --- a/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.m +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -@import XCTest; -@import os.log; - -@interface URLLauncherUITests : XCTestCase -@property(nonatomic, strong) XCUIApplication *app; -@end - -@implementation URLLauncherUITests - -- (void)setUp { - self.continueAfterFailure = NO; - - self.app = [[XCUIApplication alloc] init]; - [self.app launch]; -} - -- (void)testLaunch { - XCUIApplication *app = self.app; - - NSArray *buttonNames = @[ - @"Launch in app", @"Launch in app(JavaScript ON)", @"Launch in app(DOM storage ON)", - @"Launch a universal link in a native app, fallback to Safari.(Youtube)" - ]; - for (NSString *buttonName in buttonNames) { - XCUIElement *button = app.buttons[buttonName]; - XCTAssertTrue([button waitForExistenceWithTimeout:30.0]); - XCTAssertEqual(app.webViews.count, 0); - [button tap]; - XCUIElement *webView = app.webViews.firstMatch; - XCTAssertTrue([webView waitForExistenceWithTimeout:30.0]); - XCTAssertTrue([app.buttons[@"ForwardButton"] waitForExistenceWithTimeout:30.0]); - XCTAssertTrue(app.buttons[@"Share"].exists); - XCTAssertTrue(app.buttons[@"OpenInSafariButton"].exists); - [app.buttons[@"Done"] tap]; - } -} - -@end diff --git a/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.swift b/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.swift new file mode 100644 index 000000000000..39ec39e30c47 --- /dev/null +++ b/packages/url_launcher/url_launcher_ios/example/ios/RunnerUITests/URLLauncherUITests.swift @@ -0,0 +1,37 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import XCTest + +class URLLauncherUITests: XCTestCase { + var app: XCUIApplication! + + override func setUp() { + continueAfterFailure = false + + app = XCUIApplication() + app.launch() + } + + func testLaunch() { + let app = self.app! + + let buttonNames: [String] = [ + "Launch in app", "Launch in app(JavaScript ON)", "Launch in app(DOM storage ON)", + "Launch a universal link in a native app, fallback to Safari.(Youtube)", + ] + for buttonName in buttonNames { + let button = app.buttons[buttonName] + XCTAssertTrue(button.waitForExistence(timeout: 30.0)) + XCTAssertEqual(app.webViews.count, 0) + button.tap() + let webView = app.webViews.firstMatch + XCTAssertTrue(webView.waitForExistence(timeout: 30.0)) + XCTAssertTrue(app.buttons["ForwardButton"].waitForExistence(timeout: 30.0)) + XCTAssertTrue(app.buttons["Share"].exists) + XCTAssertTrue(app.buttons["OpenInSafariButton"].exists) + app.buttons["Done"].tap() + } + } +} diff --git a/packages/url_launcher/url_launcher_ios/ios/url_launcher_ios.podspec b/packages/url_launcher/url_launcher_ios/ios/url_launcher_ios.podspec index 50c4ffad474b..3dd3eb97c95b 100644 --- a/packages/url_launcher/url_launcher_ios/ios/url_launcher_ios.podspec +++ b/packages/url_launcher/url_launcher_ios/ios/url_launcher_ios.podspec @@ -13,8 +13,12 @@ A Flutter plugin for making the underlying platform (Android or iOS) launch a UR s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' } s.source = { :http => 'https://github.com/flutter/packages/tree/main/packages/url_launcher/url_launcher_ios' } s.documentation_url = 'https://pub.dev/packages/url_launcher' + s.swift_version = '5.0' s.source_files = 'Classes/**/*' - s.public_header_files = 'Classes/**/*.h' + s.xcconfig = { + 'LIBRARY_SEARCH_PATHS' => '$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)/ $(SDKROOT)/usr/lib/swift', + 'LD_RUNPATH_SEARCH_PATHS' => '/usr/lib/swift', + } s.dependency 'Flutter' s.platform = :ios, '11.0' s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }