diff --git a/Sources/Navigator.swift b/Sources/Navigator.swift index 1b6c138..e762c9f 100644 --- a/Sources/Navigator.swift +++ b/Sources/Navigator.swift @@ -16,6 +16,9 @@ public struct Navigator { /// A list of route strings public static var routes = [String]() + /// Handle the location request + public static var handle: ((Location) -> Void)? + /// Parse Location from url /// /// - Parameters: @@ -116,3 +119,45 @@ public struct Navigator { wildcardMatchCount: wildcardMatchCount) } } + +public extension Navigator { + + /// Navigate using urn + /// + /// - Parameters: + /// - urn: The urn + /// - payload: Optional payload + /// - Throws: RouteError if the routing fails + public static func navigate(urn: String, payload: Any? = nil) throws { + let encodedUrn = PercentEncoder.encode(string: urn, allowedCharacters: delimiter) + guard let url = URL(string: "\(scheme)\(encodedUrn)") else { + throw RouteError.notFound + } + + try navigate(url: url, payload: payload) + } + + /// Navigate using url + /// + /// - Parameters: + /// - urn: The url + /// - payload: Optional payload + /// - Throws: RouteError if the routing fails + public static func navigate(url: URL, payload: Any? = nil) throws { + guard let location = parse(url: url, payload: payload) else { + throw RouteError.notFound + } + + try navigate(location: location) + } + + /// Navigate using location + /// + /// - Parameters: + /// - urn: The urn + /// - payload: Optional payload + /// - Throws: RouteError if the routing fails + public static func navigate(location: Location) throws { + handle?(location) + } +} diff --git a/Tests/Compass/CompassTests.swift b/Tests/Compass/CompassTests.swift index aa12092..086012c 100644 --- a/Tests/Compass/CompassTests.swift +++ b/Tests/Compass/CompassTests.swift @@ -264,4 +264,16 @@ class CompassTests: XCTestCase { XCTAssertEqual(location.arguments["expires_in"], "3600") XCTAssertEqual(location.arguments["token_type"], "Bearer") } + + func testParseEncodedURL() { + let urn = "organization:hyper oslo:simply awesome" + Navigator.handle = { location in + XCTAssertEqual(location.arguments["name"], "hyper oslo") + XCTAssertEqual(location.arguments["type"], "simply awesome") + } + + try? Navigator.navigate(urn: urn) + + wait(for: 0.1) + } } diff --git a/Tests/Compass/Helpers.swift b/Tests/Compass/Helpers.swift index 2585b38..ac33f94 100644 --- a/Tests/Compass/Helpers.swift +++ b/Tests/Compass/Helpers.swift @@ -1,4 +1,5 @@ import Foundation +import XCTest @testable import Compass // MARK: - Routes @@ -49,3 +50,17 @@ extension Array { } } +extension XCTestCase { + func wait(for duration: TimeInterval) { + let waitExpectation = expectation(description: "Waiting") + + let when = DispatchTime.now() + duration + DispatchQueue.main.asyncAfter(deadline: when) { + waitExpectation.fulfill() + } + + // We use a buffer here to avoid flakiness with Timer on CI + waitForExpectations(timeout: duration + 0.5) + } +} +