-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type scheme once only #5
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,21 +3,13 @@ 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) { | ||
self.scheme = scheme | ||
} | ||
|
||
internal func register(_ route: Route<UserInfo>) { | ||
if scheme != route.patternURL.scheme { | ||
assertionFailure("Router and pattern must have the same schemes. expect: \(scheme), actual: \(route.patternURL.scheme)") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please do not remove this error. |
||
} else { | ||
routes.append(route) | ||
} | ||
} | ||
|
||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you execute |
||
@discardableResult | ||
public func openIfPossible(_ url: URL, userInfo: UserInfo) -> Bool { | ||
if scheme != url.scheme { | ||
|
@@ -35,12 +27,17 @@ public final class Router<UserInfo> { | |
|
||
public func register(_ routes: [(String, Route<UserInfo>.Handler)]) { | ||
for (pattern, handler) in routes { | ||
var pattern = pattern | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can write more clearly code. public func register(_ routes: [(String, Route<UserInfo>.Handler)]) {
for (pattern, handler) in routes {
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
}
let route = Route(pattern: patternURL, handler: handler)
register(route)
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you needn't remove |
||
let value = URL(string: pattern)?.scheme | ||
if value == nil || value?.isEmpty ?? true { | ||
pattern = scheme + "://" + pattern | ||
} | ||
guard let patternURL = PatternURL(string: pattern) else { | ||
assertionFailure("\(pattern) is invalid") | ||
continue | ||
} | ||
let route = Route(pattern: patternURL, handler: handler) | ||
register(route) | ||
self.routes.append(route) | ||
} | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,23 @@ final class RouterTest: XCTestCase { | |
XCTAssertFalse(router.responds(to: URL(string: "notfoobar://aaa/bbb")!)) | ||
XCTAssertTrue(router.responds(to: URL(string: "foobar://spam/ham")!)) | ||
} | ||
|
||
func testCanRespond2() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
let router = SimpleRouter(scheme: schema) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I found typo. Could you fix them?
|
||
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")!)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add assertions to check without scheme patterns? XCTAssertFalse(router.responds(to: URL(string: "static")!))
XCTAssertFalse(router.responds(to: URL(string: "foo/bar")!))
XCTAssertFalse(router.responds(to: URL(string: "spam/ham")!)) |
||
XCTAssertTrue(router.responds(to: URL(string: "foobar://spam/ham")!)) | ||
} | ||
|
||
func testHandle() { | ||
let router = SimpleRouter(scheme: schema) | ||
|
@@ -61,6 +78,45 @@ final class RouterTest: XCTestCase { | |
XCTAssertFalse(router.openIfPossible(URL(string: "notfoobar://static")!)) | ||
wait(for: [expectation], timeout: 2.0) | ||
} | ||
|
||
func testHandle2() { | ||
let router = SimpleRouter(scheme: schema) | ||
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")!)) | ||
wait(for: [expectation], timeout: 2.0) | ||
} | ||
|
||
func testHandlerWithSamePatterns() { | ||
let router = SimpleRouter(scheme: schema) | ||
|
@@ -88,6 +144,33 @@ final class RouterTest: XCTestCase { | |
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!)) | ||
wait(for: [idExpectation, keywordExpectation], timeout: 2.0) | ||
} | ||
|
||
func testHandlerWithSamePatterns2() { | ||
let router = SimpleRouter(scheme: schema) | ||
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")!)) | ||
wait(for: [idExpectation, keywordExpectation], timeout: 2.0) | ||
} | ||
|
||
func testHandleReturnsFalse() { | ||
let router = SimpleRouter(scheme: schema) | ||
|
@@ -107,6 +190,25 @@ final class RouterTest: XCTestCase { | |
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://foo/bar")!)) | ||
wait(for: [expectation], timeout: 2.0) | ||
} | ||
|
||
func testHandleReturnsFalse2() { | ||
let router = SimpleRouter(scheme: schema) | ||
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")!)) | ||
wait(for: [expectation], timeout: 2.0) | ||
} | ||
|
||
func testWithUserInfo() { | ||
struct UserInfo { | ||
|
@@ -124,4 +226,21 @@ final class RouterTest: XCTestCase { | |
XCTAssertTrue(router.openIfPossible(URL(string: "foobar://static")!, userInfo: UserInfo(value: 42))) | ||
XCTAssertEqual(userInfo?.value, 42) | ||
} | ||
|
||
func testWithUserInfo2() { | ||
struct UserInfo { | ||
let value: Int | ||
} | ||
let router = Router<UserInfo>(scheme: schema) | ||
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))) | ||
XCTAssertEqual(userInfo?.value, 42) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we conceal this property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, I guess that nobody use
Router.scheme
from external. 🤔There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so. I think it might be good to release API, once it becomes useful.