Skip to content
This repository was archived by the owner on Sep 30, 2024. It is now read-only.

Commit 8d5ed85

Browse files
committed
Merge branch 'release/0.7.0' into versions
2 parents fe9cc6b + b901cd7 commit 8d5ed85

4 files changed

Lines changed: 145 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
1717
### Security
1818
- None.
1919

20+
## [0.7.0] - 2021-10-14
21+
### Added
22+
- New methods for requesting raw `Data` response to allow for using alternative decoding methods such as [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON): `performRawDataRequest(AndWait)` (classic approach), `rawDataPublisher` (Combine) and `rawDataResponse` (Swift concurrency).
23+
2024
## [0.6.1] - 2021-10-14
2125
### Changed
2226
- Made the `baseUrl` parameter of `ApiProvider` editable.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
alt="codebeat badge">
1414
</a>
1515
<a href="https://github.com/Flinesoft/HandySwift/releases">
16-
<img src="https://img.shields.io/badge/Version-0.6.1-blue.svg"
17-
alt="Version: 0.6.1">
16+
<img src="https://img.shields.io/badge/Version-0.7.0-blue.svg"
17+
alt="Version: 0.7.0">
1818
<img src="https://img.shields.io/badge/Swift-5.4-FFAC45.svg"
1919
alt="Swift: 5.4">
2020
<img src="https://img.shields.io/badge/Platforms-Apple%20%7C%20Linux-FF69B4.svg"

Sources/Microya/Core/ApiProvider.swift

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ open class ApiProvider<EndpointType: Endpoint> {
3333
self.mockingBehavior = mockingBehavior
3434
}
3535

36+
/// Returns a publisher which performs a request to the server when new values are requested.
37+
/// Returns the raw response `Data` on success for custom handling, skipping the decoding logic.
38+
///
39+
/// - NOTE: Do not use this if you expect a `Decodable` response, use `publisher(on:decodeBodyTo:)` instead.
40+
public func rawDataPublisher(
41+
on endpoint: EndpointType
42+
) -> AnyPublisher<Data, ApiError<EndpointType.ClientErrorType>> {
43+
self.publisher(on: endpoint, decodeBodyTo: Data.self)
44+
}
45+
3646
/// Returns a publisher which performs a request to the server when new values are requested.
3747
/// Returns a `EmptyBodyResponse` on success.
3848
///
@@ -137,6 +147,13 @@ open class ApiProvider<EndpointType: Endpoint> {
137147
}
138148
}
139149

150+
/// - NOTE: Do not use this if you expect a `Decodable` response, use `response(on:decodeBodyTo:)` instead.
151+
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
152+
public func rawDataResponse(on endpoint: EndpointType) async -> TypedResult<Data> {
153+
await self.response(on: endpoint, decodeBodyTo: Data.self)
154+
}
155+
156+
/// - WARNING: Do not use this if you expect a body response, use `response(on:decodeBodyTo:)` instead.
140157
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
141158
public func response(on endpoint: EndpointType) async -> TypedResult<EmptyBodyResponse> {
142159
await self.response(on: endpoint, decodeBodyTo: EmptyBodyResponse.self)
@@ -199,6 +216,25 @@ open class ApiProvider<EndpointType: Endpoint> {
199216
}
200217
}
201218

219+
/// Performs the asynchronous request for the chosen write-only endpoint and calls the completion closure with the result.
220+
/// Returns the raw response `Data` on success for custom handling, skipping the decoding logic.
221+
///
222+
/// - NOTE: Do not use this if you expect a `Decodable` response, use `performRequest(on:decodeBodyTo:completion:)` instead.
223+
public func performRawDataRequest(
224+
on endpoint: EndpointType,
225+
completion: @escaping (TypedResult<Data>) -> Void
226+
) {
227+
self.performRequest(on: endpoint, decodeBodyTo: Data.self, completion: completion)
228+
}
229+
230+
/// Performs the request for the chosen write-only endpoint synchronously (waits for the result).
231+
/// Returns the raw response `Data` on success for custom handling, skipping the decoding logic.
232+
///
233+
/// - NOTE: Do not use this if you expect a `Decodable` response, use `performRequestAndWait(on:decodeBodyTo:)` instead.
234+
public func performRawDataRequestAndWait(on endpoint: EndpointType) -> TypedResult<Data> {
235+
self.performRequestAndWait(on: endpoint, decodeBodyTo: Data.self)
236+
}
237+
202238
/// Performs the asynchronous request for the chosen write-only endpoint and calls the completion closure with the result.
203239
/// Returns a `EmptyBodyResponse` on success.
204240
///
@@ -335,6 +371,10 @@ open class ApiProvider<EndpointType: Endpoint> {
335371
throw ApiError<EndpointType.ClientErrorType>.noDataInResponse(statusCode: httpResponse.statusCode)
336372
}
337373

374+
guard ResultType.self != Data.self else {
375+
return data as! ResultType
376+
}
377+
338378
do {
339379
return try endpoint.decoder.decode(ResultType.self, from: data)
340380
}

Tests/MicroyaTests/MicroyaIntegrationTests.swift

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,35 @@ class MicroyaIntegrationTests: XCTestCase {
8080
XCTAssertEqual(typedResponseBody.url, "https://postman-echo.com/post")
8181
}
8282

83+
func testRawDataPost() throws {
84+
let dataResponseBody =
85+
try sampleApiProvider.performRawDataRequestAndWait(
86+
on: .post(fooBar: FooBar(foo: "Lorem", bar: "Ipsum"))
87+
)
88+
.get()
89+
90+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Content-Type"], "application/json")
91+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept"], "application/json")
92+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept-Language"], "en")
93+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Authorization"], "Basic abc123")
94+
95+
XCTAssertEqual(TestDataStore.request?.httpMethod, "POST")
96+
XCTAssertEqual(TestDataStore.request?.url?.path, "/post")
97+
XCTAssertNil(TestDataStore.request?.url?.query)
98+
99+
XCTAssertNotNil(TestDataStore.urlSessionResult?.data)
100+
XCTAssertNil(TestDataStore.urlSessionResult?.error)
101+
XCTAssertNotNil(TestDataStore.urlSessionResult?.response)
102+
103+
let typedResponseBody = try JSONDecoder().decode(PostmanEchoResponse.self, from: dataResponseBody)
104+
105+
XCTAssertEqual(typedResponseBody.args, [:])
106+
XCTAssertEqual(typedResponseBody.headers["content-type"], "application/json")
107+
XCTAssertEqual(typedResponseBody.headers["accept"], "application/json")
108+
XCTAssertEqual(typedResponseBody.headers["accept-language"], "en")
109+
XCTAssertEqual(typedResponseBody.url, "https://postman-echo.com/post")
110+
}
111+
83112
func testGet() throws {
84113
let expectation = XCTestExpectation()
85114

@@ -237,6 +266,46 @@ class MicroyaIntegrationTests: XCTestCase {
237266
#endif
238267
}
239268

269+
func testPostRawDataCombine() throws {
270+
#if canImport(Combine)
271+
let expectation = XCTestExpectation()
272+
273+
sampleApiProvider.rawDataPublisher(
274+
on: .post(fooBar: FooBar(foo: "Lorem", bar: "Ipsum"))
275+
)
276+
.sink(
277+
receiveCompletion: { _ in },
278+
receiveValue: { dataResponseBody in
279+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Content-Type"], "application/json")
280+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept"], "application/json")
281+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept-Language"], "en")
282+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Authorization"], "Basic abc123")
283+
284+
XCTAssertEqual(TestDataStore.request?.httpMethod, "POST")
285+
XCTAssertEqual(TestDataStore.request?.url?.path, "/post")
286+
XCTAssertNil(TestDataStore.request?.url?.query)
287+
288+
XCTAssertNotNil(TestDataStore.urlSessionResult?.data)
289+
XCTAssertNil(TestDataStore.urlSessionResult?.error)
290+
XCTAssertNotNil(TestDataStore.urlSessionResult?.response)
291+
292+
let typedResponseBody = try! JSONDecoder().decode(PostmanEchoResponse.self, from: dataResponseBody)
293+
294+
XCTAssertEqual(typedResponseBody.args, [:])
295+
XCTAssertEqual(typedResponseBody.headers["content-type"], "application/json")
296+
XCTAssertEqual(typedResponseBody.headers["accept"], "application/json")
297+
XCTAssertEqual(typedResponseBody.headers["accept-language"], "en")
298+
XCTAssertEqual(typedResponseBody.url, "https://postman-echo.com/post")
299+
300+
expectation.fulfill()
301+
}
302+
)
303+
.store(in: &cancellables)
304+
305+
wait(for: [expectation], timeout: 10)
306+
#endif
307+
}
308+
240309
func testGetCombine() throws {
241310
#if canImport(Combine)
242311
let expectation = XCTestExpectation()
@@ -525,6 +594,36 @@ class MicroyaIntegrationTests: XCTestCase {
525594
XCTAssertEqual(typedResponseBody.url, "https://postman-echo.com/post")
526595
}
527596

597+
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
598+
func testPostRawDataAsync() async throws {
599+
let dataResponseBody =
600+
try await sampleApiProvider.rawDataResponse(
601+
on: .post(fooBar: FooBar(foo: "Lorem", bar: "Ipsum"))
602+
)
603+
.get()
604+
605+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Content-Type"], "application/json")
606+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept"], "application/json")
607+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Accept-Language"], "en")
608+
XCTAssertEqual(TestDataStore.request?.allHTTPHeaderFields?["Authorization"], "Basic abc123")
609+
610+
XCTAssertEqual(TestDataStore.request?.httpMethod, "POST")
611+
XCTAssertEqual(TestDataStore.request?.url?.path, "/post")
612+
XCTAssertNil(TestDataStore.request?.url?.query)
613+
614+
XCTAssertNotNil(TestDataStore.urlSessionResult?.data)
615+
XCTAssertNil(TestDataStore.urlSessionResult?.error)
616+
XCTAssertNotNil(TestDataStore.urlSessionResult?.response)
617+
618+
let typedResponseBody = try JSONDecoder().decode(PostmanEchoResponse.self, from: dataResponseBody)
619+
620+
XCTAssertEqual(typedResponseBody.args, [:])
621+
XCTAssertEqual(typedResponseBody.headers["content-type"], "application/json")
622+
XCTAssertEqual(typedResponseBody.headers["accept"], "application/json")
623+
XCTAssertEqual(typedResponseBody.headers["accept-language"], "en")
624+
XCTAssertEqual(typedResponseBody.url, "https://postman-echo.com/post")
625+
}
626+
528627
@available(iOS 15, tvOS 15, macOS 12, watchOS 8, *)
529628
func testGetAsync() async {
530629
let response = await sampleApiProvider.response(

0 commit comments

Comments
 (0)