Skip to content

Commit

Permalink
Merge pull request #5 from rob-nash/develop
Browse files Browse the repository at this point in the history
Type scheme once only
  • Loading branch information
giginet committed Jun 6, 2018
2 parents 639dab0 + 0f6449b commit ecf4887
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 8 deletions.
10 changes: 8 additions & 2 deletions Sources/Crossroad/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation
public typealias SimpleRouter = Router<Void>

public final class Router<UserInfo> {
public let scheme: String
private let scheme: String
private var routes: [Route<UserInfo>] = []

public init(scheme: String) {
Expand Down Expand Up @@ -35,7 +35,13 @@ public final class Router<UserInfo> {

public func register(_ routes: [(String, Route<UserInfo>.Handler)]) {
for (pattern, handler) in routes {
guard let patternURL = PatternURL(string: pattern) else {
let patternURLString: String
if pattern.hasPrefix("\(scheme)://") {
patternURLString = pattern
} else {
patternURLString = "\(scheme)://\(pattern)"
}
guard let patternURL = PatternURL(string: patternURLString) else {
assertionFailure("\(pattern) is invalid")
continue
}
Expand Down
161 changes: 155 additions & 6 deletions Tests/CrossroadTests/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import XCTest
import Crossroad

final class RouterTest: XCTestCase {
let schema = "foobar"
let scheme = "foobar"

func testCanRespond() {
let router = SimpleRouter(scheme: schema)
let router = SimpleRouter(scheme: scheme)
router.register([
("foobar://static", { _ in true }),
("foobar://foo/bar", { _ in true }),
Expand All @@ -21,10 +21,39 @@ final class RouterTest: XCTestCase {
XCTAssertFalse(router.responds(to: URL(string: "foobar://aaa/bbb")!))
XCTAssertFalse(router.responds(to: URL(string: "notfoobar://aaa/bbb")!))
XCTAssertTrue(router.responds(to: URL(string: "foobar://spam/ham")!))
XCTAssertFalse(router.responds(to: URL(string: "static")!))
XCTAssertFalse(router.responds(to: URL(string: "foo")!))
XCTAssertFalse(router.responds(to: URL(string: "foo/bar")!))
XCTAssertFalse(router.responds(to: URL(string: "foo/10000")!))
XCTAssertFalse(router.responds(to: URL(string: "aaa/bbb")!))
XCTAssertFalse(router.responds(to: URL(string: "spam/ham")!))
}

func testCanRespondWithoutScheme() {
let router = SimpleRouter(scheme: scheme)
router.register([
("static", { _ in true }),
("foo/bar", { _ in true }),
("spam/ham", { _ in false }),
(":keyword", { _ in true }),
("foo/:keyword", { _ in true }),
])
XCTAssertTrue(router.responds(to: URL(string: "foobar://static")!))
XCTAssertTrue(router.responds(to: URL(string: "foobar://foo")!))
XCTAssertTrue(router.responds(to: URL(string: "foobar://foo/bar")!))
XCTAssertTrue(router.responds(to: URL(string: "foobar://foo/10000")!))
XCTAssertFalse(router.responds(to: URL(string: "notfoobar://aaa/bbb")!))
XCTAssertTrue(router.responds(to: URL(string: "foobar://spam/ham")!))
XCTAssertFalse(router.responds(to: URL(string: "static")!))
XCTAssertFalse(router.responds(to: URL(string: "foo")!))
XCTAssertFalse(router.responds(to: URL(string: "foo/bar")!))
XCTAssertFalse(router.responds(to: URL(string: "foo/10000")!))
XCTAssertFalse(router.responds(to: URL(string: "aaa/bbb")!))
XCTAssertFalse(router.responds(to: URL(string: "spam/ham")!))
}

func testHandle() {
let router = SimpleRouter(scheme: schema)
let router = SimpleRouter(scheme: scheme)
let expectation = self.expectation(description: "Should called handler four times")
expectation.expectedFulfillmentCount = 4
router.register([
Expand Down Expand Up @@ -59,11 +88,60 @@ final class RouterTest: XCTestCase {
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/hoge/fuga")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foobar://spam/ham")!))
XCTAssertFalse(router.openIfPossible(URL(string: "notfoobar://static")!))
XCTAssertFalse(router.openIfPossible(URL(string: "static")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar?param0=123")!))
XCTAssertFalse(router.openIfPossible(URL(string: "hoge")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/hoge/fuga")!))
XCTAssertFalse(router.openIfPossible(URL(string: "spam/ham")!))
wait(for: [expectation], timeout: 2.0)
}

func testHandleWithoutScheme() {
let router = SimpleRouter(scheme: scheme)
let expectation = self.expectation(description: "Should called handler four times")
expectation.expectedFulfillmentCount = 4
router.register([
("static", { context in
XCTAssertEqual(context.url, URL(string: "foobar://static")!)
expectation.fulfill()
return true
}),
("foo/bar", { context in
XCTAssertEqual(context.parameter(for: "param0"), 123)
XCTAssertEqual(context.url, URL(string: "foobar://foo/bar?param0=123")!)
expectation.fulfill()
return true
}),
(":keyword", { context in
XCTAssertEqual(context.url, URL(string: "foobar://hoge")!)
XCTAssertEqual(try? context.argument(for: "keyword"), "hoge")
expectation.fulfill()
return true
}),
("foo/:keyword/:keyword2", { context in
XCTAssertEqual(context.url, URL(string: "foobar://foo/hoge/fuga")!)
XCTAssertEqual(try? context.argument(for: "keyword"), "hoge")
XCTAssertEqual(try? context.argument(for: "keyword2"), "fuga")
expectation.fulfill()
return true
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://static")!))
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar?param0=123")!))
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://hoge")!))
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/hoge/fuga")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foobar://spam/ham")!))
XCTAssertFalse(router.openIfPossible(URL(string: "notfoobar://static")!))
XCTAssertFalse(router.openIfPossible(URL(string: "static")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar?param0=123")!))
XCTAssertFalse(router.openIfPossible(URL(string: "hoge")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/hoge/fuga")!))
XCTAssertFalse(router.openIfPossible(URL(string: "spam/ham")!))
wait(for: [expectation], timeout: 2.0)
}

func testHandlerWithSamePatterns() {
let router = SimpleRouter(scheme: schema)
let router = SimpleRouter(scheme: scheme)
let idExpectation = self.expectation(description: "Should called handler with ID")
let keywordExpectation = self.expectation(description: "Should called handler with keyword")
router.register([
Expand All @@ -86,11 +164,42 @@ final class RouterTest: XCTestCase {
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/42")!))
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/42")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar")!))
wait(for: [idExpectation, keywordExpectation], timeout: 2.0)
}

func testHandlerWithSamePatternsWithoutScheme() {
let router = SimpleRouter(scheme: scheme)
let idExpectation = self.expectation(description: "Should called handler with ID")
let keywordExpectation = self.expectation(description: "Should called handler with keyword")
router.register([
("foo/:id", { context in
guard let id: Int = try? context.argument(for: "id") else {
return false
}
XCTAssertEqual(context.url, URL(string: "foobar://foo/42")!)
XCTAssertEqual(id, 42)
idExpectation.fulfill()
return true
}),
("foo/:keyword", { context in
let keyword: String = try! context.argument(for: "keyword")
XCTAssertEqual(context.url, URL(string: "foobar://foo/bar")!)
XCTAssertEqual(keyword, "bar")
keywordExpectation.fulfill()
return true
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/42")!))
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/42")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar")!))
wait(for: [idExpectation, keywordExpectation], timeout: 2.0)
}

func testHandleReturnsFalse() {
let router = SimpleRouter(scheme: schema)
let router = SimpleRouter(scheme: scheme)
let expectation = self.expectation(description: "Should called handler twice")
expectation.expectedFulfillmentCount = 2
router.register([
Expand All @@ -105,14 +214,35 @@ final class RouterTest: XCTestCase {
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar")!))
wait(for: [expectation], timeout: 2.0)
}

func testHandleReturnsFalseWithoutScheme() {
let router = SimpleRouter(scheme: scheme)
let expectation = self.expectation(description: "Should called handler twice")
expectation.expectedFulfillmentCount = 2
router.register([
("foo/bar", { _ in
expectation.fulfill()
return false
}),
("foo/:keyword", { context in
XCTAssertEqual(try? context.argument(for: "keyword"), "bar")
expectation.fulfill()
return true
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!))
XCTAssertFalse(router.openIfPossible(URL(string: "foo/bar")!))
wait(for: [expectation], timeout: 2.0)
}

func testWithUserInfo() {
struct UserInfo {
let value: Int
}
let router = Router<UserInfo>(scheme: schema)
let router = Router<UserInfo>(scheme: scheme)
var userInfo: UserInfo? = nil
router.register([
("foobar://static", { context in
Expand All @@ -122,6 +252,25 @@ final class RouterTest: XCTestCase {
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://static")!, userInfo: UserInfo(value: 42)))
XCTAssertFalse(router.openIfPossible(URL(string: "static")!, userInfo: UserInfo(value: 42)))
XCTAssertEqual(userInfo?.value, 42)
}

func testWithUserInfoWithoutScheme() {
struct UserInfo {
let value: Int
}
let router = Router<UserInfo>(scheme: scheme)
var userInfo: UserInfo? = nil
router.register([
("static", { context in
XCTAssertEqual(context.url, URL(string: "foobar://static")!)
userInfo = context.userInfo
return true
}),
])
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://static")!, userInfo: UserInfo(value: 42)))
XCTAssertFalse(router.openIfPossible(URL(string: "static")!, userInfo: UserInfo(value: 42)))
XCTAssertEqual(userInfo?.value, 42)
}
}

0 comments on commit ecf4887

Please sign in to comment.