Skip to content

Commit

Permalink
[url_launcher] migrating objc plugin to swift (#4753)
Browse files Browse the repository at this point in the history
This PR converts the iOS portion of the url_launcher plugin from objc to swift. 

*List which issues are fixed by this PR. You must list at least one issue.*
flutter/flutter#119102
  • Loading branch information
chrisdlangham authored Oct 26, 2023
1 parent 45ed8c9 commit 3aff029
Show file tree
Hide file tree
Showing 21 changed files with 751 additions and 608 deletions.
4 changes: 4 additions & 0 deletions packages/url_launcher/url_launcher_ios/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 6.2.1

* Migrates plugin from Objective-C to Swift.

## 6.2.0

* Implements `supportsMode` and `supportsCloseForMode`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1300;
LastUpgradeCheck = 1430;
ORGANIZATIONNAME = "The Flutter Authors";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -631,6 +631,7 @@
baseConfigurationReference = 666BCD7C181C34F8BE58929B /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = RunnerTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
Expand All @@ -651,6 +652,7 @@
baseConfigurationReference = D25C434271ACF6555E002440 /* Pods-RunnerTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
INFOPLIST_FILE = RunnerTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
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 = "1300"
LastUpgradeVersion = "1430"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,52 @@ import XCTest

@testable import url_launcher_ios

// Tests whether NSURL parsing is strict. When linking against the iOS 17 SDK or later,
// NSURL uses a more lenient parser which will not return nil.
private func urlParsingIsStrict() -> Bool {
return URL(string: "b a d U R L") == nil
}

final class URLLauncherTests: XCTestCase {

private func createPlugin() -> FLTURLLauncherPlugin {
private func createPlugin() -> URLLauncherPlugin {
let launcher = FakeLauncher()
return FLTURLLauncherPlugin(launcher: launcher)
return URLLauncherPlugin(launcher: launcher)
}

private func createPlugin(launcher: FakeLauncher) -> FLTURLLauncherPlugin {
FLTURLLauncherPlugin(launcher: launcher)
private func createPlugin(launcher: FakeLauncher) -> URLLauncherPlugin {
return URLLauncherPlugin(launcher: launcher)
}

func testCanLaunchSuccess() {
var error: FlutterError?
let result = createPlugin().canLaunchURL("good://url", error: &error)

XCTAssertNotNil(result)
XCTAssertTrue(result?.boolValue ?? false)
XCTAssertNil(error)
let result = createPlugin().canLaunchUrl(url: "good://url")
XCTAssertEqual(result, .success)
}

func testCanLaunchFailure() {
var error: FlutterError?
let result = createPlugin().canLaunchURL("bad://url", error: &error)

XCTAssertNotNil(result)
XCTAssertFalse(result?.boolValue ?? true)
let result = createPlugin().canLaunchUrl(url: "bad://url")
XCTAssertEqual(result, .failure)
}

func testCanLaunchFailureWithInvalidURL() {
var error: FlutterError?
let result = createPlugin().canLaunchURL("urls can't have spaces", error: &error)

if (error == nil) {
// When linking against the iOS 17 SDK or later, NSURL uses a lenient parser, and won't
// fail to parse URLs, so the test must allow for either outcome.
XCTAssertNotNil(result)
XCTAssertFalse(result?.boolValue ?? true)
XCTAssertNil(error)
let result = createPlugin().canLaunchUrl(url: "urls can't have spaces")

if urlParsingIsStrict() {
XCTAssertEqual(result, .invalidUrl)
} else {
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")
XCTAssertEqual(result, .failure)
}
}

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)
createPlugin().launchUrl(url: "good://url", universalLinksOnly: false) { result in
switch result {
case .success(let details):
XCTAssertEqual(details, .success)
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}
expectation.fulfill()
}

Expand All @@ -68,11 +61,13 @@ final class URLLauncherTests: XCTestCase {

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)
createPlugin().launchUrl(url: "bad://url", universalLinksOnly: false) { result in
switch result {
case .success(let details):
XCTAssertEqual(details, .failure)
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}
expectation.fulfill()
}

Expand All @@ -81,22 +76,17 @@ final class URLLauncherTests: XCTestCase {

func testLaunchFailureWithInvalidURL() {
let expectation = XCTestExpectation(description: "completion called")

createPlugin().launchURL("urls can't have spaces", universalLinksOnly: false) { result, error in
if (error == nil) {
// When linking against the iOS 17 SDK or later, NSURL uses a lenient parser, and won't
// fail to parse URLs, so the test must allow for either outcome.
XCTAssertNotNil(result)
XCTAssertFalse(result?.boolValue ?? true)
XCTAssertNil(error)
} else {
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")
createPlugin().launchUrl(url: "urls can't have spaces", universalLinksOnly: false) { result in
switch result {
case .success(let details):
if urlParsingIsStrict() {
XCTAssertEqual(details, .invalidUrl)
} else {
XCTAssertEqual(details, .failure)
}
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}

expectation.fulfill()
}

Expand All @@ -108,13 +98,17 @@ final class URLLauncherTests: XCTestCase {
let plugin = createPlugin(launcher: launcher)

let expectation = XCTestExpectation(description: "completion called")
plugin.launchURL("good://url", universalLinksOnly: false) { result, error in
XCTAssertNil(error)
plugin.launchUrl(url: "good://url", universalLinksOnly: false) { result in
switch result {
case .success(let details):
XCTAssertEqual(details, .success)
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}
expectation.fulfill()
}

wait(for: [expectation], timeout: 1)

XCTAssertEqual(launcher.passedOptions?[.universalLinksOnly] as? Bool, false)
}

Expand All @@ -123,31 +117,35 @@ final class URLLauncherTests: XCTestCase {
let plugin = createPlugin(launcher: launcher)

let expectation = XCTestExpectation(description: "completion called")

plugin.launchURL("good://url", universalLinksOnly: true) { result, error in
XCTAssertNil(error)
plugin.launchUrl(url: "good://url", universalLinksOnly: true) { result in
switch result {
case .success(let details):
XCTAssertEqual(details, .success)
case .failure(let error):
XCTFail("Unexpected error: \(error)")
}
expectation.fulfill()
}

wait(for: [expectation], timeout: 1)

XCTAssertEqual(launcher.passedOptions?[.universalLinksOnly] as? Bool, true)
}

}

final private class FakeLauncher: NSObject, FULLauncher {
final private class FakeLauncher: NSObject, Launcher {
var passedOptions: [UIApplication.OpenExternalURLOptionsKey: Any]?

func canOpen(_ url: URL) -> Bool {
return url.scheme == "good"
func canOpenURL(_ url: URL) -> Bool {
url.scheme == "good"
}

func open(
_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any] = [:],
completionHandler: ((Bool) -> Void)? = nil
_ url: URL,
options: [UIApplication.OpenExternalURLOptionsKey: Any],
completionHandler completion: ((Bool) -> Void)?
) {
self.passedOptions = options
completionHandler?(url.scheme == "good")
completion?(url.scheme == "good")
}
}

This file was deleted.

Loading

0 comments on commit 3aff029

Please sign in to comment.