Implemented the RedirectURIUseCase use case in the library target.

This commit is contained in:
2025-09-24 17:29:18 +02:00
parent 1b9973230d
commit c2c603a810
4 changed files with 262 additions and 7 deletions
@@ -126,10 +126,3 @@ private extension LoggerMetadata_HelpersTests {
}
}
// MARK: - Constants
private extension String {
/// A URI path to use as a redirection sample.
static let uriRedirection = "/some/redirect/path"
}
@@ -0,0 +1,164 @@
// ===----------------------------------------------------------------------===
//
// This source file is part of the Hummingbird DocC Middleware open source project
//
// Copyright (c) 2025 Röck+Cöde VoF. and the Hummingbird DocC Middleware project authors
// Licensed under the EUPL 1.2 or later.
//
// See LICENSE for license information
// See CONTRIBUTORS for the list of Hummingbird DocC Middleware project authors
//
// ===----------------------------------------------------------------------===
import Hummingbird
import Testing
import struct Logging.Logger
@testable import struct DocCMiddleware.RedirectURIUseCase
@Suite("Redirect URI Use Case", .tags(.useCase))
struct RedirectURIUseCaseTests {
// MARK: Use case tests
#if swift(>=6.2)
@Test
func `response when logger expects an event`() async throws {
try await assertResponse(
logLevel: try randomLogLevelWithEvent,
uriRedirection: .uriRedirection,
expects: .movedPermanently
)
}
@Test
func `response when logger does not expects an event`() async throws {
try await assertResponse(
logLevel: try randomLogLevelWithNoEvent,
uriRedirection: .uriRedirection,
expects: .movedPermanently
)
}
#else
@Test("response when logger expects an event")
func responseWhenLoggerExpectsEvent() async throws {
try await assertResponse(
logLevel: try randomLogLevelWithEvent,
uriRedirection: .uriRedirection,
expects: .movedPermanently
)
}
@Test("response when logger does not expects an event")
func responseWhenLogLevel() async throws {
try await assertResponse(
logLevel: try randomLogLevelWithNoEvent,
uriRedirection: .uriRedirection,
expects: .movedPermanently
)
}
#endif
}
// MARK: - Assertions
private extension RedirectURIUseCaseTests {
// MARK: Functions
/// Asserts the response returned by the ``RedirectURIUseCase`` use case based on the given `logLevel` logging level and the `uriRedirection`
/// URI path plus the expected status code of the response.
/// - Parameters:
/// - logLevel: A representation of the logging level to set in the `Logger` instance.
/// - uriRedirection: A URI path to use in the redirection.
/// - statusCode: An expected status code from the response coming out of the use case.
/// - Throws: An error in case an issue is encountered while asserting the use case.
func assertResponse(
logLevel: Logger.Level,
uriRedirection: String,
expects statusCode: HTTPResponse.Status
) async throws {
let logHandler = LogHandlerMock()
let logger = Logger.test(
level: logLevel,
handler: logHandler
)
let context: any RequestContext = RequestContextMock(logger: logger)
let request: Request = .test(method: .get)
let useCase = RedirectURIUseCase(logger: logger)
// WHEN
let result = useCase(
uriRedirection,
with: (request, context)
)
// THEN
#expect(result.status == .movedPermanently)
#expect(result.body.contentLength == 0)
#expect(result.headers == [
.location: uriRedirection,
.contentLength: "0"
])
let events = await logHandler.entries
if shouldEventBeLogged(logLevel) {
#expect(!events.isEmpty)
#expect(events.count == 1)
let loggedEvent = try #require(events.first)
#expect(loggedEvent == .init(
level: .debug,
metadata: [
"hb.request.id": "\(context.id)",
"hb.request.method": "\(request.method.rawValue)",
"hb.request.path": "\(request.uri.path)",
"hb.request.status": "\(statusCode.code)",
"hb.request.redirect": "\(uriRedirection)"
],
message: "The URI path is redirected to this path: \(uriRedirection)",
source: "DocCMiddleware"
))
} else {
#expect(events.isEmpty)
}
}
}
// MARK: - Helpers
private extension RedirectURIUseCaseTests {
// MARK: Computed
/// Extracts a random logging level that support event logging for the use case.
var randomLogLevelWithEvent: Logger.Level {
get throws {
try #require([.debug, .trace].randomElement())
}
}
/// Extracts a random logging level that does not support event logging for the use case.
var randomLogLevelWithNoEvent: Logger.Level {
get throws {
try #require([.critical, .error, .info, .notice, .warning].randomElement())
}
}
// MARK: Functions
/// Checks whether a logging event should be logged or not, based on a given logging level.
/// - Parameter level: A representation of a logging level defined in the `Logger` instance.
/// - Returns: A boolean value that indicates whether a logging event should have been logged or not.
func shouldEventBeLogged(_ logLevel: Logger.Level) -> Bool {
[Logger.Level.trace, .debug].contains(logLevel)
}
}
@@ -0,0 +1,20 @@
// ===----------------------------------------------------------------------===
//
// This source file is part of the Hummingbird DocC Middleware open source project
//
// Copyright (c) 2025 Röck+Cöde VoF. and the Hummingbird DocC Middleware project authors
// Licensed under the EUPL 1.2 or later.
//
// See LICENSE for license information
// See CONTRIBUTORS for the list of Hummingbird DocC Middleware project authors
//
// ===----------------------------------------------------------------------===
extension String {
// MARK: Constants
/// A URI path to use as a redirection sample.
static let uriRedirection = "/some/redirect/path"
}