[url_launcher] Improving unit tests on mac (#4472)
Add unit tests for url_launcher canLaunch and launch methods on mac with success and failure results.
Fixes #92969
diff --git a/packages/url_launcher/url_launcher_macos/CHANGELOG.md b/packages/url_launcher/url_launcher_macos/CHANGELOG.md
index 7b7677a..9281c91 100644
--- a/packages/url_launcher/url_launcher_macos/CHANGELOG.md
+++ b/packages/url_launcher/url_launcher_macos/CHANGELOG.md
@@ -1,6 +1,7 @@
-## NEXT
+## 2.0.3
* Updates code for new analysis options.
+* Updates unit tests.
## 2.0.2
diff --git a/packages/url_launcher/url_launcher_macos/example/macos/RunnerTests/RunnerTests.swift b/packages/url_launcher/url_launcher_macos/example/macos/RunnerTests/RunnerTests.swift
index d08f664..adbd114 100644
--- a/packages/url_launcher/url_launcher_macos/example/macos/RunnerTests/RunnerTests.swift
+++ b/packages/url_launcher/url_launcher_macos/example/macos/RunnerTests/RunnerTests.swift
@@ -6,19 +6,149 @@
import XCTest
import url_launcher_macos
+/// A stub to simulate the system Url handler.
+class StubWorkspace: SystemURLHandler {
+
+ var isSuccessful = true
+
+ func open(_ url: URL) -> Bool {
+ return isSuccessful
+ }
+
+ func urlForApplication(toOpen: URL) -> URL? {
+ return toOpen
+ }
+}
+
class RunnerTests: XCTestCase {
- func testCanLaunch() throws {
+
+ func testCanLaunchSuccessReturnsTrue() throws {
+ let expectation = XCTestExpectation(description: "Check if the URL can be launched")
let plugin = UrlLauncherPlugin()
+
let call = FlutterMethodCall(
methodName: "canLaunch",
arguments: ["url": "https://flutter.dev"])
- var canLaunch: Bool?
+
plugin.handle(
call,
result: { (result: Any?) -> Void in
- canLaunch = result as? Bool
+ XCTAssertEqual(result as? Bool, true)
+ expectation.fulfill()
})
- XCTAssertTrue(canLaunch == true)
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testCanLaunchNoAppIsAbleToOpenUrlReturnsFalse() throws {
+ let expectation = XCTestExpectation(description: "Check if the URL can be launched")
+ let plugin = UrlLauncherPlugin()
+
+ let call = FlutterMethodCall(
+ methodName: "canLaunch",
+ arguments: ["url": "example://flutter.dev"])
+
+ plugin.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertEqual(result as? Bool, false)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testCanLaunchInvalidUrlReturnsFalse() throws {
+ let expectation = XCTestExpectation(description: "Check if the URL can be launched")
+ let plugin = UrlLauncherPlugin()
+
+ let call = FlutterMethodCall(
+ methodName: "canLaunch",
+ arguments: ["url": "brokenUrl"])
+
+ plugin.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertEqual(result as? Bool, false)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testCanLaunchMissingArgumentReturnsFlutterError() throws {
+ let expectation = XCTestExpectation(description: "Check if the URL can be launched")
+ let plugin = UrlLauncherPlugin()
+
+ let call = FlutterMethodCall(
+ methodName: "canLaunch",
+ arguments: [])
+
+ plugin.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertTrue(result is FlutterError)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testLaunchSuccessReturnsTrue() throws {
+ let expectation = XCTestExpectation(description: "Try to open the URL")
+ let workspace = StubWorkspace()
+ let pluginWithStubWorkspace = UrlLauncherPlugin(workspace)
+
+ let call = FlutterMethodCall(
+ methodName: "launch",
+ arguments: ["url": "https://flutter.dev"])
+
+ pluginWithStubWorkspace.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertEqual(result as? Bool, true)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testLaunchNoAppIsAbleToOpenUrlReturnsFalse() throws {
+ let expectation = XCTestExpectation(description: "Try to open the URL")
+ let workspace = StubWorkspace()
+ workspace.isSuccessful = false
+ let pluginWithStubWorkspace = UrlLauncherPlugin(workspace)
+
+ let call = FlutterMethodCall(
+ methodName: "launch",
+ arguments: ["url": "schemethatdoesnotexist://flutter.dev"])
+
+ pluginWithStubWorkspace.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertEqual(result as? Bool, false)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
+ }
+
+ func testLaunchMissingArgumentReturnsFlutterError() throws {
+ let expectation = XCTestExpectation(description: "Try to open the URL")
+ let workspace = StubWorkspace()
+ let pluginWithStubWorkspace = UrlLauncherPlugin(workspace)
+
+ let call = FlutterMethodCall(
+ methodName: "launch",
+ arguments: [])
+
+ pluginWithStubWorkspace.handle(
+ call,
+ result: { (result: Any?) -> Void in
+ XCTAssertTrue(result is FlutterError)
+ expectation.fulfill()
+ })
+
+ wait(for: [expectation], timeout: 10.0)
}
}
diff --git a/packages/url_launcher/url_launcher_macos/macos/Classes/UrlLauncherPlugin.swift b/packages/url_launcher/url_launcher_macos/macos/Classes/UrlLauncherPlugin.swift
index ab89038..c311b85 100644
--- a/packages/url_launcher/url_launcher_macos/macos/Classes/UrlLauncherPlugin.swift
+++ b/packages/url_launcher/url_launcher_macos/macos/Classes/UrlLauncherPlugin.swift
@@ -5,7 +5,35 @@
import FlutterMacOS
import Foundation
+/// A handler that can launch other apps, check if any app is able to open the URL.
+public protocol SystemURLHandler {
+
+ /// Opens the location at the specified URL.
+ ///
+ /// - Parameters:
+ /// - url: A URL specifying the location to open.
+ /// - Returns: true if the location was successfully opened; otherwise, false.
+ func open(_ url: URL) -> Bool
+
+ /// Returns the URL to the default app that would be opened.
+ ///
+ /// - Parameters:
+ /// - toOpen: The URL of the file to open.
+ /// - Returns: The URL of the default app that would open the specified url.
+ /// Returns nil if no app is able to open the URL, or if the file URL does not exist.
+ func urlForApplication(toOpen: URL) -> URL?
+}
+
+extension NSWorkspace: SystemURLHandler {}
+
public class UrlLauncherPlugin: NSObject, FlutterPlugin {
+
+ private var workspace: SystemURLHandler
+
+ public init(_ workspace: SystemURLHandler = NSWorkspace.shared) {
+ self.workspace = workspace
+ }
+
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "plugins.flutter.io/url_launcher",
@@ -24,7 +52,7 @@
result(invalidURLError(urlString))
return
}
- result(NSWorkspace.shared.urlForApplication(toOpen: url) != nil)
+ result(workspace.urlForApplication(toOpen: url) != nil)
case "launch":
guard let unwrappedURLString = urlString,
let url = URL.init(string: unwrappedURLString)
@@ -32,7 +60,7 @@
result(invalidURLError(urlString))
return
}
- result(NSWorkspace.shared.open(url))
+ result(workspace.open(url))
default:
result(FlutterMethodNotImplemented)
}
diff --git a/packages/url_launcher/url_launcher_macos/pubspec.yaml b/packages/url_launcher/url_launcher_macos/pubspec.yaml
index 01f1db0..55e8ec3 100644
--- a/packages/url_launcher/url_launcher_macos/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_macos/pubspec.yaml
@@ -2,7 +2,7 @@
description: macOS implementation of the url_launcher plugin.
repository: https://github.com/flutter/plugins/tree/master/packages/url_launcher/url_launcher_macos
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+url_launcher%22
-version: 2.0.2
+version: 2.0.3
environment:
sdk: ">=2.12.0 <3.0.0"