Skip to content

Commit

Permalink
Merge pull request #17 from giginet/support-slash-prefix
Browse files Browse the repository at this point in the history
Support relative path
  • Loading branch information
giginet committed Aug 2, 2019
2 parents cc1a2eb + 85c934e commit 945f979
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ Imagine to implement Pokédex on iOS. You can access somewhere via URL scheme.
```swift
router = DefaultRouter(scheme: "pokedex")
router.register([
("pokedex://pokemons", { context in
("/pokemons", { context in
let type: Type? = context.parameter(for: "type")
presentPokedexListViewController(for: type)
return true
}),
("pokedex://pokemons/:pokedexID", { context in
("/pokemons/:pokedexID", { context in
guard let pokedexID: Int? = try? context.argument(for: "pokedexID") else {
// pokedexID must be Int
return false
Expand Down
15 changes: 11 additions & 4 deletions Sources/Crossroad/Router.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,28 @@ public final class Router<UserInfo> {
return routes.first { $0.responds(to: url, userInfo: userInfo) } != nil
}

private func canonicalizePattern(_ pattern: String) -> String {
if pattern.hasPrefix("/") {
return String(pattern.dropFirst())
}
return pattern
}

public func register(_ routes: [(String, Route<UserInfo>.Handler)]) {
for (pattern, handler) in routes {
let patternURLString: String
switch prefix {
case .scheme(let scheme):
if pattern.hasPrefix("\(scheme)://") {
patternURLString = pattern
patternURLString = canonicalizePattern(pattern)
} else {
patternURLString = "\(scheme)://\(pattern)"
patternURLString = "\(scheme)://\(canonicalizePattern(pattern))"
}
case .url(let url):
if pattern.hasPrefix(url.absoluteString) {
patternURLString = pattern
patternURLString = canonicalizePattern(pattern)
} else {
patternURLString = url.appendingPathComponent(pattern).absoluteString
patternURLString = url.appendingPathComponent(canonicalizePattern(pattern)).absoluteString
}
}
guard let patternURL = PatternURL(string: patternURLString) else {
Expand Down
67 changes: 67 additions & 0 deletions Tests/CrossroadTests/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,29 @@ final class RouterTest: XCTestCase {
XCTAssertFalse(router.responds(to: URL(string: "spam/ham")!))
}

func testCanRespondWithRelativePath() {
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 testCanRespondWithoutPrefixWithURLPrefix() {
let router = SimpleRouter(url: URL(string: "https://example.com/")!)
router.register([
Expand Down Expand Up @@ -231,6 +254,50 @@ final class RouterTest: XCTestCase {
wait(for: [expectation], timeout: 2.0)
}

func testHandleWithSlashPrefix() {
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 testHandleWithoutPrefixWithURLPrefix() {
let router = SimpleRouter(url: URL(string: "https://example.com")!)
let expectation = self.expectation(description: "Should called handler four times")
Expand Down

0 comments on commit 945f979

Please sign in to comment.