import Foundation import HTTPTypes import Hummingbird import HummingbirdTesting import Localization import NIOCore import Testing @testable import Infrastructure @Suite( "Negotiate+Request extension", .tags(.extension) ) struct NegotiateRequestTests { // MARK: Constants /// Exercised through a route rather than a hand-built `Request`: the query parameter and path segment it reads are parsed from the URI. private let app: Application = .init(router: { let negotiate = Negotiate(bundle: .module) let router = Router(context: StubRequestContext.self) router.get("language") { request, _ in negotiate(for: request) } router.get("de/language") { request, _ in negotiate(for: request) } return router }()) // MARK: Functional tests @Test func `negotiates a supported language from the header`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/language", method: .get, headers: [.acceptLanguage: "de-DE,de;q=0.9"] ) { response in #expect(String(buffer: response.body) == "de") } } } @Test func `falls back to the default without a header`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/language", method: .get ) { response in #expect(String(buffer: response.body) == "en") } } } @Test func `falls back to the default for an unsupported language`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/language", method: .get, headers: [.acceptLanguage: "fr-FR,fr;q=0.9"] ) { response in #expect(String(buffer: response.body) == "en") } } } @Test func `honours a supported lang query parameter over the header`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/language?lang=de", method: .get, headers: [.acceptLanguage: "en"] ) { response in #expect(String(buffer: response.body) == "de") } } } /// A language's whole URL prefix answers in its language, so its not-found page does too. @Test func `pins the language a leading path segment names over the header`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/de/language", method: .get, headers: [.acceptLanguage: "en"] ) { response in #expect(String(buffer: response.body) == "de") } } } @Test func `negotiates the header when the lang query parameter is unsupported`() async throws { try await app.test(.router) { client in try await client.execute( uri: "/language?lang=fr", method: .get, headers: [.acceptLanguage: "de"] ) { response in #expect(String(buffer: response.body) == "de") } } } }