Skip to content

Commit

Permalink
Merge branch 'release/4.0' of https://github.com/dbsystel/DBNetworkStack
Browse files Browse the repository at this point in the history
 into release/4.0
  • Loading branch information
lightsprint09 committed Nov 25, 2024
2 parents f3f4a43 + b7b5f80 commit 7a0784c
Show file tree
Hide file tree
Showing 14 changed files with 70 additions and 39 deletions.
18 changes: 9 additions & 9 deletions Source/NetworkError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public enum NetworkError: Error, Sendable {
/// Error on the server (HTTP Error 500...511)
case serverError(response: HTTPURLResponse?, data: Data?)
/// Parsing the body into expected type failed.
case serializationError(error: Error, data: Data?)
case serializationError(error: Error, response: HTTPURLResponse, data: Data?)
/// Complete request failed.
case requestError(error: Error)

Expand Down Expand Up @@ -75,21 +75,21 @@ extension NetworkError: CustomDebugStringConvertible {
case .cancelled:
return "Request cancelled"
case .unauthorized(let response, let data):
return "Authorization error: \(response), response: ".appendingContentsOf(data: data)
return "Authorization error, response headers: \(response), response body: ".appendingContentsOf(data: data)
case .clientError(let response, let data):
if let response = response {
return "Client error: \((response)), response: ".appendingContentsOf(data: data)
return "Client error, response headers: \((response)), response body: ".appendingContentsOf(data: data)
}
return "Client error, response: ".appendingContentsOf(data: data)
case .serializationError(let description, let data):
return "Serialization error: \(description), response: ".appendingContentsOf(data: data)
return "Client error, response headers: nil, response body: ".appendingContentsOf(data: data)
case .serializationError(let error, let response, let data):
return "Serialization error: \(error), response headers: \(response), response body: ".appendingContentsOf(data: data)
case .requestError(let error):
return "Request error: \(error)"
case .serverError(let response, let data):
if let response = response {
return "Server error: \(String(describing: response)), response: ".appendingContentsOf(data: data)
if let response {
return "Server error, response headers: \(String(describing: response)), response body: ".appendingContentsOf(data: data)
} else {
return "Server error: nil, response: ".appendingContentsOf(data: data)
return "Server error: nil, response body: ".appendingContentsOf(data: data)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Source/NetworkServices/BasicNetworkService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public final class BasicNetworkService: NetworkService {
do {
return .success((try resource.parse(data), response))
} catch let error {
return .failure(.serializationError(error: error, data: data))
return .failure(.serializationError(error: error, response: response, data: data))
}
} catch let error {
if case URLError.cancelled = error {
Expand Down
14 changes: 12 additions & 2 deletions Source/Resource+Decodable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ extension Resource where Model: Decodable {
/// - decoder: a decoder which can decode the payload into the model type
/// - mapError: a closure which maps to Error
public init(request: URLRequest, decoder: JSONDecoder, mapError: @escaping @Sendable (_ networkError: NetworkError) -> E) {
self.init(request: request, parse: { try decoder.decode(Model.self, from: $0) }, mapError: mapError)
self.init(request: request, parse: {
try decoder.decode(Model.self, from: $0)
},
mapError: mapError
)
}
}

Expand All @@ -47,6 +51,12 @@ extension Resource where Model: Decodable, E: NetworkErrorConvertible {
/// - decoder: a decoder which can decode the payload into the model type
/// - mapError: a closure which maps to Error
public init(request: URLRequest, decoder: JSONDecoder) {
self.init(request: request, parse: { try decoder.decode(Model.self, from: $0) }, mapError: { E(networkError: $0) })
self.init(request: request, parse: {
try decoder.decode(Model.self, from: $0)
},
mapError: {
E(networkError: $0)
}
)
}
}
2 changes: 1 addition & 1 deletion Source/Resource+Inspect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extension Resource {
- parameter inspector: closure which gets passed the data
- returns: a new resource which gets instepcted before parsing
*/
public func inspectData(_ inspector: @escaping @Sendable (Data) -> Void) -> Resource<Model, E> {
public func inspectData(_ inspector: @escaping @Sendable (Data) -> Void) -> Resource<Model, E> {
let parse: @Sendable (Data) throws -> Model = { data in
inspector(data)
return try self.parse(data)
Expand Down
4 changes: 3 additions & 1 deletion Source/Resource+Map.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ extension Resource {
public func map<T>(transform: @escaping @Sendable (Model) throws -> T) -> Resource<T, E> {
return Resource<T, E>(
request: request,
parse: { return try transform(try self.parse($0)) },
parse: { data in
return try transform(try self.parse(data))
},
mapError: mapError
)
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/DecodableResoureTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class DecodableResoureTest: XCTestCase {
func testResource_withValidData() {
//When
let fetchedTrain = try? resource.parse(Train.validJSONData)

//Then
XCTAssertEqual(fetchedTrain?.name, "ICE")
}
Expand All @@ -43,7 +43,7 @@ class DecodableResoureTest: XCTestCase {
//When
let nameResource = resource.map { $0.name }
let fetchedTrainName = try? nameResource.parse(Train.validJSONData)

//Then
XCTAssertEqual(fetchedTrainName, "ICE")
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/ModifyRequestNetworkService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ class ModifyRequestNetworkServiceTest: XCTestCase {
let networkService = ModifyRequestNetworkService(networkService: networkServiceMock, requestModifications: modification)
let request = URLRequest(path: "/trains", baseURL: .defaultMock)
let resource = Resource<Int, NetworkError>(request: request, parse: { _ in return 1 })

//When
await networkService.requestResult(for: resource)

//Then
let lastRequest = await networkServiceMock.lastRequest
let lastRequest = networkServiceMock.lastRequest
let lastRequestURL = try XCTUnwrap(lastRequest?.url)
XCTAssert(lastRequestURL.absoluteString.contains("key=1"))
}
Expand Down
15 changes: 8 additions & 7 deletions Tests/NetworkErrorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ class NetworkErrorTest: XCTestCase {
let debugDescription = error.debugDescription

//Then
XCTAssert(debugDescription.hasPrefix("Authorization error: <NSHTTPURLResponse: "))
XCTAssert(debugDescription.hasSuffix("response: dataString"))
XCTAssert(debugDescription.hasPrefix("Authorization error, response headers: <NSHTTPURLResponse: "), debugDescription)
XCTAssert(debugDescription.hasSuffix("response body: dataString"), debugDescription)
}

func testUnknownError_clientError_description() {
Expand All @@ -149,21 +149,22 @@ class NetworkErrorTest: XCTestCase {
let debugDescription = error.debugDescription

//Then
XCTAssert(debugDescription.hasPrefix("Client error: <NSHTTPURLResponse: "))
XCTAssert(debugDescription.hasSuffix("response: dataString"))
XCTAssert(debugDescription.hasPrefix("Client error, response headers: <NSHTTPURLResponse: "), debugDescription)
XCTAssert(debugDescription.hasSuffix("response body: dataString"), debugDescription)
}

func testUnknownError_serializationError_description() {
//Given
let nserror = NSError(domain: "TestError", code: 0, userInfo: nil)
let data = "dataString".data(using: .utf8)
let error: NetworkError = .serializationError(error: nserror, data: data)
let error: NetworkError = .serializationError(error: nserror, response: HTTPURLResponse.defaultMock, data: data)

//When
let debugDescription = error.debugDescription

//Then
XCTAssertEqual(debugDescription, "Serialization error: Error Domain=TestError Code=0 \"(null)\", response: dataString")
XCTAssert(debugDescription.hasPrefix("Serialization error: Error Domain=TestError Code=0 \"(null)\", response headers: <NSHTTPURLResponse:"), debugDescription)
XCTAssert(debugDescription.hasSuffix("response body: dataString"), debugDescription)
}

func testUnknownError_requestError_description() {
Expand Down
4 changes: 2 additions & 2 deletions Tests/NetworkServiceMockTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class NetworkServiceMockTest: XCTestCase {
try await networkServiceMock.request(resource)

//Then
let requestCount = await networkServiceMock.requestCount
let requestCount = networkServiceMock.requestCount
XCTAssertEqual(requestCount, 2)
}

Expand All @@ -57,7 +57,7 @@ class NetworkServiceMockTest: XCTestCase {
try await networkServiceMock.request(resource)

//Then
let lastRequests = await networkServiceMock.lastRequests
let lastRequests = networkServiceMock.lastRequests
XCTAssertEqual(lastRequests, [resource.request, resource.request])
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/NetworkServiceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class NetworkServiceTest: XCTestCase {
let result = await networkService.requestResult(for: resource)

//Then
if case .failure(.serializationError(_, let data)) = result {
if case .failure(.serializationError(_, _, let data)) = result {
XCTAssertEqual(data, Train.JSONDataWithInvalidKey)
} else {
XCTFail("Expects serializationError")
Expand Down
35 changes: 27 additions & 8 deletions Tests/ResourceInspectTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,42 @@ final class ResourceInspectTest: XCTestCase {
func testInspect() {
//Given
let data = Data()
var capuredParsingData: Data?
var capturedInspectedData: Data?
let capturedParsingData = Container<Data?>(nil)
let capturedInspectedData = Container<Data?>(nil)

let resource = Resource<Int, NetworkError>(request: URLRequest.defaultMock, parse: { data in
capuredParsingData = data
capturedParsingData.setValue(data)
return 1
})

//When
let inspectedResource = resource.inspectData({ data in
capturedInspectedData = data
capturedInspectedData.setValue(data)
})
let result = try? inspectedResource.parse(data)

//Then
XCTAssertNotNil(result)
XCTAssertEqual(capuredParsingData, capturedInspectedData)
XCTAssertEqual(data, capturedInspectedData)
XCTAssertEqual(capuredParsingData, data)
XCTAssertEqual(capturedParsingData.getValue(), capturedInspectedData.getValue())
XCTAssertEqual(data, capturedInspectedData.getValue())
XCTAssertEqual(capturedParsingData.getValue(), data)
}
}

private class Container<T> {
private var value: T

init(_ value: T) {
self.value = value
}

/// caller should manage concurrent access to its own state
func setValue(_ newValue: T) {
value = newValue
}

/// caller should manage concurrent access to its own state
func getValue() -> T {
value
}
}
2 changes: 1 addition & 1 deletion Tests/ResourceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ResourceTest: XCTestCase {

//When
let name = try resource.parse(validData)

//Then
XCTAssertEqual(name, "ICE")
}
Expand Down
2 changes: 1 addition & 1 deletion Tests/ResourceWithErrorTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ResourceWithErrorTest: XCTestCase {

//When
let name = try resource.parse(validData)

//Then
XCTAssertEqual(name, "ICE")
}
Expand Down
1 change: 0 additions & 1 deletion Tests/RetryNetworkserviceTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ class RetryNetworkserviceTest: XCTestCase {

func testRetryRequest_shouldRetry() async throws {
//Given
let errorCount = 2
let numberOfRetries = 2
let networkServiceMock = NetworkServiceMock(
Result<Int, NetworkError>.failure(.unknownError),
Expand Down

0 comments on commit 7a0784c

Please sign in to comment.