Skip to content

Commit

Permalink
Add tests for RouteCollections
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-fowler committed Apr 21, 2024
1 parent 3357bd9 commit 66b050c
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 11 deletions.
10 changes: 6 additions & 4 deletions Sources/Hummingbird/Router/RouteCollection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import HTTPTypes
/// Collection of routes
public final class RouteCollection<Context: BaseRequestContext>: RouterMethods {
/// Initialize RouteCollection
public init() {
public init(context: Context.Type = BasicRequestContext.self) {
self.routes = .init()
self.middlewares = .init()
}
Expand All @@ -40,7 +40,7 @@ public final class RouteCollection<Context: BaseRequestContext>: RouterMethods {

/// Return a group inside the route collection
/// - Parameter path: path prefix to add to routes inside this group
public func group(_ path: String) -> RouterGroup<Context> {
public func group(_ path: String = "") -> RouterGroup<Context> {
return .init(path: path, router: self)
}

Expand All @@ -62,9 +62,11 @@ public final class RouteCollection<Context: BaseRequestContext>: RouterMethods {
extension RouterMethods {
/// Add route collection to router
/// - Parameter collection: Route collection
public func add(_ collection: RouteCollection<Context>) {
public func add(_ path: String = "", routes collection: RouteCollection<Context>) {
for (definition, responder) in collection.routes {
self.on(definition.path, method: definition.method, responder: collection.middlewares.constructResponder(finalResponder: responder))
// ensure path starts with a "/" and doesn't end with a "/"
let path = self.combinePaths(path, definition.path)
self.on(path, method: definition.method, responder: collection.middlewares.constructResponder(finalResponder: responder))
}
}
}
6 changes: 0 additions & 6 deletions Sources/Hummingbird/Router/RouterGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,4 @@ public struct RouterGroup<Context: BaseRequestContext>: RouterMethods {
self.router.on(path, method: method, responder: self.middlewares.constructResponder(finalResponder: responder))
return self
}

internal func combinePaths(_ path1: String, _ path2: String) -> String {
let path1 = path1.dropSuffix("/")
let path2 = path2.dropPrefix("/")
return "\(path1)/\(path2)"
}
}
8 changes: 7 additions & 1 deletion Sources/Hummingbird/Router/RouterMethods.swift
Original file line number Diff line number Diff line change
Expand Up @@ -96,12 +96,18 @@ extension RouterMethods {
return self.on(path, method: .patch, use: handler)
}

func constructResponder(
internal func constructResponder(
use closure: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator
) -> CallbackResponder<Context> {
return CallbackResponder { request, context in
let output = try await closure(request, context)
return try output.response(from: request, context: context)
}
}

internal func combinePaths(_ path1: String, _ path2: String) -> String {
let path1 = path1.dropSuffix("/")
let path2 = path2.dropPrefix("/")
return "\(path1)/\(path2)"
}
}
75 changes: 75 additions & 0 deletions Tests/HummingbirdTests/RouterTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,75 @@ final class RouterTests: XCTestCase {
}
}

// Test route collection added to Router
func testRouteCollection() async throws {
let router = Router()
let routes = RouteCollection()
routes.get("that") { _, _ in
return HTTPResponse.Status.ok
}
router.add("this", routes: routes)
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/this/that", method: .get) { response in
XCTAssertEqual(response.status, .ok)
}
}
}

// Test route collection added to Router
func testRouteCollectionInGroup() async throws {
let router = Router()
let routes = RouteCollection()
.get("that") { _, _ in
return HTTPResponse.Status.ok
}
router.group("this").add(routes: routes)
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/this/that", method: .get) { response in
XCTAssertEqual(response.status, .ok)
}
}
}

// Test middleware in route collection
func testMiddlewareInRouteCollection() async throws {
let router = Router()
let routes = RouteCollection()
.add(middleware: TestMiddleware("Hello"))
.get("that") { _, _ in
return HTTPResponse.Status.ok
}
router.add("this", routes: routes)
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/this/that", method: .get) { response in
XCTAssertEqual(response.status, .ok)
XCTAssertEqual(response.headers[.test], "Hello")
}
}
}

// Test group in route collection
func testGroupInRouteCollection() async throws {
let router = Router()
let routes = RouteCollection()
routes.group("2")
.add(middleware: TestMiddleware("Hello"))
.get("3") { _, _ in
return HTTPResponse.Status.ok
}
router.add("1", routes: routes)
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/1/2/3", method: .get) { response in
XCTAssertEqual(response.status, .ok)
XCTAssertEqual(response.headers[.test], "Hello")
}
}
}

// Test case insensitive router works
func testCaseInsensitive() async throws {
let router = Router(options: .caseInsensitive)
Expand All @@ -440,6 +509,9 @@ final class RouterTests: XCTestCase {
router.get("lowercased") { _, _ in
return HTTPResponse.Status.ok
}
router.group("group").get("Uppercased") { _, _ in
return HTTPResponse.Status.ok
}
let app = Application(responder: router.buildResponder())
try await app.test(.router) { client in
try await client.execute(uri: "/uppercased", method: .get) { response in
Expand All @@ -448,6 +520,9 @@ final class RouterTests: XCTestCase {
try await client.execute(uri: "/LOWERCASED", method: .get) { response in
XCTAssertEqual(response.status, .ok)
}
try await client.execute(uri: "/Group/uppercased", method: .get) { response in
XCTAssertEqual(response.status, .ok)
}
}
}

Expand Down

0 comments on commit 66b050c

Please sign in to comment.