From d7dad91c0bcbd820199b3a2ca0949b3e0e2fe5a2 Mon Sep 17 00:00:00 2001
From: Elvis <elvisnunez@me.com>
Date: Fri, 19 Jul 2024 18:36:26 +0200
Subject: [PATCH 1/5] Fix Void return for fake

---
 Sources/Networking/Networking+New.swift | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Sources/Networking/Networking+New.swift b/Sources/Networking/Networking+New.swift
index e6e7505..8303113 100644
--- a/Sources/Networking/Networking+New.swift
+++ b/Sources/Networking/Networking+New.swift
@@ -17,7 +17,7 @@ extension Networking {
                 case .success(let response):
                     if T.self == Data.self {
                         logger.info("Successfully processed fake request to \(path, privacy: .public)")
-                        return .success(() as! T)
+                        return .success(Data() as! T)
                     } else {
                         let decoder = JSONDecoder()
                         decoder.dateDecodingStrategy = .iso8601

From dba6e3a70160a70cec4ac0068c41f2fd4ea0f600 Mon Sep 17 00:00:00 2001
From: Elvis <elvisnunez@me.com>
Date: Fri, 19 Jul 2024 20:20:16 +0200
Subject: [PATCH 2/5] Fix/test faking for new methods

---
 Sources/Networking/Networking+New.swift      |  7 +++++
 Tests/NetworkingTests/FakeRequestTests.swift | 33 ++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/Sources/Networking/Networking+New.swift b/Sources/Networking/Networking+New.swift
index 8303113..d03955d 100644
--- a/Sources/Networking/Networking+New.swift
+++ b/Sources/Networking/Networking+New.swift
@@ -18,6 +18,13 @@ extension Networking {
                     if T.self == Data.self {
                         logger.info("Successfully processed fake request to \(path, privacy: .public)")
                         return .success(Data() as! T)
+                    } else if T.self == NetworkingResponse.self {
+                        let headers = Dictionary(uniqueKeysWithValues: response.headers.compactMap { key, value in
+                            (key as? String).map { ($0, AnyCodable(value)) }
+                        })
+                        let body = try JSONDecoder().decode([String: AnyCodable].self, from: response.data)
+                        let networkingJSON = NetworkingResponse(headers: headers, body: body)
+                        return .success(networkingJSON as! T)
                     } else {
                         let decoder = JSONDecoder()
                         decoder.dateDecodingStrategy = .iso8601
diff --git a/Tests/NetworkingTests/FakeRequestTests.swift b/Tests/NetworkingTests/FakeRequestTests.swift
index dc2e27f..ef2af4a 100644
--- a/Tests/NetworkingTests/FakeRequestTests.swift
+++ b/Tests/NetworkingTests/FakeRequestTests.swift
@@ -683,4 +683,37 @@ extension FakeRequestTests {
             XCTFail(response.error.localizedDescription)
         }
     }
+
+    func testNewPostWithFakeHeaders() async {
+        let networking = Networking(baseURL: baseURL)
+
+        networking.fakePOST("/auth/verify_confirmation_code", response: [
+            "phone_number": "phoneNumber"
+        ], headerFields: [
+            "client": "aClient",
+            "access-token": "anAccessToken",
+            "uid": "aUID",
+            "Authorization": "authorization",
+        ])
+
+        let parameters: [String: Any] = [
+            "phone_number": "phoneNumber",
+            "confirmation_code": "confirmationCode"
+        ]
+
+        let result: Result<NetworkingResponse, NetworkingError> = await networking.newPost("/auth/verify_confirmation_code", parameters: parameters)
+        switch result {
+        case .success(let response):
+            let headers = response.headers
+            XCTAssertEqual(headers.string(for: "access-token"), "anAccessToken")
+            XCTAssertEqual(headers.string(for: "client"), "aClient")
+            XCTAssertEqual(headers.string(for: "uid"), "aUID")
+            XCTAssertEqual(headers.string(for: "Authorization"), "authorization")
+
+            let body = response.body
+            XCTAssertEqual(body.string(for: "phone_number"), "phoneNumber")
+        case .failure (let response):
+            XCTFail(response.localizedDescription)
+        }
+    }
 }

From 5aaa89fef02602f435bb39d891585c7f30edf7df Mon Sep 17 00:00:00 2001
From: Elvis <elvisnunez@me.com>
Date: Mon, 5 Aug 2024 01:24:57 +0200
Subject: [PATCH 3/5] Add newPatch

---
 Sources/Networking/Networking+HTTPRequests.swift | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/Sources/Networking/Networking+HTTPRequests.swift b/Sources/Networking/Networking+HTTPRequests.swift
index ef05626..d3d0c64 100644
--- a/Sources/Networking/Networking+HTTPRequests.swift
+++ b/Sources/Networking/Networking+HTTPRequests.swift
@@ -73,6 +73,20 @@ public extension Networking {
         }
     }
 
+    func newPatch<T: Decodable>(_ path: String, parameters: [String: Any]) async -> Result<T, NetworkingError> {
+        return await handle(.patch, path: path, parameters: parameters)
+    }
+
+    func newPatch(_ path: String, parameters: [String: Any]) async -> Result<Void, NetworkingError> {
+        let result: Result<Data, NetworkingError> = await handle(.patch, path: path, parameters: parameters)
+        switch result {
+        case .success:
+            return .success(())
+        case .failure(let error):
+            return .failure(error)
+        }
+    }
+
     func newDelete(_ path: String) async -> Result<Void, NetworkingError> {
         let result: Result<Data, NetworkingError> = await handle(.delete, path: path, parameters: nil)
         switch result {

From 28f479ef6738fb90c2f0b91fce4d13f8c74073cb Mon Sep 17 00:00:00 2001
From: Elvis Nunez <3lvis@users.noreply.github.com>
Date: Mon, 5 Aug 2024 13:22:05 +0200
Subject: [PATCH 4/5] Improve Fake handling, add status code to faking with a
 file. (#280)

* Improve fake handling

* Improve fake handling, add status code to faking with file

* Remove dumb comparison

* Rename none to data
---
 Sources/Networking/JSON.swift                 |  15 +-
 .../Networking/Networking+HTTPRequests.swift  |  20 +-
 Sources/Networking/Networking+New.swift       | 204 +++++++++---------
 Sources/Networking/Networking+Private.swift   |   4 +-
 Sources/Networking/NetworkingResult.swift     |   9 +-
 Sources/Networking/Response.swift             |   2 +-
 Tests/NetworkingTests/GETTests.swift          |  39 ----
 Tests/NetworkingTests/JSONTests.swift         |   3 +-
 .../NetworkingTests/NewNetworkingTests.swift  |  64 ++++++
 Tests/NetworkingTests/ResultTests.swift       |  10 +-
 10 files changed, 201 insertions(+), 169 deletions(-)
 create mode 100644 Tests/NetworkingTests/NewNetworkingTests.swift

diff --git a/Sources/Networking/JSON.swift b/Sources/Networking/JSON.swift
index 019c005..c919773 100644
--- a/Sources/Networking/JSON.swift
+++ b/Sources/Networking/JSON.swift
@@ -6,7 +6,7 @@ enum ParsingError: Error {
 }
 
 enum JSON: Equatable {
-    case none
+    case data(Data)
 
     case dictionary(Data, [String: Any])
 
@@ -30,6 +30,17 @@ enum JSON: Equatable {
         }
     }
 
+    var data: Data {
+        switch self {
+        case let .dictionary(data, _):
+            return data
+        case let .array(data, _):
+            return data
+        case let .data(data):
+            return data
+        }
+    }
+
     init(_ data: Data) throws {
         let body = try JSONSerialization.jsonObject(with: data, options: [])
 
@@ -38,7 +49,7 @@ enum JSON: Equatable {
         } else if let array = body as? [[String: Any]] {
             self = .array(data, array)
         } else {
-            self = JSON.none
+            self = .data(data)
         }
     }
 
diff --git a/Sources/Networking/Networking+HTTPRequests.swift b/Sources/Networking/Networking+HTTPRequests.swift
index d3d0c64..85ef829 100644
--- a/Sources/Networking/Networking+HTTPRequests.swift
+++ b/Sources/Networking/Networking+HTTPRequests.swift
@@ -29,8 +29,8 @@ public extension Networking {
     ///   - path: The path for the faked GET request.
     ///   - fileName: The name of the file, whose contents will be registered as a reponse.
     ///   - bundle: The Bundle where the file is located.
-    func fakeGET(_ path: String, fileName: String, bundle: Bundle = Bundle.main, delay: Double = 0) {
-        registerFake(requestType: .get, path: path, fileName: fileName, bundle: bundle, delay: delay)
+    func fakeGET(_ path: String, fileName: String, bundle: Bundle = Bundle.main, statusCode: Int = 200, delay: Double = 0) {
+        registerFake(requestType: .get, path: path, fileName: fileName, bundle: bundle, statusCode: statusCode, delay: delay)
     }
 
     /// Cancels the GET request for the specified path. This causes the request to complete with error code URLError.cancelled.
@@ -127,8 +127,8 @@ public extension Networking {
     ///   - path: The path for the faked PATCH request.
     ///   - fileName: The name of the file, whose contents will be registered as a reponse.
     ///   - bundle: The Bundle where the file is located.
-    func fakePATCH(_ path: String, fileName: String, bundle: Bundle = Bundle.main, delay: Double = 0) {
-        registerFake(requestType: .patch, path: path, fileName: fileName, bundle: bundle, delay: delay)
+    func fakePATCH(_ path: String, fileName: String, bundle: Bundle = Bundle.main, statusCode: Int = 200, delay: Double = 0) {
+        registerFake(requestType: .patch, path: path, fileName: fileName, bundle: bundle, statusCode: statusCode, delay: delay)
     }
 
     /// Cancels the PATCH request for the specified path. This causes the request to complete with error code URLError.cancelled.
@@ -169,8 +169,8 @@ public extension Networking {
     ///   - path: The path for the faked PUT request.
     ///   - fileName: The name of the file, whose contents will be registered as a reponse.
     ///   - bundle: The Bundle where the file is located.
-    func fakePUT(_ path: String, fileName: String, bundle: Bundle = Bundle.main, delay: Double = 0) {
-        registerFake(requestType: .put, path: path, fileName: fileName, bundle: bundle, delay: delay)
+    func fakePUT(_ path: String, fileName: String, bundle: Bundle = Bundle.main, statusCode: Int = 200, delay: Double = 0) {
+        registerFake(requestType: .put, path: path, fileName: fileName, bundle: bundle, statusCode: statusCode, delay: delay)
     }
 
     /// Cancels the PUT request for the specified path. This causes the request to complete with error code URLError.cancelled.
@@ -221,8 +221,8 @@ public extension Networking {
     ///   - path: The path for the faked POST request.
     ///   - fileName: The name of the file, whose contents will be registered as a reponse.
     ///   - bundle: The Bundle where the file is located.
-    func fakePOST(_ path: String, fileName: String, bundle: Bundle = Bundle.main, delay: Double = 0) {
-        registerFake(requestType: .post, path: path, fileName: fileName, bundle: bundle, delay: delay)
+    func fakePOST(_ path: String, fileName: String, bundle: Bundle = Bundle.main, statusCode: Int = 200, delay: Double = 0) {
+        registerFake(requestType: .post, path: path, fileName: fileName, bundle: bundle, statusCode: statusCode, delay: delay)
     }
 
     /// Cancels the POST request for the specified path. This causes the request to complete with error code URLError.cancelled.
@@ -263,8 +263,8 @@ public extension Networking {
     ///   - path: The path for the faked DELETE request.
     ///   - fileName: The name of the file, whose contents will be registered as a reponse.
     ///   - bundle: The Bundle where the file is located.
-    func fakeDELETE(_ path: String, fileName: String, bundle: Bundle = Bundle.main, delay: Double = 0) {
-        registerFake(requestType: .delete, path: path, fileName: fileName, bundle: bundle, delay: delay)
+    func fakeDELETE(_ path: String, fileName: String, bundle: Bundle = Bundle.main, statusCode: Int = 200, delay: Double = 0) {
+        registerFake(requestType: .delete, path: path, fileName: fileName, bundle: bundle, statusCode: statusCode, delay: delay)
     }
 
     /// Cancels the DELETE request for the specified path. This causes the request to complete with error code URLError.cancelled.
diff --git a/Sources/Networking/Networking+New.swift b/Sources/Networking/Networking+New.swift
index d03955d..d7a6f0a 100644
--- a/Sources/Networking/Networking+New.swift
+++ b/Sources/Networking/Networking+New.swift
@@ -2,122 +2,112 @@ import Foundation
 
 extension Networking {
     func handle<T: Decodable>(_ requestType: RequestType, path: String, parameters: Any?) async -> Result<T, NetworkingError> {
-        var data: Data?
         do {
             logger.info("Starting \(requestType.rawValue) request to \(path, privacy: .public)")
 
             if let fakeRequest = try FakeRequest.find(ofType: requestType, forPath: path, in: fakeRequests) {
-                let (_, response, error) = try handleFakeRequest(fakeRequest, path: path, cacheName: nil, cachingLevel: .none)
-                if fakeRequest.delay > 0 {
-                    let nanoseconds = UInt64(fakeRequest.delay * 1_000_000_000)
-                    try? await Task.sleep(nanoseconds: nanoseconds)
-                }
-                let result = try JSONResult(body: fakeRequest.response, response: response, error: error)
-                switch result {
-                case .success(let response):
-                    if T.self == Data.self {
-                        logger.info("Successfully processed fake request to \(path, privacy: .public)")
-                        return .success(Data() as! T)
-                    } else if T.self == NetworkingResponse.self {
-                        let headers = Dictionary(uniqueKeysWithValues: response.headers.compactMap { key, value in
-                            (key as? String).map { ($0, AnyCodable(value)) }
-                        })
-                        let body = try JSONDecoder().decode([String: AnyCodable].self, from: response.data)
-                        let networkingJSON = NetworkingResponse(headers: headers, body: body)
-                        return .success(networkingJSON as! T)
-                    } else {
-                        let decoder = JSONDecoder()
-                        decoder.dateDecodingStrategy = .iso8601
-                        let decodedResponse = try decoder.decode(T.self, from: response.data)
-                        logger.info("Successfully decoded response from fake request to \(path, privacy: .public)")
-                        return .success(decodedResponse)
-                    }
-                case .failure(let response):
-                    logger.error("Failed to process fake request to \(path, privacy: .public): \(response.error.localizedDescription, privacy: .public)")
-                    return .failure(.unexpectedError(statusCode: nil, message: "Failed to process fake request (error: \(response.error.localizedDescription))."))
-                }
+                return try await handleFakeRequest(fakeRequest, path: path, requestType: requestType)
             }
 
-            let parameterType: Networking.ParameterType? = parameters != nil ? .json : nil
-            var request = URLRequest(url: try composedURL(with: path), requestType: requestType, path: path, parameterType: parameterType, responseType: .json, boundary: boundary, authorizationHeaderValue: authorizationHeaderValue, token: token, authorizationHeaderKey: authorizationHeaderKey, headerFields: headerFields)
+            let request = try createRequest(path: path, requestType: requestType, parameters: parameters)
+            let (responseData, response) = try await session.data(for: request)
+            return try handleResponse(responseData: responseData, response: response, path: path)
 
-            if let parameters = parameters {
-                request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
-            }
+        } catch {
+            return handleRequestError(error: error)
+        }
+    }
 
-            let (responseData, response) = try await session.data(for: request)
-            data = responseData
-            guard let httpResponse = response as? HTTPURLResponse else {
-                logger.error("Invalid response received from \(path, privacy: .public)")
-                return .failure(.invalidResponse)
-            }
+    private func handleFakeRequest<T: Decodable>(_ fakeRequest: FakeRequest, path: String, requestType: RequestType) async throws -> Result<T, NetworkingError> {
+        let (_, response, error) = try handleFakeRequest(fakeRequest, path: path, cacheName: nil, cachingLevel: .none)
 
-            let statusCode = httpResponse.statusCode
-            switch statusCode.statusCodeType {
-            case .informational, .successful:
-                logger.info("Received successful response with status code \(statusCode) from \(path, privacy: .public)")
-                if T.self == Data.self {
-                    return .success(Data() as! T)
-                } else if T.self == NetworkingResponse.self {
-                    let headers = Dictionary(uniqueKeysWithValues: httpResponse.allHeaderFields.compactMap { key, value in
-                        (key as? String).map { ($0, AnyCodable(value)) }
-                    })
-                    let body = try JSONDecoder().decode([String: AnyCodable].self, from: responseData)
-                    let networkingJSON = NetworkingResponse(headers: headers, body: body)
-                    return .success(networkingJSON as! T)
-                } else {
-                    let decoder = JSONDecoder()
-                    decoder.dateDecodingStrategy = .iso8601
-                    let decodedResponse = try decoder.decode(T.self, from: responseData)
-                    return .success(decodedResponse)
-                }
-            case .redirection:
-                logger.warning("Redirection response with status code \(statusCode) from \(path, privacy: .public)")
-                return .failure(.unexpectedError(statusCode: statusCode, message: "Redirection occurred."))
-            case .clientError:
-                let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
-                if let jsonString = String(data: responseData, encoding: .utf8) {
-                    logger.warning("Client error: \(jsonString, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                }
-                if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: responseData) {
-                    logger.warning("Client error: \(errorResponse.combinedMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                    return .failure(.clientError(statusCode: statusCode, message: errorResponse.combinedMessage))
-                } else {
-                    logger.warning("Client error: \(errorMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                    return .failure(.clientError(statusCode: statusCode, message: errorMessage))
-                }
-            case .serverError:
-                let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
-                var errorDetails: [String: Any]? = nil
-                if let jsonString = String(data: responseData, encoding: .utf8) {
-                    logger.error("Server error: \(jsonString, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                }
-                if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: responseData) {
-                    errorDetails = ["error": errorResponse.error ?? "",
-                                    "message": errorResponse.message ?? "",
-                                    "errors": errorResponse.errors ?? [:]]
-                    logger.error("Server error: \(errorResponse.combinedMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                    return .failure(.serverError(statusCode: statusCode, message: errorResponse.combinedMessage, details: errorDetails))
-                } else {
-                    logger.error("Server error: \(errorMessage, privacy: .public) with status code \(statusCode) from \(path, privacy: .public)")
-                    return .failure(.serverError(statusCode: statusCode, message: errorMessage, details: errorDetails))
-                }
-            case .cancelled:
-                logger.info("Request cancelled with status code \(statusCode) from \(path, privacy: .public)")
-                return .failure(.unexpectedError(statusCode: statusCode, message: "Request was cancelled."))
-            case .unknown:
-                logger.error("Unexpected error with status code \(statusCode) from \(path, privacy: .public)")
-                return .failure(.unexpectedError(statusCode: statusCode, message: "An unexpected error occurred."))
-            }
-        } catch let error as NSError {
-            if let data = data, let jsonString = String(data: data, encoding: .utf8) {
-                logger.error("Unexpected error occurred: \(error.localizedDescription, privacy: .public). Response data: \(jsonString, privacy: .public)")
-            } else if let decodingError = error as? DecodingError {
-                logger.error("Unexpected error occurred: \(decodingError.detailedMessage, privacy: .public)")
-            } else {
-                logger.error("Unexpected error occurred: \(error.localizedDescription, privacy: .public)")
-            }
-            return .failure(.unexpectedError(statusCode: nil, message: "Failed to process request (error: \(error.localizedDescription))."))
+        if fakeRequest.delay > 0 {
+            try? await Task.sleep(nanoseconds: UInt64(fakeRequest.delay * 1_000_000_000))
+        }
+
+        let result = try JSONResult(body: fakeRequest.response, response: response, error: error)
+        return try handleResponse(responseData: result.data, response: response, path: path)
+    }
+
+    private func createRequest(path: String, requestType: RequestType, parameters: Any?) throws -> URLRequest {
+        let parameterType: Networking.ParameterType? = parameters != nil ? .json : nil
+        var request = URLRequest(url: try composedURL(with: path), requestType: requestType, path: path, parameterType: parameterType, responseType: .json, boundary: boundary, authorizationHeaderValue: authorizationHeaderValue, token: token, authorizationHeaderKey: authorizationHeaderKey, headerFields: headerFields)
+
+        if let parameters = parameters {
+            request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
+        }
+
+        return request
+    }
+
+    private func handleResponse<T: Decodable>(responseData: Data, response: URLResponse, path: String) throws -> Result<T, NetworkingError> {
+        guard let httpResponse = response as? HTTPURLResponse else {
+            return .failure(.invalidResponse)
+        }
+
+        let statusCode = httpResponse.statusCode
+        switch statusCode.statusCodeType {
+        case .informational, .successful:
+            return try handleSuccessfulResponse(responseData: responseData, path: path, httpResponse: httpResponse)
+        case .redirection:
+            return .failure(.unexpectedError(statusCode: statusCode, message: "Redirection occurred."))
+        case .clientError:
+            return try handleClientError(responseData: responseData, statusCode: statusCode, path: path)
+        case .serverError:
+            return try handleServerError(responseData: responseData, statusCode: statusCode, path: path)
+        case .cancelled:
+            return .failure(.unexpectedError(statusCode: statusCode, message: "Request was cancelled."))
+        case .unknown:
+            return .failure(.unexpectedError(statusCode: statusCode, message: "An unexpected error occurred."))
+        }
+    }
+
+    private func handleSuccessfulResponse<T: Decodable>(responseData: Data, path: String, httpResponse: HTTPURLResponse) throws -> Result<T, NetworkingError> {
+        if T.self == Data.self {
+            return .success(Data() as! T)
+        } else if T.self == NetworkingResponse.self {
+            let headers = Dictionary(uniqueKeysWithValues: httpResponse.allHeaderFields.compactMap { key, value in
+                (key as? String).map { ($0, AnyCodable(value)) }
+            })
+            let body = try JSONDecoder().decode([String: AnyCodable].self, from: responseData)
+            let networkingJSON = NetworkingResponse(headers: headers, body: body)
+            return .success(networkingJSON as! T)
+        } else {
+            let decoder = JSONDecoder()
+            decoder.dateDecodingStrategy = .iso8601
+            let decodedResponse = try decoder.decode(T.self, from: responseData)
+            return .success(decodedResponse)
+        }
+    }
+
+    private func handleClientError<T: Decodable>(responseData: Data, statusCode: Int, path: String) throws -> Result<T, NetworkingError> {
+        let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
+        if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: responseData) {
+            return .failure(.clientError(statusCode: statusCode, message: errorResponse.combinedMessage))
+        } else {
+            return .failure(.clientError(statusCode: statusCode, message: errorMessage))
+        }
+    }
+
+    private func handleServerError<T: Decodable>(responseData: Data, statusCode: Int, path: String) throws -> Result<T, NetworkingError> {
+        let errorMessage = HTTPURLResponse.localizedString(forStatusCode: statusCode)
+        var errorDetails: [String: Any]? = nil
+        if let errorResponse = try? JSONDecoder().decode(ErrorResponse.self, from: responseData) {
+            errorDetails = ["error": errorResponse.error ?? "",
+                            "message": errorResponse.message ?? "",
+                            "errors": errorResponse.errors ?? [:]]
+            return .failure(.serverError(statusCode: statusCode, message: errorResponse.combinedMessage, details: errorDetails))
+        } else {
+            return .failure(.serverError(statusCode: statusCode, message: errorMessage, details: errorDetails))
+        }
+    }
+
+    private func handleRequestError<T: Decodable>(error: Error) -> Result<T, NetworkingError> {
+        if let decodingError = error as? DecodingError {
+            logger.error("Unexpected error occurred: \(decodingError.detailedMessage, privacy: .public)")
+        } else {
+            logger.error("Unexpected error occurred: \(error.localizedDescription, privacy: .public)")
         }
+        return .failure(.unexpectedError(statusCode: nil, message: "Failed to process request (error: \(error.localizedDescription))."))
     }
 }
diff --git a/Sources/Networking/Networking+Private.swift b/Sources/Networking/Networking+Private.swift
index 4deab31..7c72891 100644
--- a/Sources/Networking/Networking+Private.swift
+++ b/Sources/Networking/Networking+Private.swift
@@ -39,10 +39,10 @@ extension Networking {
         }
     }
 
-    func registerFake(requestType: RequestType, path: String, fileName: String, bundle: Bundle, delay: Double) {
+    func registerFake(requestType: RequestType, path: String, fileName: String, bundle: Bundle, statusCode: Int, delay: Double) {
         do {
             if let result = try FileManager.json(from: fileName, bundle: bundle) {
-                registerFake(requestType: requestType, path: path, headerFields: nil, response: result, responseType: .json, statusCode: 200, delay: delay)
+                registerFake(requestType: requestType, path: path, headerFields: nil, response: result, responseType: .json, statusCode: statusCode, delay: delay)
             }
         } catch ParsingError.notFound {
             fatalError("We couldn't find \(fileName), are you sure is there?")
diff --git a/Sources/Networking/NetworkingResult.swift b/Sources/Networking/NetworkingResult.swift
index 648550b..b3c55a4 100644
--- a/Sources/Networking/NetworkingResult.swift
+++ b/Sources/Networking/NetworkingResult.swift
@@ -19,6 +19,13 @@ public enum JSONResult: NetworkingResult {
 
     case failure(FailureJSONResponse)
 
+    public var data: Data {
+        switch self {
+        case .success(let response): return response.json.data
+        case .failure(let response): return response.json.data
+        }
+    }
+
     public var error: NSError? {
         switch self {
         case .success:
@@ -30,7 +37,7 @@ public enum JSONResult: NetworkingResult {
 
     public init(body: Any?, response: HTTPURLResponse, error: NSError?) throws {
         var returnedError = error
-        var json = JSON.none
+        var json = JSON.data(Data())
 
         do {
             if let dictionary = body as? [String: Any] {
diff --git a/Sources/Networking/Response.swift b/Sources/Networking/Response.swift
index 89e4c04..35bb6b2 100644
--- a/Sources/Networking/Response.swift
+++ b/Sources/Networking/Response.swift
@@ -44,7 +44,7 @@ public class JSONResponse: Response {
             return value
         case let .dictionary(value, _):
             return value
-        case .none:
+        case .data:
             return Data()
         }
     }
diff --git a/Tests/NetworkingTests/GETTests.swift b/Tests/NetworkingTests/GETTests.swift
index 8099210..0b07038 100644
--- a/Tests/NetworkingTests/GETTests.swift
+++ b/Tests/NetworkingTests/GETTests.swift
@@ -229,43 +229,4 @@ class GETTests: XCTestCase {
             XCTFail(response.error.localizedDescription)
         }
     }
-
-    func testNewGET() async throws {
-        let networking = Networking(baseURL: baseURL)
-
-        let result: Result<Friend, NetworkingError> = await networking.newGet("/get")
-
-        switch result {
-        case .success(let success):
-            print("worked")
-        case .failure(let failure):
-            print(failure.localizedDescription)
-        }
-    }
-
-    func testNewPOST() async throws {
-        let networking = Networking(baseURL: baseURL)
-
-        let result: Result<Void, NetworkingError> = await networking.newPost("/get", parameters: ["String": "String"])
-
-        switch result {
-        case .success(let success):
-            print("worked")
-        case .failure(let failure):
-            print(failure.localizedDescription)
-        }
-    }
-
-    func testNetworkingJSON() async throws {
-        let networking = Networking(baseURL: baseURL)
-
-        let result: Result<NetworkingResponse, NetworkingError> = await networking.newGet("/auth")
-        switch result {
-        case .success(let success):
-            let header = success.headers.string(for: "access-token")
-            let body = success.body.string(for: "id")
-        case .failure(let failure):
-            print(failure.localizedDescription)
-        }
-    }
 }
diff --git a/Tests/NetworkingTests/JSONTests.swift b/Tests/NetworkingTests/JSONTests.swift
index 359e63d..f2253f7 100644
--- a/Tests/NetworkingTests/JSONTests.swift
+++ b/Tests/NetworkingTests/JSONTests.swift
@@ -26,8 +26,7 @@ class JSONTests: XCTestCase {
     }
 
     func testEqualNone() {
-        XCTAssertEqual(JSON.none, JSON.none)
-        XCTAssertNotEqual(JSON.none, try JSON(["hello": "value"]))
+        XCTAssertNotEqual(JSON.data(Data()), try JSON(["hello": "value"]))
     }
 
     // MARKL - Accessors
diff --git a/Tests/NetworkingTests/NewNetworkingTests.swift b/Tests/NetworkingTests/NewNetworkingTests.swift
new file mode 100644
index 0000000..be4e7dc
--- /dev/null
+++ b/Tests/NetworkingTests/NewNetworkingTests.swift
@@ -0,0 +1,64 @@
+import Foundation
+import XCTest
+@testable import Networking
+
+class NewNetworkingTests: XCTestCase {
+    let baseURL = "http://httpbin.org"
+
+    func testNewGET() async throws {
+        let networking = Networking(baseURL: baseURL)
+
+        let result: Result<Friend, NetworkingError> = await networking.newGet("/get")
+
+        switch result {
+        case .success(_):
+            print("worked")
+        case .failure(let failure):
+            print(failure.localizedDescription)
+        }
+    }
+
+    func testNewPOST() async throws {
+        let networking = Networking(baseURL: baseURL)
+
+        let result: Result<Void, NetworkingError> = await networking.newPost("/get", parameters: ["String": "String"])
+
+        switch result {
+        case .success(_):
+            print("worked")
+        case .failure(let failure):
+            print(failure.localizedDescription)
+        }
+    }
+
+    func testNetworkingJSON() async throws {
+        let networking = Networking(baseURL: baseURL)
+
+        let result: Result<NetworkingResponse, NetworkingError> = await networking.newGet("/auth")
+        switch result {
+        case .success(let success):
+            _ = success.headers.string(for: "access-token")
+            _ = success.body.string(for: "id")
+        case .failure(let failure):
+            print(failure.localizedDescription)
+        }
+    }
+
+    func testErrorNetworkingJSON() async throws {
+        let networking = Networking(baseURL: baseURL)
+
+        let response: [String: Any] = [
+            "errors": [
+                "phone_number": ["has already been taken"]
+            ]
+        ]
+        networking.fakePOST("/auth", response: response, statusCode: 422)
+
+        let result: Result<NetworkingResponse, NetworkingError> = await networking.newPost("/auth", parameters: [:])
+        switch result {
+        case .success(_): break
+        case .failure(let response):
+            XCTAssertTrue(response.errorDescription!.contains("has already been taken"))
+        }
+    }
+}
diff --git a/Tests/NetworkingTests/ResultTests.swift b/Tests/NetworkingTests/ResultTests.swift
index 5dc2d3f..9c8e68b 100644
--- a/Tests/NetworkingTests/ResultTests.swift
+++ b/Tests/NetworkingTests/ResultTests.swift
@@ -22,7 +22,7 @@ class ResultTests: XCTestCase {
             switch value.json {
             case let .dictionary(_, valueBody):
                 XCTAssertEqual(body.debugDescription, valueBody.debugDescription)
-            case .array(_, _), .none:
+            case .array(_, _), .data:
                 XCTFail()
             }
         case let .failure(response):
@@ -43,7 +43,7 @@ class ResultTests: XCTestCase {
             case let .array(_, valueBody):
                 XCTAssertEqual(expectedBody.debugDescription, valueBody.debugDescription)
                 // XCTAssertEqual(dataBody.hashValue, expectedBody.hashValue)
-            case .dictionary(_, _), .none:
+            case .dictionary(_, _), .data:
                 XCTFail()
             }
         case let .failure(response):
@@ -65,7 +65,7 @@ class ResultTests: XCTestCase {
             case let .dictionary(dataBody, valueBody):
                 XCTAssertEqual(dataBody.hashValue, expectedBodyData.hashValue)
                 XCTAssertEqual(valueBody.debugDescription, expectedBody.debugDescription)
-            case .array(_, _), .none:
+            case .array(_, _), .data:
                 XCTFail()
             }
         case let .failure(response):
@@ -87,7 +87,7 @@ class ResultTests: XCTestCase {
             case let .array(dataBody, valueBody):
                 XCTAssertEqual(dataBody.hashValue, expectedBodyData.hashValue)
                 XCTAssertEqual(valueBody.debugDescription, expectedBody.debugDescription)
-            case .dictionary(_, _), .none:
+            case .dictionary(_, _), .data:
                 XCTFail()
             }
         case let .failure(response):
@@ -106,7 +106,7 @@ class ResultTests: XCTestCase {
             switch value.json {
             case .dictionary(_, _), .array:
                 XCTFail()
-            case .none:
+            case .data:
                 break
             }
         case let .failure(response):

From 127ac618bc264074c2c6edaa9d496b5519deef4c Mon Sep 17 00:00:00 2001
From: Elvis Nunez <3lvis@users.noreply.github.com>
Date: Mon, 14 Oct 2024 00:31:11 +0200
Subject: [PATCH 5/5] Now supporting get parameters (#281)

---
 .../Networking/Networking+HTTPRequests.swift  |  4 +--
 Sources/Networking/Networking+New.swift       | 31 +++++++++++++++++--
 .../NetworkingTests/NewNetworkingTests.swift  | 24 ++++++++++++++
 3 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/Sources/Networking/Networking+HTTPRequests.swift b/Sources/Networking/Networking+HTTPRequests.swift
index 85ef829..1cef7c1 100644
--- a/Sources/Networking/Networking+HTTPRequests.swift
+++ b/Sources/Networking/Networking+HTTPRequests.swift
@@ -41,8 +41,8 @@ public extension Networking {
         await cancelRequest(.data, requestType: .get, url: url)
     }
 
-    func newGet<T: Decodable>(_ path: String) async -> Result<T, NetworkingError> {
-        return await handle(.get, path: path, parameters: nil)
+    func newGet<T: Decodable>(_ path: String, parameters: Any? = nil) async -> Result<T, NetworkingError> {
+        return await handle(.get, path: path, parameters: parameters)
     }
 
     func newPost<T: Decodable>(_ path: String, parameters: [String: Any]) async -> Result<T, NetworkingError> {
diff --git a/Sources/Networking/Networking+New.swift b/Sources/Networking/Networking+New.swift
index d7a6f0a..adc1a97 100644
--- a/Sources/Networking/Networking+New.swift
+++ b/Sources/Networking/Networking+New.swift
@@ -30,10 +30,35 @@ extension Networking {
     }
 
     private func createRequest(path: String, requestType: RequestType, parameters: Any?) throws -> URLRequest {
-        let parameterType: Networking.ParameterType? = parameters != nil ? .json : nil
-        var request = URLRequest(url: try composedURL(with: path), requestType: requestType, path: path, parameterType: parameterType, responseType: .json, boundary: boundary, authorizationHeaderValue: authorizationHeaderValue, token: token, authorizationHeaderKey: authorizationHeaderKey, headerFields: headerFields)
+        guard var urlComponents = URLComponents(string: try composedURL(with: path).absoluteString) else {
+            throw URLError(.badURL)
+        }
+
+        if requestType == .get, let queryParameters = parameters as? [String: Any] {
+            urlComponents.queryItems = queryParameters.map { key, value in
+                URLQueryItem(name: key, value: "\(value)")
+            }
+        }
+
+        guard let url = urlComponents.url else {
+            throw URLError(.badURL)
+        }
 
-        if let parameters = parameters {
+        let parameterType: Networking.ParameterType? = (requestType == .get || parameters == nil) ? nil : .json
+        var request = URLRequest(
+            url: url,
+            requestType: requestType,
+            path: path,
+            parameterType: parameterType,
+            responseType: .json,
+            boundary: boundary,
+            authorizationHeaderValue: authorizationHeaderValue,
+            token: token,
+            authorizationHeaderKey: authorizationHeaderKey,
+            headerFields: headerFields
+        )
+
+        if requestType != .get, let parameters = parameters {
             request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
         }
 
diff --git a/Tests/NetworkingTests/NewNetworkingTests.swift b/Tests/NetworkingTests/NewNetworkingTests.swift
index be4e7dc..ab28ea5 100644
--- a/Tests/NetworkingTests/NewNetworkingTests.swift
+++ b/Tests/NetworkingTests/NewNetworkingTests.swift
@@ -1,5 +1,6 @@
 import Foundation
 import XCTest
+import CoreLocation
 @testable import Networking
 
 class NewNetworkingTests: XCTestCase {
@@ -18,6 +19,29 @@ class NewNetworkingTests: XCTestCase {
         }
     }
 
+    func testNewGETWithParams() async throws {
+        let networking = Networking(baseURL: baseURL)
+
+        let pickupCoordinate = CLLocationCoordinate2D(latitude: 59.91700978556453, longitude: 10.760668740407757)
+        let deliveryCoordinate = CLLocationCoordinate2D(latitude: 59.937611066825674, longitude: 10.735343079276985)
+
+        let parameters = [
+            "pickup_latitude": pickupCoordinate.latitude,
+            "pickup_longitude": pickupCoordinate.longitude,
+            "delivery_latitude": deliveryCoordinate.latitude,
+            "delivery_longitude": deliveryCoordinate.longitude
+        ]
+
+        let result: Result<Friend, NetworkingError> = await networking.newGet("/get", parameters: parameters)
+
+        switch result {
+        case .success(_):
+            print("Test passed")
+        case .failure(let error):
+            print("error \(error)")
+        }
+    }
+
     func testNewPOST() async throws {
         let networking = Networking(baseURL: baseURL)