Skip to content

Commit

Permalink
Merge pull request #34 from hyperoslo/feature/payload
Browse files Browse the repository at this point in the history
Feature: location payload
  • Loading branch information
zenangst committed Aug 24, 2016
2 parents b061d66 + 28dbc2d commit 5897840
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 16 deletions.
10 changes: 5 additions & 5 deletions Sources/Compass.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ public struct Compass {

public static var routes = [String]()

public static func parse(url: NSURL, fragments: [String : AnyObject] = [:]) -> Location? {
public static func parse(url: NSURL, payload: Any? = nil) -> Location? {
let path = url.absoluteString.substringFromIndex(scheme.endIndex)

guard !(path.containsString("?") || path.containsString("#")) else {
return parseAsURL(url, fragments: fragments)
return parseAsURL(url, payload: payload)
}

let results: [Result] = routes.flatMap {
Expand All @@ -36,13 +36,13 @@ public struct Compass {
}

if let result = results.first {
return Location(path: result.route, arguments: result.arguments, fragments: fragments)
return Location(path: result.route, arguments: result.arguments, payload: payload)
}

return nil
}

static func parseAsURL(url: NSURL, fragments: [String : AnyObject] = [:]) -> Location? {
static func parseAsURL(url: NSURL, payload: Any? = nil) -> Location? {
guard let route = url.host else { return nil }

let urlComponents = NSURLComponents(URL: url, resolvingAgainstBaseURL: false)
Expand All @@ -56,7 +56,7 @@ public struct Compass {
arguments = fragment.queryParameters()
}

return Location(path: route, arguments: arguments, fragments: fragments)
return Location(path: route, arguments: arguments, payload: payload)
}

static func findMatch(routeString: String, pathString: String) -> Result? {
Expand Down
6 changes: 3 additions & 3 deletions Sources/Location.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ public struct Location {

public let path: String
public let arguments: [String: String]
public let fragments: [String: AnyObject]
public let payload: Any?

public var scheme: String {
return Compass.scheme
}

public init(path: String, arguments: [String: String] = [:], fragments: [String: AnyObject] = [:]) {
public init(path: String, arguments: [String: String] = [:], payload: Any? = nil) {
self.path = path
self.arguments = arguments
self.fragments = fragments
self.payload = payload
}
}
26 changes: 23 additions & 3 deletions Sources/Router.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
public enum RouteError: ErrorType {
case NotFound
case InvalidArguments(Location)
case InvalidPayload(Location)
}

public protocol Routable {

func navigate(to location: Location, from currentController: Controller)
func navigate(to location: Location, from currentController: Controller) throws
}

public protocol ErrorRoutable {

func handle(routeError: ErrorType, from currentController: Controller)
}

public struct Router: Routable {

public var routes = [String: Routable]()
public var errorRoute: ErrorRoutable?

public init() {}

public func navigate(to location: Location, from currentController: Controller) {
guard let route = routes[location.path] else { return }
route.navigate(to: location, from: currentController)
guard let route = routes[location.path] else {
errorRoute?.handle(RouteError.NotFound, from: currentController)
return
}

do {
try route.navigate(to: location, from: currentController)
} catch {
errorRoute?.handle(error, from: currentController)
}
}
}
9 changes: 6 additions & 3 deletions Tests/Compass/CompassTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,20 @@ class CompassTests: XCTestCase {
XCTAssertEqual(location.arguments["user"], "testUser")
}

func testParseFragments() {
func testParsePayload() {
let url = NSURL(string: "compassTests://profile:testUser")!

guard let location = Compass.parse(url, fragments: ["meta" : "foo"]) else {
typealias Payload = (firstName: String, lastName: String)

guard let location = Compass.parse(url, payload: Payload(firstName: "foo", lastName: "bar")) else {
XCTFail("Compass parsing failed")
return
}

XCTAssertEqual("profile:{user}", location.path)
XCTAssertEqual(location.arguments["user"], "testUser")
XCTAssertEqual("foo" , location.fragments["meta"] as? String)
XCTAssertEqual("foo" , (location.payload as? Payload)?.firstName)
XCTAssertEqual("bar" , (location.payload as? Payload)?.lastName)
}

func testParseRouteConcreateMatchCount() {
Expand Down
22 changes: 21 additions & 1 deletion Tests/Compass/Helpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,31 @@ class TestRoute: Routable {

var resolved = false

func navigate(to location: Location, from currentController: Controller) {
func navigate(to location: Location, from currentController: Controller) throws {
resolved = true
}
}

class ThrowableRoute: Routable {

enum Error: ErrorType {
case Unknown
}

func navigate(to location: Location, from currentController: Controller) throws {
throw Error.Unknown
}
}

class ErrorRoute: ErrorRoutable {

var error: ErrorType?

func handle(routeError: ErrorType, from currentController: Controller) {
error = routeError
}
}

// MARK: - Shuffle

extension CollectionType {
Expand Down
16 changes: 15 additions & 1 deletion Tests/Compass/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,38 @@ import XCTest
class RouterTests: XCTestCase {

var router: Router!
var controller = Controller()
var route: TestRoute!
var controller: Controller!
var errorRoute: ErrorRoute!

override func setUp() {
router = Router()
route = TestRoute()
controller = Controller()
errorRoute = ErrorRoute()

router.errorRoute = errorRoute
}

func testNavigateIfRouteRegistered() {
router.routes["test"] = route
router.navigate(to: Location(path: "test"), from: controller)

XCTAssertTrue(route.resolved)
XCTAssertNil(errorRoute.error)
}

func testNavigateIfRouteNotRegistered() {
router.navigate(to: Location(path: "test"), from: controller)

XCTAssertFalse(route.resolved)
XCTAssertTrue(errorRoute.error is RouteError)
}

func testNavigateIfRouteThrowsError() {
router.routes["throw"] = ThrowableRoute()
router.navigate(to: Location(path: "throw"), from: controller)

XCTAssertTrue(errorRoute.error is ThrowableRoute.Error)
}
}

0 comments on commit 5897840

Please sign in to comment.