Skip to content

Commit b4eace8

Browse files
committed
mock http clients for testing
1 parent e7f0522 commit b4eace8

File tree

1 file changed

+59
-0
lines changed

1 file changed

+59
-0
lines changed

Sources/SwiftAPIClient/Clients/HTTPClient.swift

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,65 @@ public struct HTTPClient {
1717
}
1818
}
1919

20+
extension HTTPClient {
21+
22+
/// Mocks the client to always return the provided data and response.
23+
/// - Parameters:
24+
/// - data: The data to be returned by the mock client.
25+
/// - response: The HTTP response to be returned by the mock client. Defaults to a 200 OK response.
26+
/// - Returns: An instance of `HTTPClient` that always returns the specified data and response.
27+
public static func mock(data: Data, response: HTTPResponse = .init(status: .ok)) -> HTTPClient {
28+
HTTPClient { request, _ in
29+
(data, response)
30+
}
31+
}
32+
33+
/// Mocks the client to encode and return the provided encodable object along with the specified response.
34+
/// - Parameters:
35+
/// - encodable: The encodable object to be encoded and returned as data. Uses the client's body encoder.
36+
/// - response: The HTTP response to be returned by the mock client. Defaults to a 200 OK response.
37+
/// - Returns: An instance of `HTTPClient` that encodes and returns the specified object and response.
38+
/// - Tip: In order to use a specific encoder, configure the client using `.configs(\.bodyEncoder, encoder)` before applying this mock.
39+
public static func mock(_ encodable: any Encodable, response: HTTPResponse = .init(status: .ok)) -> HTTPClient {
40+
HTTPClient { request, configs in
41+
let data = try configs.bodyEncoder.encode(encodable)
42+
return (data, response)
43+
}
44+
}
45+
46+
/// Mocks the client to encode and return the provided encodable object along with the specified response status.
47+
/// - Parameters:
48+
/// - encodable: The encodable object to be encoded and returned as data. Uses the client's body encoder.
49+
/// - status: The HTTP status to be used in the response.
50+
/// - Returns: An instance of `HTTPClient` that encodes and returns the specified object and response.
51+
/// - Tip: In order to use a specific encoder, configure the client using `.configs(\.bodyEncoder, encoder)` before applying this mock.
52+
public static func mock(_ encodable: any Encodable, status: HTTPResponse.Status) -> HTTPClient {
53+
.mock(encodable, response: .init(status: status))
54+
}
55+
56+
/// Configures the client with specific configuration values.
57+
/// - Parameters:
58+
/// - keyPath: The key path to the configuration property to be modified.
59+
/// - value: The new value for the specified configuration property.
60+
/// - Returns: An instance of `APIClient` with updated configurations.
61+
public func configs<T>(_ keyPath: WritableKeyPath<APIClient.Configs, T>, _ value: T) -> HTTPClient {
62+
configs {
63+
$0[keyPath: keyPath] = value
64+
}
65+
}
66+
67+
/// Configures the client with a closure that modifies its configurations.
68+
/// - Parameter configs: A closure that takes `inout Configs` and modifies them.
69+
/// - Returns: An instance of `APIClient` with updated configurations.
70+
public func configs(_ configs: @escaping (inout APIClient.Configs) -> Void) -> HTTPClient {
71+
HTTPClient { request, currentConfigs in
72+
var newConfigs = currentConfigs
73+
configs(&newConfigs)
74+
return try await self.data(request, newConfigs)
75+
}
76+
}
77+
}
78+
2079
public enum RequestBody: Hashable, Sendable {
2180

2281
case file(URL)

0 commit comments

Comments
 (0)