Skip to content

Commit 60e74b0

Browse files
authored
Put, Patch, Delete helpers (#16)
1 parent 5ab7a47 commit 60e74b0

File tree

6 files changed

+130
-16
lines changed

6 files changed

+130
-16
lines changed

.codebeatignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Sources/HTTPEngine/HTTPEngine+ConvenienceMethods.swift

Sources/HTTPEngine/Errors.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// swiftlint:disable nesting
12
import Foundation
23

34
public struct Errors {

Sources/HTTPEngine/HTTPEngine+ConvenienceMethods.swift

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// swiftlint:disable line_length
12
import Foundation
23
import Combine
34

@@ -81,8 +82,8 @@ public extension HTTPEngine {
8182
.decode(type: decodableResponse.self, decoder: JSONDecoder())
8283
.eraseToAnyPublisher()
8384
}
84-
85-
85+
86+
8687
/// Makes a request via HTTP and Decodes the response
8788
/// - Parameters:
8889
/// - decodableResponse: Decodable - An object that represents the response body
@@ -108,7 +109,7 @@ public extension HTTPEngine {
108109
}
109110

110111

111-
/// Makes a request via HTTP, Encodes the body and Decodes the response
112+
/// Makes a POST request via HTTP, Encodes the body and Decodes the response
112113
/// - Parameters:
113114
/// - decodableResponse: Decodable - An object that represents the response body
114115
/// - urlString: URL domain + path as a string: `"abc.com/some/path"`
@@ -134,8 +135,8 @@ public extension HTTPEngine {
134135
makeRequestAndParseResponse(value.self, method: .post, url: url, body: body, validator: validator)
135136
}
136137

137-
138-
/// Makes a request via HTTP, Encodes the body and Decodes the response
138+
139+
/// Makes a POST request via HTTP, Encodes the body and Decodes the response
139140
/// - Parameters:
140141
/// - decodableResponse: Decodable - An object that represents the response body
141142
/// - urlString: URL domain + path as a string: `"abc.com/some/path"`
@@ -158,6 +159,86 @@ public extension HTTPEngine {
158159
) -> AnyPublisher<Response, Error> {
159160
post(value.self, url: url, body: nil as NilBody?, validator: validator)
160161
}
162+
163+
164+
/// Makes a PATCH request via HTTP, Encodes the body and Decodes the response
165+
/// - Parameters:
166+
/// - decodableResponse: Decodable - An object that represents the response body
167+
/// - urlString: URL domain + path as a string: `"abc.com/some/path"`
168+
/// - body: Encodable?: The encodable object that represents body data to send with a request
169+
/// - validator: `(Int) -> Bool` - A function to validate the response code of the request. By default, makeRequest() will fail if the status code does not fall within the 200 - 299 range. To override this, pass in a function that compares the status code and returns a boolean. True == success, False == failure. Upon failure an error will be thrown that contains the HTTPURLResponse for inspection.
170+
///
171+
/// - Returns: AnyPubliser<Data, Error>
172+
///
173+
/// -- Validation
174+
///
175+
/// By default the validation checks for a 200-299 status code and fails if the code is out of bounds
176+
/// ```swift
177+
/// // example validator
178+
/// validator: { $0 == 202 }
179+
/// // Failure throws Errors.Response.unexpectedStatusCode(HTTPURLRequest)
180+
/// ```
181+
func patch<Response: Decodable, Body: Encodable>(
182+
_ value: Response.Type,
183+
url: String,
184+
body: Body? = nil,
185+
validator: ResponseValidationClosure? = nil
186+
) -> AnyPublisher<Response, Error> {
187+
makeRequestAndParseResponse(value.self, method: .patch, url: url, body: body, validator: validator)
188+
}
189+
190+
191+
/// Makes a PUT request via HTTP, Encodes the body and Decodes the response
192+
/// - Parameters:
193+
/// - decodableResponse: Decodable - An object that represents the response body
194+
/// - urlString: URL domain + path as a string: `"abc.com/some/path"`
195+
/// - body: Encodable?: The encodable object that represents body data to send with a request
196+
/// - validator: `(Int) -> Bool` - A function to validate the response code of the request. By default, makeRequest() will fail if the status code does not fall within the 200 - 299 range. To override this, pass in a function that compares the status code and returns a boolean. True == success, False == failure. Upon failure an error will be thrown that contains the HTTPURLResponse for inspection.
197+
///
198+
/// - Returns: AnyPubliser<Data, Error>
199+
///
200+
/// -- Validation
201+
///
202+
/// By default the validation checks for a 200-299 status code and fails if the code is out of bounds
203+
/// ```swift
204+
/// // example validator
205+
/// validator: { $0 == 202 }
206+
/// // Failure throws Errors.Response.unexpectedStatusCode(HTTPURLRequest)
207+
/// ```
208+
func put<Response: Decodable, Body: Encodable>(
209+
_ value: Response.Type,
210+
url: String,
211+
body: Body? = nil,
212+
validator: ResponseValidationClosure? = nil
213+
) -> AnyPublisher<Response, Error> {
214+
makeRequestAndParseResponse(value.self, method: .put, url: url, body: body, validator: validator)
215+
}
216+
217+
/// Makes a DELETE request via HTTP, Encodes the body and Decodes the response
218+
/// - Parameters:
219+
/// - decodableResponse: Decodable - An object that represents the response body
220+
/// - urlString: URL domain + path as a string: `"abc.com/some/path"`
221+
/// - body: Encodable?: The encodable object that represents body data to send with a request
222+
/// - validator: `(Int) -> Bool` - A function to validate the response code of the request. By default, makeRequest() will fail if the status code does not fall within the 200 - 299 range. To override this, pass in a function that compares the status code and returns a boolean. True == success, False == failure. Upon failure an error will be thrown that contains the HTTPURLResponse for inspection.
223+
///
224+
/// - Returns: AnyPubliser<Data, Error>
225+
///
226+
/// -- Validation
227+
///
228+
/// By default the validation checks for a 200-299 status code and fails if the code is out of bounds
229+
/// ```swift
230+
/// // example validator
231+
/// validator: { $0 == 202 }
232+
/// // Failure throws Errors.Response.unexpectedStatusCode(HTTPURLRequest)
233+
/// ```
234+
func delete<Response: Decodable, Body: Encodable>(
235+
_ value: Response.Type,
236+
url: String,
237+
body: Body? = nil,
238+
validator: ResponseValidationClosure? = nil
239+
) -> AnyPublisher<Response, Error> {
240+
makeRequestAndParseResponse(value.self, method: .delete, url: url, body: body, validator: validator)
241+
}
161242
}
162243

163244
private struct NilBody: Encodable {}

Sources/HTTPEngine/HTTPEngine.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// swiftlint:disable line_length
12
import Foundation
23
import Combine
34

Sources/HTTPEngine/Utilities.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// swiftlint:disable line_length
12
import Foundation
23
import Combine
34

Tests/HTTPEngineTests/HTTPEngine+ConvenieceMethodTests.swift

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,7 @@ import OHHTTPStubsSwift
55
@testable import HTTPEngine
66

77
final class HTTPEngineConvenienceMethodTests: XCTestCase {
8-
static var allTests = [
9-
("make request and parse response decodes into type", testMakeRequestAndParseResponseDecodesIntoType),
10-
("make request and parse response throws if Decode fails", testMakeRequestAndParseResponseThrowsIfDecodeFails),
11-
("make request and parse response Encodes and Decodes into type", testMakeRequestAndParseResponseEncodesAndDecodesIntoType),
12-
("get succeeds", testGetSucceeds),
13-
("post succeeds", testPostSucceeds),
14-
]
15-
8+
169
func testMakeRequestAndParseResponseDecodesIntoType() {
1710
stub(condition: isHost("google.com") && isMethodGET()) { _ in
1811
HTTPStubsResponse(jsonObject: ["key":"value"], statusCode: 200, headers: nil)
@@ -25,7 +18,7 @@ final class HTTPEngineConvenienceMethodTests: XCTestCase {
2518
}
2619

2720
}
28-
21+
2922
func testMakeRequestAndParseResponseThrowsIfDecodeFails() {
3023
stub(condition: isHost("google.com") && isMethodGET()) { _ in
3124
HTTPStubsResponse(jsonObject: [:], statusCode: 200, headers: nil)
@@ -46,7 +39,7 @@ final class HTTPEngineConvenienceMethodTests: XCTestCase {
4639
XCTAssertEqual($0.key, "value")
4740
}
4841
}
49-
42+
5043
func testGetSucceeds() {
5144
stub(condition: isHost("google.com") && isMethodGET()) { _ in
5245
HTTPStubsResponse(jsonObject: ["key": "value"], statusCode: 200, headers: nil)
@@ -59,7 +52,7 @@ final class HTTPEngineConvenienceMethodTests: XCTestCase {
5952

6053
}
6154
}
62-
55+
6356
func testPostSucceeds() {
6457
stub(condition: isHost("google.com") && isMethodPOST()) { _ in
6558
HTTPStubsResponse(jsonObject: ["key": "value"], statusCode: 200, headers: nil)
@@ -71,6 +64,42 @@ final class HTTPEngineConvenienceMethodTests: XCTestCase {
7164
XCTAssertEqual($0.key, "value")
7265
}
7366
}
67+
68+
func testPatchSucceeds() {
69+
stub(condition: isHost("google.com") && isMethodPATCH()) { _ in
70+
HTTPStubsResponse(jsonObject: ["key": "value"], statusCode: 200, headers: nil)
71+
}
72+
73+
HTTPEngine()
74+
.patch(TestResponseBody.self, url: "https://google.com", body: nil as TestResponseBody?)
75+
.assertResult(test: self) {
76+
XCTAssertEqual($0.key, "value")
77+
}
78+
}
79+
80+
func testPutSucceeds() {
81+
stub(condition: isHost("google.com") && isMethodPUT()) { _ in
82+
HTTPStubsResponse(jsonObject: ["key": "value"], statusCode: 200, headers: nil)
83+
}
84+
85+
HTTPEngine()
86+
.put(TestResponseBody.self, url: "https://google.com", body: nil as TestResponseBody?)
87+
.assertResult(test: self) {
88+
XCTAssertEqual($0.key, "value")
89+
}
90+
}
91+
92+
func testDeleteSucceeds() {
93+
stub(condition: isHost("google.com") && isMethodDELETE()) { _ in
94+
HTTPStubsResponse(jsonObject: ["key": "value"], statusCode: 200, headers: nil)
95+
}
96+
97+
HTTPEngine()
98+
.delete(TestResponseBody.self, url: "https://google.com", body: nil as TestResponseBody?)
99+
.assertResult(test: self) {
100+
XCTAssertEqual($0.key, "value")
101+
}
102+
}
74103
}
75104

76105
struct TestResponseBody: Codable {

0 commit comments

Comments
 (0)