diff --git a/README.md b/README.md index ae73e63..26d6b9f 100644 --- a/README.md +++ b/README.md @@ -334,10 +334,11 @@ Deserializer can also be declared without generic parameter but in that case the #### Client protocol -Implement following method from `Client` protocol: +Implement following method from `Client` protocol - userInfo contains custom data you can pass to the client to do some internal logic: e.g. add some extra headers, add encryption etc.: ```swift -func executeRequest(path: String, +func executeRequest(userInfo: [String: Any], + path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, @@ -676,6 +677,7 @@ dataSource - [x] DataSource with router and client when deleting resource client receives correct data from router for execution - [x] DataSource with path and client when creating resource invokes execute request on client - [x] DataSource with path and client when creating resource client receives correct data for execution +- [x] DataSource with path and client when creating resource client receives userInfo for execution - [x] DataSource with path and client when fetching single resource invokes execute request on client - [x] DataSource with path and client when fetching single resource client receives correct data for execution - [x] DataSource with path and client when fetching resource collection with custom pagination invokes execute request on client diff --git a/Vox/Core/Networking/Class/Request.swift b/Vox/Core/Networking/Class/Request.swift index fbc5e08..ac6501a 100644 --- a/Vox/Core/Networking/Class/Request.swift +++ b/Vox/Core/Networking/Class/Request.swift @@ -37,7 +37,7 @@ public class Request: DataSourceRes func execute() throws { let parameters: [String: Any]? = try resource?.documentDictionary() - client.executeRequest(request: unsafeBitCast(self, to: Request.self), path: path, method: httpMethod, queryItems: queryItems, bodyParameters: parameters, success: { (response, data) in + client.executeRequest(path: path, method: httpMethod, queryItems: queryItems, bodyParameters: parameters, success: { (response, data) in if let success = self.successBlock as? DataSource.ResourceSuccessBlock { guard let data = data else { fatalError("Unhandled exception") @@ -76,7 +76,7 @@ public class Request: DataSourceRes } else if let success = self.successBlock as? DataSource.DeleteSuccessBlock { success() } - }) { (error, data) in + }, failure: { (error, data) in guard let data = data else { self.failureBlock?(error) return @@ -87,7 +87,7 @@ public class Request: DataSourceRes } catch let __error { self.failureBlock?(__error) } - } + }, userInfo: userInfo) } } diff --git a/Vox/Core/Networking/Protocol/Client.swift b/Vox/Core/Networking/Protocol/Client.swift index a8596a1..6e68839 100644 --- a/Vox/Core/Networking/Protocol/Client.swift +++ b/Vox/Core/Networking/Protocol/Client.swift @@ -4,6 +4,6 @@ public typealias ClientSuccessBlock = (_ response: HTTPURLResponse?, _ data: Dat public typealias ClientFailureBlock = (_ error: Error?, _ data: Data?) -> Void public protocol Client: class { - func executeRequest(request: Request, path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String: Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock) + func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String: Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock, userInfo: [String: Any]) } diff --git a/Vox/Plugins/Alamofire/JSONAPIClient_Alamofire.swift b/Vox/Plugins/Alamofire/JSONAPIClient_Alamofire.swift index 08efe29..c269636 100644 --- a/Vox/Plugins/Alamofire/JSONAPIClient_Alamofire.swift +++ b/Vox/Plugins/Alamofire/JSONAPIClient_Alamofire.swift @@ -10,7 +10,7 @@ extension JSONAPIClient { self.baseURL = baseURL } - public func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock) { + public func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock, userInfo: [String: Any]) { let sessionManager = SessionManager.default let url = baseURL.appendingPathComponent(path) let headers: HTTPHeaders = [ diff --git a/VoxTests/DataSource/DataSourceSpec.swift b/VoxTests/DataSource/DataSourceSpec.swift index e5c7d7f..70636d2 100644 --- a/VoxTests/DataSource/DataSourceSpec.swift +++ b/VoxTests/DataSource/DataSourceSpec.swift @@ -88,15 +88,17 @@ fileprivate class MockClient: Client { class ExecuteRequestInspector { var path: String! var queryItems: [URLQueryItem] = [] + var userInfo: [String: Any] = [:] } let invocation = Invocation() let executeRequestInspector = ExecuteRequestInspector() - func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock) { + func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock, userInfo: [String: Any]) { invocation.executeRequest.invoke() executeRequestInspector.path = path executeRequestInspector.queryItems = queryItems + executeRequestInspector.userInfo = userInfo } } @@ -119,6 +121,13 @@ fileprivate class MockResource: Resource { } } +fileprivate extension Request { + func mockConfiguration() -> Self { + self.userInfo["key"] = "value" + return self + } +} + class DataSourceSpec: QuickSpec { override func spec() { @@ -129,11 +138,14 @@ class DataSourceSpec: QuickSpec { let sut = DataSource(strategy: .router(router), client: client) let resource = MockResource() - try! sut.create(resource).result({ (document) in - - }, { (error) in - - }) + try! sut + .create(resource) + .mockConfiguration() + .result({ (document) in + + }, { (error) in + + }) it("invokes execute request on client", closure: { expect(client.invocation.executeRequest.isInvokedOnce).to(beTrue()) @@ -150,6 +162,10 @@ class DataSourceSpec: QuickSpec { it("client receives correct data from router for execution", closure: { expect(client.executeRequestInspector.path).to(equal(createPath)) }) + + it("client receives correct data from request for execution", closure: { + expect(client.executeRequestInspector.userInfo as NSDictionary).to(equal(["key": "value"] as NSDictionary)) + }) }) context("when fetching single resource", { diff --git a/VoxTests/DataSource/PaginationSpec.swift b/VoxTests/DataSource/PaginationSpec.swift index ae699af..41f730c 100644 --- a/VoxTests/DataSource/PaginationSpec.swift +++ b/VoxTests/DataSource/PaginationSpec.swift @@ -69,7 +69,7 @@ fileprivate class MockClient: Client { var nextPath: String? var queryItems: [URLQueryItem]? - func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock) { + func executeRequest(path: String, method: String, queryItems: [URLQueryItem], bodyParameters: [String : Any]?, success: @escaping ClientSuccessBlock, failure: @escaping ClientFailureBlock, userInfo: [String: Any]) { if count == 0 { count += 1