[Bugfix] Communications #7

Merged
javier merged 4 commits from bugfix/communications into main 2023-04-18 22:55:25 +00:00
5 changed files with 63 additions and 23 deletions

View File

@ -0,0 +1,17 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftLibs open source project
//
// Copyright (c) 2023 Röck+Cöde VoF. and the SwiftLibs project authors
// Licensed under the EUPL 1.2 or later.
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftLibs project authors
//
//===----------------------------------------------------------------------===//
/// Errors generated out of the `MakeURLRequestUseCase` use case.
public enum MakeURLRequestError: Error {
/// An expected URL was not created.
case urlNotCreated
}

View File

@ -27,9 +27,4 @@ public protocol Client {
as model: Model.Type
) async throws -> Model
/// Makes a request to a remote location based on a given endpoint and expects to return an original, uncasted response.
/// - Parameter endpoint: The endpoint for which to make a remote call.
/// - Returns: An original data response from a call to a remote endpoint.
@discardableResult func request(endpoint: some Endpoint) async throws -> Data
}

View File

@ -15,6 +15,11 @@ import Foundation
/// This protocol defines an endpoint to be used in a remote call.
public protocol Endpoint {
// MARK: Type aliases
typealias Parameters = [String : String?]
typealias Headers = [String : String]
// MARK: Properties
/// The scheme subcomponent for the endpoint.
@ -29,11 +34,14 @@ public protocol Endpoint {
/// The path subcomponent for the endpoint.
var path: String { get }
/// The query parameter subcomponents for the endpoint.
var parameters: Parameters { get }
/// The HTTP request method for the endpoint.
var method: HTTPRequestMethod { get }
/// The HTTP header fields as a dictionary for the endpoint.
var headers: [String: String] { get }
var headers: Headers { get }
/// The message body as data for a request.
var body: Data? { get }

View File

@ -35,6 +35,12 @@ public struct MakeURLRequestUseCase {
urlComponents.port = port
}
if !endpoint.parameters.isEmpty {
urlComponents.queryItems = endpoint.parameters
.map(URLQueryItem.init)
.sorted(by: { $0.name < $1.name })
}
guard let url = urlComponents.url else {
throw MakeURLRequestError.urlNotCreated
}
@ -49,10 +55,3 @@ public struct MakeURLRequestUseCase {
}
}
// MARK: - Errors
enum MakeURLRequestError: Error {
case urlNotCreated
}

View File

@ -52,6 +52,25 @@ final class MakeURLRequestUseCaseTests: XCTestCase {
XCTAssertNil(result.httpBody)
}
func test_withEndpoint_initialisedWithParameters() throws {
// GIVEN
let endpoint = TestEndpoint(parameters: [
"someParameter": "someValue",
"anotherParameter": nil,
"otherParameter": "yetAnotherValue"
])
// WHEN
let result = try makeURLRequest(endpoint: endpoint)
// THEN
XCTAssertNotNil(result)
XCTAssertEqual(result.url?.absoluteString, "http://www.something.com/path/to/endpoint?anotherParameter&otherParameter=yetAnotherValue&someParameter=someValue")
XCTAssertEqual(result.httpMethod, HTTPRequestMethod.get.rawValue)
XCTAssertEqual(result.allHTTPHeaderFields, [:])
XCTAssertNil(result.httpBody)
}
func test_withEndpoint_initialisedWithHeaders() throws {
// GIVEN
let endpoint = TestEndpoint(headers: [
@ -100,23 +119,25 @@ private struct TestEndpoint: Endpoint {
let scheme: String = "http"
let host: String = "www.something.com"
let port: Int?
let path: String = "/path/to/endpoint"
let parameters: Parameters
let method: HTTPRequestMethod = .get
var port: Int?
var headers: [String : String]
var body: Data?
let headers: Headers
let body: Data?
// MARK: Initialisers
init(
port: Int? = nil,
headers: [String : String] = [:],
parameters: Parameters = [:],
headers: Headers = [:],
body: Data? = nil
) {
self.port = port
self.body = body
self.parameters = parameters
self.headers = headers
self.body = body
}
}