From 0f64fdc913302ad73b7ce8f1dc1bf52f4fddf3bb Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Sat, 13 Jan 2018 06:18:33 -0200 Subject: [PATCH 01/12] Create NetworkPost --- .../Frisbee/Requestables/NetworkPost.swift | 49 +++++++++++++++++++ Sources/Frisbee/Requestables/Postable.swift | 10 ++++ .../IntegrationNetworkPostTests.swift | 12 +++++ .../Requestables/NetworkPostTests.swift | 2 + 4 files changed, 73 insertions(+) create mode 100644 Sources/Frisbee/Requestables/NetworkPost.swift create mode 100644 Sources/Frisbee/Requestables/Postable.swift create mode 100644 Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift create mode 100644 Tests/FrisbeeTests/Requestables/NetworkPostTests.swift diff --git a/Sources/Frisbee/Requestables/NetworkPost.swift b/Sources/Frisbee/Requestables/NetworkPost.swift new file mode 100644 index 0000000..323392f --- /dev/null +++ b/Sources/Frisbee/Requestables/NetworkPost.swift @@ -0,0 +1,49 @@ +import Foundation + +public final class NetworkPost: Postable { + + let urlSession: URLSession + + public init() { + self.urlSession = URLSessionFactory.make() + } + + public init(urlSession: URLSession) { + self.urlSession = urlSession + } + + public func post(url: String, onComplete: @escaping (Result) -> Void) { + guard let url = URL(string: url) else { + return onComplete(.fail(FrisbeeError.invalidUrl)) + } + makeRequest(url: url, onComplete: onComplete) + } + + public func post(url: URL, onComplete: @escaping (Result) -> Void) { + makeRequest(url: url, onComplete: onComplete) + } + + public func post(url: String, body: Body, + onComplete: @escaping (Result) -> Void) { + guard let url = URL(string: url) else { + return onComplete(.fail(FrisbeeError.invalidUrl)) + } + makeRequest(url: url, onComplete: onComplete) + } + + public func post(url: URL, body: Body, + onComplete: @escaping (Result) -> Void) { + makeRequest(url: url, onComplete: onComplete) + } + + private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { + let request = URLRequestFactory.make(.POST, url) + + let task = urlSession.dataTask(with: request) { data, _, error in + onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) + } + + task.resume() + } + +} diff --git a/Sources/Frisbee/Requestables/Postable.swift b/Sources/Frisbee/Requestables/Postable.swift new file mode 100644 index 0000000..e781a68 --- /dev/null +++ b/Sources/Frisbee/Requestables/Postable.swift @@ -0,0 +1,10 @@ +import Foundation + +protocol Postable { + func post(url: String, onComplete: @escaping (Result) -> Void) + func post(url: URL, onComplete: @escaping (Result) -> Void) + func post(url: String, body: Body, + onComplete: @escaping (Result) -> Void) + func post(url: URL, body: Body, + onComplete: @escaping (Result) -> Void) +} diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift new file mode 100644 index 0000000..c59d153 --- /dev/null +++ b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift @@ -0,0 +1,12 @@ +import XCTest + +final class IntegrationNetworkPostTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + func testMethodNameWhenSomethingThenDoAnotherThing() { + } + +} diff --git a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift new file mode 100644 index 0000000..1f2af05 --- /dev/null +++ b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift @@ -0,0 +1,2 @@ +final class NetworkPostTests { +} From c1e53417705ae226dc4d993b7be311e436813b54 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Sat, 13 Jan 2018 06:19:04 -0200 Subject: [PATCH 02/12] Create NetworkPost --- Frisbee.xcodeproj/project.pbxproj | 16 +++ .../IntegrationNetworkPostTests.swift | 21 +++- .../Requestables/NetworkPostTests.swift | 98 ++++++++++++++++++- Tests/LinuxMain.swift | 2 +- 4 files changed, 132 insertions(+), 5 deletions(-) diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index cff564d..c6db662 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -21,6 +21,10 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 3409C9E02009EFBA00353DC4 /* Postable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9DE2009EFBA00353DC4 /* Postable.swift */; }; + 3409C9E12009EFBA00353DC4 /* NetworkPost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */; }; + 3409C9E32009EFE000353DC4 /* NetworkPostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */; }; + 3409C9E52009F4E900353DC4 /* IntegrationNetworkPostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */; }; 3434A0B21FE7D9CC000659E5 /* URLRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */; }; 3434A0B41FE7D9FF000659E5 /* URLSessionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */; }; 3434A0B61FE7DA5A000659E5 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */; }; @@ -77,6 +81,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 3409C9DE2009EFBA00353DC4 /* Postable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Postable.swift; sourceTree = ""; }; + 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkPost.swift; sourceTree = ""; }; + 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkPostTests.swift; sourceTree = ""; }; + 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationNetworkPostTests.swift; sourceTree = ""; }; 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestFactory.swift; sourceTree = ""; }; 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionFactory.swift; sourceTree = ""; }; 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; @@ -163,6 +171,7 @@ isa = PBXGroup; children = ( 3434A0BE1FE7E025000659E5 /* IntegrationNetworkGetTests.swift */, + 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */, ); name = Integration; path = Tests/FrisbeeTests/Integration; @@ -184,6 +193,8 @@ children = ( 344FC7191FE5B93200958CE4 /* Getable.swift */, 344FC71F1FE5BBFE00958CE4 /* NetworkGet.swift */, + 3409C9DE2009EFBA00353DC4 /* Postable.swift */, + 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */, ); name = Requestables; path = Sources/Frisbee/Requestables; @@ -206,6 +217,7 @@ isa = PBXGroup; children = ( OBJ_12 /* NetworkGetTests.swift */, + 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */, ); name = Requestables; path = Tests/FrisbeeTests/Requestables; @@ -447,11 +459,13 @@ 34F91DA32008219600FFAE20 /* Movie.swift in Sources */, 578D2CA520019B1400EE3865 /* ResultTests.swift in Sources */, 579F534E200151DF00E9996A /* MockURLSession.swift in Sources */, + 3409C9E32009EFE000353DC4 /* NetworkPostTests.swift in Sources */, 578D2CA720019C3D00EE3865 /* SequenceExtensions.swift in Sources */, 34F91DAC200823FA00FFAE20 /* SomeEntity.swift in Sources */, 3434A0BF1FE7E025000659E5 /* IntegrationNetworkGetTests.swift in Sources */, 3434A0BA1FE7DC30000659E5 /* URLRequestFactoryTests.swift in Sources */, 579F53512001525100E9996A /* SomeError.swift in Sources */, + 3409C9E52009F4E900353DC4 /* IntegrationNetworkPostTests.swift in Sources */, 344FC7291FE5D7FC00958CE4 /* ResultGeneratorTests.swift in Sources */, 344DD87D1FFEFC910021350B /* URLWithQueryBuilderTests.swift in Sources */, OBJ_27 /* NetworkGetTests.swift in Sources */, @@ -469,6 +483,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( + 3409C9E12009EFBA00353DC4 /* NetworkPost.swift in Sources */, 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */, 344FC71A1FE5B93200958CE4 /* Getable.swift in Sources */, 344DD87B1FFEFBE40021350B /* URLWithQueryBuilder.swift in Sources */, @@ -483,6 +498,7 @@ 34C52E8920098A3100DCD88C /* FrisbeeDecodableFacotry.swift in Sources */, 34C52E8B20098D4100DCD88C /* FrisbeeJSONDecoder.swift in Sources */, 344FC71C1FE5B9D500958CE4 /* FrisbeeError.swift in Sources */, + 3409C9E02009EFBA00353DC4 /* Postable.swift in Sources */, 34F9C72C1FE89F44002C1EB0 /* QueryItemBuilder.swift in Sources */, 34C52E8D20098D8D00DCD88C /* URLWithQueryBuildable.swift in Sources */, ); diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift index c59d153..f2b18b3 100644 --- a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift +++ b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift @@ -1,12 +1,27 @@ import XCTest +import Frisbee final class IntegrationNetworkPostTests: XCTestCase { - override func setUp() { - super.setUp() + struct Json: Decodable { + let url: String } - func testMethodNameWhenSomethingThenDoAnotherThing() { + func testPostWhenHasValidURLThenRequestAndTransformData() { + let url = URL(string: "https://httpbin.org/anything/testPostWhenHasValidURLThenRequestAndTransformData")! + let longRunningExpectation = expectation(description: "RequestMoviesWithSuccess") + let expectedUrlAtResponse = url.absoluteString + var returnedData: Json? + + NetworkPost().post(url: url) { (result: Result) in + returnedData = result.data + longRunningExpectation.fulfill() + } + + waitForExpectations(timeout: 20) { expectationError in + XCTAssertNil(expectationError, expectationError!.localizedDescription) + XCTAssertEqual(returnedData?.url, expectedUrlAtResponse) + } } } diff --git a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift index 1f2af05..7f06351 100644 --- a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift +++ b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift @@ -1,2 +1,98 @@ -final class NetworkPostTests { +import XCTest +@testable import Frisbee + +final class NetworkPostTests: XCTestCase { + + private let invalidUrlString = "🤷‍♂️" + private let validUrlString = "http://www.com.br" + + #if !os(Linux) + func testInitWithCustomUrlSessionThenKeepSameReferenceOfUrlSession() { + let urlSession = URLSession(configuration: .default) + let networkPost = NetworkPost(urlSession: urlSession) + + XCTAssertEqual(urlSession, networkPost.urlSession) + } + + func testPostWhenURLStringIsInvalidFormatThenExecuteCompletionHandlerWithInvalidURLError() { + var generatedResult: Result! + + NetworkPost().post(url: invalidUrlString) { generatedResult = $0 } + + XCTAssertEqual(generatedResult, Result.fail(.invalidUrl)) + } + + func testPostWhenValidURLThenGenerateSuccessResult() { + let session = MockURLSession(results: [.success(Empty.data, URLResponse())]) + let networkPost = NetworkPost(urlSession: session) + var generatedResult: Result! + + networkPost.post(url: validUrlString) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.data, Empty()) + XCTAssertNil(generatedResult.error) + } + + func testPostWhenValidURLWithBodyThenGenerateSuccessResult() { + let session = MockURLSession(results: [.success(Empty.data, URLResponse())]) + let networkPost = NetworkPost(urlSession: session) + let body = Empty() + var generatedResult: Result! + + networkPost.post(url: validUrlString, body: body) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.data, Empty()) + XCTAssertNil(generatedResult.error) + } + + func testPostWhenInvalidURLThenGenerateFailResult() { + let session = MockURLSession(results: []) + let networkPost = NetworkPost(urlSession: session) + var generatedResult: Result! + + networkPost.post(url: invalidUrlString) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.error, .invalidUrl) + XCTAssertNil(generatedResult.data) + } + + func testPostWithBodyWhenInvalidURLThenGenerateFailResult() { + let session = MockURLSession(results: []) + let networkPost = NetworkPost(urlSession: session) + let body = Empty() + var generatedResult: Result! + + networkPost.post(url: invalidUrlString, body: body) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.error, .invalidUrl) + XCTAssertNil(generatedResult.data) + } + + func testPostWhenValidURLAndRequestFailsThenGenerateFailResult() { + let session = MockURLSession(results: [.error(SomeError.some)]) + let networkPost = NetworkPost(urlSession: session) + var generatedResult: Result! + + networkPost.post(url: validUrlString) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.error, .other(localizedDescription: SomeError.some.localizedDescription)) + XCTAssertNil(generatedResult.data) + } + + static var allTests = [ + ("testInitWithCustomUrlSessionThenKeepSameReferenceOfUrlSession", + testInitWithCustomUrlSessionThenKeepSameReferenceOfUrlSession), + ("testPostWhenURLStringIsInvalidFormatThenExecuteCompletionHandlerWithInvalidURLError", + testPostWhenURLStringIsInvalidFormatThenExecuteCompletionHandlerWithInvalidURLError), + ("testPostWhenValidURLThenGenerateSuccessResult", + testPostWhenValidURLThenGenerateSuccessResult), + ("testPostWhenInvalidURLThenGenerateFailResult", + testPostWhenInvalidURLThenGenerateFailResult), + ("testPostWithBodyWhenInvalidURLThenGenerateFailResult", + testPostWithBodyWhenInvalidURLThenGenerateFailResult), + ("testPostWhenValidURLAndRequestFailsThenGenerateFailResult", + testPostWhenValidURLAndRequestFailsThenGenerateFailResult) + ] + #endif + } diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index e3fcf9a..5c5811a 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -13,7 +13,7 @@ var allTests = [ ] #if !os(Linux) -allTests.append(testCase(NetworkGetterTests.allTests)) +allTests.append(testCase(NetworkGetTests.allTests)) #endif XCTMain(allTests) From 235bc302cc57ec54302a95fd47313519912947e6 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Sun, 14 Jan 2018 23:58:22 -0200 Subject: [PATCH 03/12] Update NetworkPost adding request body --- Frisbee.xcodeproj/project.pbxproj | 12 +++++++ .../Factories/BodyBuildableFactory.swift | 7 ++++ .../Frisbee/Factories/URLRequestFactory.swift | 2 ++ .../Frisbee/Interactors/BodyBuildable.swift | 5 +++ Sources/Frisbee/Interactors/BodyBuilder.swift | 15 +++++++++ .../Frisbee/Requestables/NetworkPost.swift | 32 ++++++++++++++++--- .../IntegrationNetworkPostTests.swift | 24 ++++++++++++-- .../Requestables/NetworkPostTests.swift | 22 +++++++++++++ 8 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 Sources/Frisbee/Factories/BodyBuildableFactory.swift create mode 100644 Sources/Frisbee/Interactors/BodyBuildable.swift create mode 100644 Sources/Frisbee/Interactors/BodyBuilder.swift diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index c6db662..78e79bf 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -25,6 +25,9 @@ 3409C9E12009EFBA00353DC4 /* NetworkPost.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */; }; 3409C9E32009EFE000353DC4 /* NetworkPostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */; }; 3409C9E52009F4E900353DC4 /* IntegrationNetworkPostTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */; }; + 3409C9E7200C385100353DC4 /* BodyBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E6200C385100353DC4 /* BodyBuildable.swift */; }; + 3409C9E9200C385900353DC4 /* BodyBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E8200C385900353DC4 /* BodyBuilder.swift */; }; + 3409C9EB200C388E00353DC4 /* BodyBuildableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */; }; 3434A0B21FE7D9CC000659E5 /* URLRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */; }; 3434A0B41FE7D9FF000659E5 /* URLSessionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */; }; 3434A0B61FE7DA5A000659E5 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */; }; @@ -85,6 +88,9 @@ 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkPost.swift; sourceTree = ""; }; 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkPostTests.swift; sourceTree = ""; }; 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationNetworkPostTests.swift; sourceTree = ""; }; + 3409C9E6200C385100353DC4 /* BodyBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuildable.swift; sourceTree = ""; }; + 3409C9E8200C385900353DC4 /* BodyBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuilder.swift; sourceTree = ""; }; + 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuildableFactory.swift; sourceTree = ""; }; 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestFactory.swift; sourceTree = ""; }; 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionFactory.swift; sourceTree = ""; }; 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; @@ -152,6 +158,7 @@ 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */, 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */, 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */, + 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */, ); name = Factories; path = Sources/Frisbee/Factories; @@ -230,6 +237,8 @@ 344FC7251FE5D76B00958CE4 /* ResultGenerator.swift */, 34C52E8C20098D8D00DCD88C /* URLWithQueryBuildable.swift */, 344DD8791FFEFB120021350B /* URLWithQueryBuilder.swift */, + 3409C9E6200C385100353DC4 /* BodyBuildable.swift */, + 3409C9E8200C385900353DC4 /* BodyBuilder.swift */, ); name = Interactors; path = Sources/Frisbee/Interactors; @@ -484,13 +493,16 @@ buildActionMask = 0; files = ( 3409C9E12009EFBA00353DC4 /* NetworkPost.swift in Sources */, + 3409C9E9200C385900353DC4 /* BodyBuilder.swift in Sources */, 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */, 344FC71A1FE5B93200958CE4 /* Getable.swift in Sources */, 344DD87B1FFEFBE40021350B /* URLWithQueryBuilder.swift in Sources */, 34C52E832009844400DCD88C /* URLWithQueryBuildableFactory.swift in Sources */, 3434A0B41FE7D9FF000659E5 /* URLSessionFactory.swift in Sources */, 344FC71E1FE5BA0200958CE4 /* Result.swift in Sources */, + 3409C9E7200C385100353DC4 /* BodyBuildable.swift in Sources */, 344FC7261FE5D76B00958CE4 /* ResultGenerator.swift in Sources */, + 3409C9EB200C388E00353DC4 /* BodyBuildableFactory.swift in Sources */, 3434A0B61FE7DA5A000659E5 /* HTTPMethod.swift in Sources */, 344FC7201FE5BBFE00958CE4 /* NetworkGet.swift in Sources */, 3434A0B21FE7D9CC000659E5 /* URLRequestFactory.swift in Sources */, diff --git a/Sources/Frisbee/Factories/BodyBuildableFactory.swift b/Sources/Frisbee/Factories/BodyBuildableFactory.swift new file mode 100644 index 0000000..221a619 --- /dev/null +++ b/Sources/Frisbee/Factories/BodyBuildableFactory.swift @@ -0,0 +1,7 @@ +struct BodyBuildableFactory { + + static func make() -> BodyBuildable { + return BodyBuilder() + } + +} diff --git a/Sources/Frisbee/Factories/URLRequestFactory.swift b/Sources/Frisbee/Factories/URLRequestFactory.swift index 8552990..4feca1c 100644 --- a/Sources/Frisbee/Factories/URLRequestFactory.swift +++ b/Sources/Frisbee/Factories/URLRequestFactory.swift @@ -5,6 +5,8 @@ struct URLRequestFactory { static func make(_ httpMethod: HTTPMethod, _ url: URL) -> URLRequest { var request = URLRequest(url: url) request.httpMethod = httpMethod.rawValue + request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type") + request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Accept") return request } diff --git a/Sources/Frisbee/Interactors/BodyBuildable.swift b/Sources/Frisbee/Interactors/BodyBuildable.swift new file mode 100644 index 0000000..f4455b5 --- /dev/null +++ b/Sources/Frisbee/Interactors/BodyBuildable.swift @@ -0,0 +1,5 @@ +import Foundation + +protocol BodyBuildable { + func build(withBody body: Entity) throws -> [String: Any] +} diff --git a/Sources/Frisbee/Interactors/BodyBuilder.swift b/Sources/Frisbee/Interactors/BodyBuilder.swift new file mode 100644 index 0000000..9abc4f8 --- /dev/null +++ b/Sources/Frisbee/Interactors/BodyBuilder.swift @@ -0,0 +1,15 @@ +import Foundation + +struct BodyBuilder: BodyBuildable { + + func build(withBody body: Entity) throws -> [String: Any] { + var json: [String: Any] = [:] + + let data = try JSONEncoder().encode(body) + let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) + if let jsonDictionary = jsonObject as? [String: Any] { json = jsonDictionary } + + return json + } + +} diff --git a/Sources/Frisbee/Requestables/NetworkPost.swift b/Sources/Frisbee/Requestables/NetworkPost.swift index 323392f..a1a1b8e 100644 --- a/Sources/Frisbee/Requestables/NetworkPost.swift +++ b/Sources/Frisbee/Requestables/NetworkPost.swift @@ -3,13 +3,19 @@ import Foundation public final class NetworkPost: Postable { let urlSession: URLSession + private let bodyBuilder: BodyBuildable - public init() { - self.urlSession = URLSessionFactory.make() + public convenience init() { + self.init(urlSession: URLSessionFactory.make(), bodyBuilder: BodyBuildableFactory.make()) } - public init(urlSession: URLSession) { + public convenience init(urlSession: URLSession) { + self.init(urlSession: urlSession, bodyBuilder: BodyBuildableFactory.make()) + } + + init(urlSession: URLSession, bodyBuilder: BodyBuildable) { self.urlSession = urlSession + self.bodyBuilder = bodyBuilder } public func post(url: String, onComplete: @escaping (Result) -> Void) { @@ -28,17 +34,33 @@ public final class NetworkPost: Postable { guard let url = URL(string: url) else { return onComplete(.fail(FrisbeeError.invalidUrl)) } - makeRequest(url: url, onComplete: onComplete) + makeRequest(url: url, body: body, onComplete: onComplete) } public func post(url: URL, body: Body, onComplete: @escaping (Result) -> Void) { - makeRequest(url: url, onComplete: onComplete) + makeRequest(url: url, body: body, onComplete: onComplete) } private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { let request = URLRequestFactory.make(.POST, url) + runTask(with: request, onComplete: onComplete) + } + + private func makeRequest(url: URL, body: Body, + onComplete: @escaping (Result) -> Void) { + var request = URLRequestFactory.make(.POST, url) + do { + let bodyObject = try bodyBuilder.build(withBody: body) + request.httpBody = try JSONSerialization.data(withJSONObject: bodyObject, options: []) + } catch { + return onComplete(.fail(FrisbeeError(error))) + } + + runTask(with: request, onComplete: onComplete) + } + private func runTask(with request: URLRequest, onComplete: @escaping (Result) -> Void) { let task = urlSession.dataTask(with: request) { data, _, error in onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) } diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift index f2b18b3..0d8d2e8 100644 --- a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift +++ b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift @@ -3,12 +3,13 @@ import Frisbee final class IntegrationNetworkPostTests: XCTestCase { - struct Json: Decodable { + struct Json: Codable { + let content: String let url: String } func testPostWhenHasValidURLThenRequestAndTransformData() { - let url = URL(string: "https://httpbin.org/anything/testPostWhenHasValidURLThenRequestAndTransformData")! + let url = URL(string: "https://putsreq.com/RrJlwsma8cM8TjC1ipmB")! let longRunningExpectation = expectation(description: "RequestMoviesWithSuccess") let expectedUrlAtResponse = url.absoluteString var returnedData: Json? @@ -21,6 +22,25 @@ final class IntegrationNetworkPostTests: XCTestCase { waitForExpectations(timeout: 20) { expectationError in XCTAssertNil(expectationError, expectationError!.localizedDescription) XCTAssertEqual(returnedData?.url, expectedUrlAtResponse) + XCTAssertEqual(returnedData?.content, "content") + } + } + + func testPostWhenHasValidURLAndWithBodyThenRequestAndTransformData() { + let url = URL(string: "https://putsreq.com/RrJlwsma8cM8TjC1ipmB")! + let longRunningExpectation = expectation(description: "RequestMoviesWithSuccess") + var returnedData: Json? + let body = Json(content: #function, url: url.absoluteString) + + NetworkPost().post(url: url, body: body) { (result: Result) in + returnedData = result.data + longRunningExpectation.fulfill() + } + + waitForExpectations(timeout: 20) { expectationError in + XCTAssertNil(expectationError, expectationError!.localizedDescription) + XCTAssertEqual(returnedData?.url, body.url) + XCTAssertEqual(returnedData?.content, body.content) } } diff --git a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift index 7f06351..fdaa94a 100644 --- a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift +++ b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift @@ -68,6 +68,18 @@ final class NetworkPostTests: XCTestCase { XCTAssertNil(generatedResult.data) } + func testPostWithBodyWhenBodyBuilderThrowAnErrorThenGenerateFailResult() { + let session = MockURLSession(results: []) + let networkPost = NetworkPost(urlSession: session, bodyBuilder: BodyStubBuilder()) + let body = Empty() + var generatedResult: Result! + + networkPost.post(url: validUrlString, body: body) { generatedResult = $0 } + + XCTAssertEqual(generatedResult.error, .invalidEntity) + XCTAssertNil(generatedResult.data) + } + func testPostWhenValidURLAndRequestFailsThenGenerateFailResult() { let session = MockURLSession(results: [.error(SomeError.some)]) let networkPost = NetworkPost(urlSession: session) @@ -90,9 +102,19 @@ final class NetworkPostTests: XCTestCase { testPostWhenInvalidURLThenGenerateFailResult), ("testPostWithBodyWhenInvalidURLThenGenerateFailResult", testPostWithBodyWhenInvalidURLThenGenerateFailResult), + ("testPostWithBodyWhenBodyBuilderThrowAnErrorThenGenerateFailResult", + testPostWithBodyWhenBodyBuilderThrowAnErrorThenGenerateFailResult), ("testPostWhenValidURLAndRequestFailsThenGenerateFailResult", testPostWhenValidURLAndRequestFailsThenGenerateFailResult) ] #endif } + +struct BodyStubBuilder: BodyBuildable { + var errorToThrow = FrisbeeError.invalidEntity + + func build(withBody body: Entity) throws -> [String: Any] { + throw errorToThrow + } +} From ec051d984b13dba9ab3f9f22388463454d0ff389 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Sun, 14 Jan 2018 23:59:31 -0200 Subject: [PATCH 04/12] Update linux main --- Tests/LinuxMain.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 5c5811a..10dc88f 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -13,6 +13,7 @@ var allTests = [ ] #if !os(Linux) +allTests.append(testCase(NetworkPostTests.allTests)) allTests.append(testCase(NetworkGetTests.allTests)) #endif From 56f95cf2ea9c0b1f8e8d38e11349495e2c61b972 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 00:01:50 -0200 Subject: [PATCH 05/12] Update linux main --- .../Integration/IntegrationNetworkPostTests.swift | 7 +++++++ Tests/LinuxMain.swift | 1 + 2 files changed, 8 insertions(+) diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift index 0d8d2e8..37f7e91 100644 --- a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift +++ b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift @@ -44,4 +44,11 @@ final class IntegrationNetworkPostTests: XCTestCase { } } + static var allTests = [ + ("testPostWhenHasValidURLThenRequestAndTransformData", + testPostWhenHasValidURLThenRequestAndTransformData), + ("testPostWhenHasValidURLAndWithBodyThenRequestAndTransformData", + testPostWhenHasValidURLAndWithBodyThenRequestAndTransformData) + ] + } diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 10dc88f..b9073b8 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -3,6 +3,7 @@ import XCTest var allTests = [ testCase(IntegrationNetworkGetTests.allTests), + testCase(IntegrationNetworkPostTests.allTests), testCase(URLSessionFactoryTests.allTests), testCase(URLRequestFactoryTests.allTests), testCase(QueryItemBuilderTests.allTests), From fa57a11b48e8f3882ddfd0c3047ccff62f5cab56 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 09:32:10 -0200 Subject: [PATCH 06/12] Update file paths + Extract some test doubles --- Frisbee.xcodeproj/project.pbxproj | 93 +++++++++++++------ .../Interactors/ResultGeneratorTests.swift | 15 +-- .../Requestables/NetworkGetTests.swift | 14 +-- .../Requestables/NetworkPostTests.swift | 10 +- .../Doubles/BodyThrowErrorFakeBuilder.swift | 10 ++ .../FrisbeeThrowErrorFakeDecodable.swift | 11 +++ .../Doubles}/MockURLSession.swift | 0 ...URLWithQueryTrhrowErrorFakeBuildable.swift | 14 +++ .../Helpers => Support/Entities}/Empty.swift | 0 Tests/Support/Entities/Fake.swift | 5 + .../Helpers => Support/Entities}/Movie.swift | 0 .../Entities}/MovieQuery.swift | 0 .../Entities}/SomeEntity.swift | 0 .../Entities}/SomeError.swift | 0 .../Extensions/FrisbeeError+All.swift | 0 .../Extensions/SequenceExtensions.swift | 0 .../XCTestCase+AssertContains.swift | 0 17 files changed, 108 insertions(+), 64 deletions(-) create mode 100644 Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift create mode 100644 Tests/Support/Doubles/FrisbeeThrowErrorFakeDecodable.swift rename Tests/{FrisbeeTests/Helpers => Support/Doubles}/MockURLSession.swift (100%) create mode 100644 Tests/Support/Doubles/URLWithQueryTrhrowErrorFakeBuildable.swift rename Tests/{FrisbeeTests/Helpers => Support/Entities}/Empty.swift (100%) create mode 100644 Tests/Support/Entities/Fake.swift rename Tests/{FrisbeeTests/Helpers => Support/Entities}/Movie.swift (100%) rename Tests/{FrisbeeTests/Helpers => Support/Entities}/MovieQuery.swift (100%) rename Tests/{FrisbeeTests/Helpers => Support/Entities}/SomeEntity.swift (100%) rename Tests/{FrisbeeTests/Helpers => Support/Entities}/SomeError.swift (100%) rename Tests/{FrisbeeTests => Support}/Extensions/FrisbeeError+All.swift (100%) rename Tests/{FrisbeeTests => Support}/Extensions/SequenceExtensions.swift (100%) rename Tests/{FrisbeeTests => Support}/Extensions/XCTestCase+AssertContains.swift (100%) diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index 78e79bf..047111b 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -28,12 +28,22 @@ 3409C9E7200C385100353DC4 /* BodyBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E6200C385100353DC4 /* BodyBuildable.swift */; }; 3409C9E9200C385900353DC4 /* BodyBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9E8200C385900353DC4 /* BodyBuilder.swift */; }; 3409C9EB200C388E00353DC4 /* BodyBuildableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */; }; + 3409C9EE200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9ED200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift */; }; + 3409C9F0200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9EF200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift */; }; + 3409C9F2200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3409C9F1200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift */; }; 3434A0B21FE7D9CC000659E5 /* URLRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */; }; 3434A0B41FE7D9FF000659E5 /* URLSessionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */; }; 3434A0B61FE7DA5A000659E5 /* HTTPMethod.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */; }; 3434A0BA1FE7DC30000659E5 /* URLRequestFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0B81FE7DBC4000659E5 /* URLRequestFactoryTests.swift */; }; 3434A0BC1FE7DD74000659E5 /* URLSessionFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0BB1FE7DD74000659E5 /* URLSessionFactoryTests.swift */; }; 3434A0BF1FE7E025000659E5 /* IntegrationNetworkGetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3434A0BE1FE7E025000659E5 /* IntegrationNetworkGetTests.swift */; }; + 343ECBA5200CC90500320259 /* Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB9D200CC90100320259 /* Empty.swift */; }; + 343ECBA6200CC90500320259 /* Fake.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB9A200CC90000320259 /* Fake.swift */; }; + 343ECBA7200CC90500320259 /* Movie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB99200CC90000320259 /* Movie.swift */; }; + 343ECBA8200CC90500320259 /* MovieQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB9C200CC90100320259 /* MovieQuery.swift */; }; + 343ECBA9200CC90500320259 /* SomeEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB9E200CC90100320259 /* SomeEntity.swift */; }; + 343ECBAA200CC90500320259 /* SomeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECB9B200CC90100320259 /* SomeError.swift */; }; + 343ECBAC200CC93D00320259 /* LinuxMain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 343ECBAB200CC93D00320259 /* LinuxMain.swift */; }; 344DD87B1FFEFBE40021350B /* URLWithQueryBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344DD8791FFEFB120021350B /* URLWithQueryBuilder.swift */; }; 344DD87D1FFEFC910021350B /* URLWithQueryBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344DD87C1FFEFC910021350B /* URLWithQueryBuilderTests.swift */; }; 344FC71A1FE5B93200958CE4 /* Getable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7191FE5B93200958CE4 /* Getable.swift */; }; @@ -48,19 +58,14 @@ 34C52E8920098A3100DCD88C /* FrisbeeDecodableFacotry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8820098A3100DCD88C /* FrisbeeDecodableFacotry.swift */; }; 34C52E8B20098D4100DCD88C /* FrisbeeJSONDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8A20098D4100DCD88C /* FrisbeeJSONDecoder.swift */; }; 34C52E8D20098D8D00DCD88C /* URLWithQueryBuildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8C20098D8D00DCD88C /* URLWithQueryBuildable.swift */; }; - 34F91DA32008219600FFAE20 /* Movie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F91DA12008217500FFAE20 /* Movie.swift */; }; 34F91DA6200821B900FFAE20 /* XCTestCase+AssertContains.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F91DA4200821A500FFAE20 /* XCTestCase+AssertContains.swift */; }; 34F91DA9200822F500FFAE20 /* FrisbeeError+All.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F91DA7200822E000FFAE20 /* FrisbeeError+All.swift */; }; - 34F91DAC200823FA00FFAE20 /* SomeEntity.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F91DAB200823FA00FFAE20 /* SomeEntity.swift */; }; - 34F91DAE2008246700FFAE20 /* MovieQuery.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F91DAD2008246700FFAE20 /* MovieQuery.swift */; }; 34F9C72A1FE89EF5002C1EB0 /* QueryItemBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F9C7291FE89EF5002C1EB0 /* QueryItemBuilderTests.swift */; }; 34F9C72C1FE89F44002C1EB0 /* QueryItemBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F9C72B1FE89F44002C1EB0 /* QueryItemBuilder.swift */; }; 578D2CA3200199A500EE3865 /* FrisbeeErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578D2CA2200199A500EE3865 /* FrisbeeErrorTests.swift */; }; 578D2CA520019B1400EE3865 /* ResultTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578D2CA420019B1400EE3865 /* ResultTests.swift */; }; 578D2CA720019C3D00EE3865 /* SequenceExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 578D2CA620019C3D00EE3865 /* SequenceExtensions.swift */; }; - 579F534B200151B700E9996A /* Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579F5349200151B300E9996A /* Empty.swift */; }; 579F534E200151DF00E9996A /* MockURLSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579F534C200151D700E9996A /* MockURLSession.swift */; }; - 579F53512001525100E9996A /* SomeError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 579F534F2001521300E9996A /* SomeError.swift */; }; OBJ_21 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; OBJ_27 /* NetworkGetTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* NetworkGetTests.swift */; }; OBJ_29 /* Frisbee.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = "Frisbee::Frisbee::Product" /* Frisbee.framework */; }; @@ -91,12 +96,22 @@ 3409C9E6200C385100353DC4 /* BodyBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuildable.swift; sourceTree = ""; }; 3409C9E8200C385900353DC4 /* BodyBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuilder.swift; sourceTree = ""; }; 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuildableFactory.swift; sourceTree = ""; }; + 3409C9ED200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyThrowErrorFakeBuilder.swift; sourceTree = ""; }; + 3409C9EF200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeThrowErrorFakeDecodable.swift; sourceTree = ""; }; + 3409C9F1200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryTrhrowErrorFakeBuildable.swift; sourceTree = ""; }; 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestFactory.swift; sourceTree = ""; }; 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionFactory.swift; sourceTree = ""; }; 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = ""; }; 3434A0B81FE7DBC4000659E5 /* URLRequestFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLRequestFactoryTests.swift; sourceTree = ""; }; 3434A0BB1FE7DD74000659E5 /* URLSessionFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionFactoryTests.swift; sourceTree = ""; }; 3434A0BE1FE7E025000659E5 /* IntegrationNetworkGetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationNetworkGetTests.swift; sourceTree = ""; }; + 343ECB99200CC90000320259 /* Movie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Movie.swift; path = Tests/Support/Entities/Movie.swift; sourceTree = SOURCE_ROOT; }; + 343ECB9A200CC90000320259 /* Fake.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Fake.swift; path = Tests/Support/Entities/Fake.swift; sourceTree = SOURCE_ROOT; }; + 343ECB9B200CC90100320259 /* SomeError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SomeError.swift; path = Tests/Support/Entities/SomeError.swift; sourceTree = SOURCE_ROOT; }; + 343ECB9C200CC90100320259 /* MovieQuery.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MovieQuery.swift; path = Tests/Support/Entities/MovieQuery.swift; sourceTree = SOURCE_ROOT; }; + 343ECB9D200CC90100320259 /* Empty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Empty.swift; path = Tests/Support/Entities/Empty.swift; sourceTree = SOURCE_ROOT; }; + 343ECB9E200CC90100320259 /* SomeEntity.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SomeEntity.swift; path = Tests/Support/Entities/SomeEntity.swift; sourceTree = SOURCE_ROOT; }; + 343ECBAB200CC93D00320259 /* LinuxMain.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = Tests/LinuxMain.swift; sourceTree = SOURCE_ROOT; }; 344DD8791FFEFB120021350B /* URLWithQueryBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuilder.swift; sourceTree = ""; }; 344DD87C1FFEFC910021350B /* URLWithQueryBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuilderTests.swift; sourceTree = ""; }; 344FC7191FE5B93200958CE4 /* Getable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Getable.swift; sourceTree = ""; }; @@ -111,20 +126,14 @@ 34C52E8820098A3100DCD88C /* FrisbeeDecodableFacotry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeDecodableFacotry.swift; sourceTree = ""; }; 34C52E8A20098D4100DCD88C /* FrisbeeJSONDecoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeJSONDecoder.swift; sourceTree = ""; }; 34C52E8C20098D8D00DCD88C /* URLWithQueryBuildable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuildable.swift; sourceTree = ""; }; - 34F91DA12008217500FFAE20 /* Movie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Movie.swift; sourceTree = ""; }; 34F91DA4200821A500FFAE20 /* XCTestCase+AssertContains.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "XCTestCase+AssertContains.swift"; sourceTree = ""; }; 34F91DA7200822E000FFAE20 /* FrisbeeError+All.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FrisbeeError+All.swift"; sourceTree = ""; }; - 34F91DAA2008239600FFAE20 /* LinuxMain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = LinuxMain.swift; path = Tests/LinuxMain.swift; sourceTree = ""; }; - 34F91DAB200823FA00FFAE20 /* SomeEntity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeEntity.swift; sourceTree = ""; }; - 34F91DAD2008246700FFAE20 /* MovieQuery.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieQuery.swift; sourceTree = ""; }; 34F9C7291FE89EF5002C1EB0 /* QueryItemBuilderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryItemBuilderTests.swift; sourceTree = ""; }; 34F9C72B1FE89F44002C1EB0 /* QueryItemBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueryItemBuilder.swift; sourceTree = ""; }; 578D2CA2200199A500EE3865 /* FrisbeeErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeErrorTests.swift; sourceTree = ""; }; 578D2CA420019B1400EE3865 /* ResultTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultTests.swift; sourceTree = ""; }; 578D2CA620019C3D00EE3865 /* SequenceExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SequenceExtensions.swift; sourceTree = ""; }; - 579F5349200151B300E9996A /* Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Empty.swift; sourceTree = ""; }; 579F534C200151D700E9996A /* MockURLSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockURLSession.swift; sourceTree = ""; }; - 579F534F2001521300E9996A /* SomeError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeError.swift; sourceTree = ""; }; "Frisbee::Frisbee::Product" /* Frisbee.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Frisbee.framework; sourceTree = BUILT_PRODUCTS_DIR; }; "Frisbee::FrisbeeTests::Product" /* FrisbeeTests.xctest */ = {isa = PBXFileReference; lastKnownFileType = file; path = FrisbeeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; OBJ_12 /* NetworkGetTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkGetTests.swift; sourceTree = ""; }; @@ -150,6 +159,32 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 3409C9EC200CC60300353DC4 /* Doubles */ = { + isa = PBXGroup; + children = ( + 579F534C200151D700E9996A /* MockURLSession.swift */, + 3409C9ED200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift */, + 3409C9EF200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift */, + 3409C9F1200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift */, + ); + name = Doubles; + path = Tests/Support/Doubles; + sourceTree = SOURCE_ROOT; + }; + 3409C9F5200CC7CD00353DC4 /* Entities */ = { + isa = PBXGroup; + children = ( + 343ECB9D200CC90100320259 /* Empty.swift */, + 343ECB9A200CC90000320259 /* Fake.swift */, + 343ECB99200CC90000320259 /* Movie.swift */, + 343ECB9C200CC90100320259 /* MovieQuery.swift */, + 343ECB9E200CC90100320259 /* SomeEntity.swift */, + 343ECB9B200CC90100320259 /* SomeError.swift */, + ); + name = Entities; + path = Tests/Support/Entities; + sourceTree = SOURCE_ROOT; + }; 3434A0AF1FE7D912000659E5 /* Factories */ = { isa = PBXGroup; children = ( @@ -192,7 +227,7 @@ 34F91DA7200822E000FFAE20 /* FrisbeeError+All.swift */, ); name = Extensions; - path = Tests/FrisbeeTests/Extensions; + path = Tests/Support/Extensions; sourceTree = SOURCE_ROOT; }; 344FC7301FE5DB7700958CE4 /* Requestables */ = { @@ -265,23 +300,22 @@ path = Tests/FrisbeeTests/Entities; sourceTree = SOURCE_ROOT; }; - 579F5348200151A300E9996A /* Helpers */ = { + 579F5348200151A300E9996A /* Support */ = { isa = PBXGroup; children = ( - 579F5349200151B300E9996A /* Empty.swift */, - 579F534C200151D700E9996A /* MockURLSession.swift */, - 579F534F2001521300E9996A /* SomeError.swift */, - 34F91DA12008217500FFAE20 /* Movie.swift */, - 34F91DAB200823FA00FFAE20 /* SomeEntity.swift */, - 34F91DAD2008246700FFAE20 /* MovieQuery.swift */, + 343ECBAB200CC93D00320259 /* LinuxMain.swift */, + 344FC7211FE5BDAE00958CE4 /* Extensions */, + 3409C9EC200CC60300353DC4 /* Doubles */, + 3409C9F5200CC7CD00353DC4 /* Entities */, ); - path = Helpers; + name = Support; + path = Tests/Support; sourceTree = ""; }; OBJ_10 /* Tests */ = { isa = PBXGroup; children = ( - 34F91DAA2008239600FFAE20 /* LinuxMain.swift */, + 579F5348200151A300E9996A /* Support */, OBJ_11 /* FrisbeeTests */, ); name = Tests; @@ -291,9 +325,7 @@ isa = PBXGroup; children = ( 578D2CA12001998500EE3865 /* Entities */, - 344FC7211FE5BDAE00958CE4 /* Extensions */, 3434A0B71FE7DBA8000659E5 /* Factories */, - 579F5348200151A300E9996A /* Helpers */, 3434A0BD1FE7DFEF000659E5 /* Integration */, 34F9C7241FE895F6002C1EB0 /* Interactors */, 344FC7321FE5DFD400958CE4 /* Requestables */, @@ -458,6 +490,7 @@ buildActionMask = 0; files = ( OBJ_21 /* Package.swift in Sources */, + 343ECBAC200CC93D00320259 /* LinuxMain.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -465,26 +498,30 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( - 34F91DA32008219600FFAE20 /* Movie.swift in Sources */, 578D2CA520019B1400EE3865 /* ResultTests.swift in Sources */, 579F534E200151DF00E9996A /* MockURLSession.swift in Sources */, 3409C9E32009EFE000353DC4 /* NetworkPostTests.swift in Sources */, 578D2CA720019C3D00EE3865 /* SequenceExtensions.swift in Sources */, - 34F91DAC200823FA00FFAE20 /* SomeEntity.swift in Sources */, 3434A0BF1FE7E025000659E5 /* IntegrationNetworkGetTests.swift in Sources */, 3434A0BA1FE7DC30000659E5 /* URLRequestFactoryTests.swift in Sources */, - 579F53512001525100E9996A /* SomeError.swift in Sources */, 3409C9E52009F4E900353DC4 /* IntegrationNetworkPostTests.swift in Sources */, + 3409C9F2200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift in Sources */, 344FC7291FE5D7FC00958CE4 /* ResultGeneratorTests.swift in Sources */, 344DD87D1FFEFC910021350B /* URLWithQueryBuilderTests.swift in Sources */, + 343ECBA5200CC90500320259 /* Empty.swift in Sources */, + 343ECBA8200CC90500320259 /* MovieQuery.swift in Sources */, + 3409C9EE200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift in Sources */, + 343ECBA9200CC90500320259 /* SomeEntity.swift in Sources */, OBJ_27 /* NetworkGetTests.swift in Sources */, - 34F91DAE2008246700FFAE20 /* MovieQuery.swift in Sources */, 34F9C72A1FE89EF5002C1EB0 /* QueryItemBuilderTests.swift in Sources */, + 343ECBAA200CC90500320259 /* SomeError.swift in Sources */, + 343ECBA7200CC90500320259 /* Movie.swift in Sources */, 34F91DA6200821B900FFAE20 /* XCTestCase+AssertContains.swift in Sources */, - 579F534B200151B700E9996A /* Empty.swift in Sources */, 3434A0BC1FE7DD74000659E5 /* URLSessionFactoryTests.swift in Sources */, + 343ECBA6200CC90500320259 /* Fake.swift in Sources */, 578D2CA3200199A500EE3865 /* FrisbeeErrorTests.swift in Sources */, 34F91DA9200822F500FFAE20 /* FrisbeeError+All.swift in Sources */, + 3409C9F0200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/FrisbeeTests/Interactors/ResultGeneratorTests.swift b/Tests/FrisbeeTests/Interactors/ResultGeneratorTests.swift index 5f9e155..7d08e5a 100644 --- a/Tests/FrisbeeTests/Interactors/ResultGeneratorTests.swift +++ b/Tests/FrisbeeTests/Interactors/ResultGeneratorTests.swift @@ -1,27 +1,14 @@ import XCTest @testable import Frisbee -struct Fake: Codable { let fake: String } - -class FrisbeeStubDecodable: FrisbeeDecodable { - var error: FrisbeeError! - - func decode(_ type: T.Type, from data: Data) throws -> T { - throw error - } - -} - final class ResultGeneratorTests: XCTestCase { private let someError = NSError(domain: "Some error", code: 33, userInfo: nil) private let fakeString = "Fake Fake" func testGenerateResultWhenEncoderTrhowAnerrorThenGenerateFailResult() { - let frisbeDecoder = FrisbeeStubDecodable() - frisbeDecoder.error = .invalidEntity let data = try? JSONEncoder().encode(Fake(fake: fakeString)) - let resultGenerator = ResultGenerator(decoder: frisbeDecoder) + let resultGenerator = ResultGenerator(decoder: FrisbeeThrowErrorFakeDecodable()) let result = resultGenerator.generate(data: data, error: nil) diff --git a/Tests/FrisbeeTests/Requestables/NetworkGetTests.swift b/Tests/FrisbeeTests/Requestables/NetworkGetTests.swift index 73ff909..a150bf2 100644 --- a/Tests/FrisbeeTests/Requestables/NetworkGetTests.swift +++ b/Tests/FrisbeeTests/Requestables/NetworkGetTests.swift @@ -1,18 +1,6 @@ import XCTest @testable import Frisbee -class URLWithQueryStubBuildable: URLWithQueryBuildable { - var errorToThrow: FrisbeeError! - - func build(withUrl url: String, query: Query) throws -> URL { - throw errorToThrow - } - - func build(withUrl url: URL, query: Query) throws -> URL { - throw errorToThrow - } -} - final class NetworkGetTests: XCTestCase { private let invalidUrlString = "🤷‍♂️" @@ -22,7 +10,7 @@ final class NetworkGetTests: XCTestCase { func testGetWhenThrowsAnErrorAtQueryBuilderThenGenerateFailResult() { let session = MockURLSession(results: [.error(SomeError.some)]) - let urlQueryBuilder = URLWithQueryStubBuildable() + let urlQueryBuilder = URLWithQueryTrhrowErrorFakeBuildable() urlQueryBuilder.errorToThrow = .invalidEntity let query = Empty() let getter = NetworkGet(queryBuildable: urlQueryBuilder, urlSession: session) diff --git a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift index fdaa94a..9f0fe37 100644 --- a/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift +++ b/Tests/FrisbeeTests/Requestables/NetworkPostTests.swift @@ -70,7 +70,7 @@ final class NetworkPostTests: XCTestCase { func testPostWithBodyWhenBodyBuilderThrowAnErrorThenGenerateFailResult() { let session = MockURLSession(results: []) - let networkPost = NetworkPost(urlSession: session, bodyBuilder: BodyStubBuilder()) + let networkPost = NetworkPost(urlSession: session, bodyBuilder: BodyThrowErrorFakeBuilder()) let body = Empty() var generatedResult: Result! @@ -110,11 +110,3 @@ final class NetworkPostTests: XCTestCase { #endif } - -struct BodyStubBuilder: BodyBuildable { - var errorToThrow = FrisbeeError.invalidEntity - - func build(withBody body: Entity) throws -> [String: Any] { - throw errorToThrow - } -} diff --git a/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift b/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift new file mode 100644 index 0000000..130e9a0 --- /dev/null +++ b/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift @@ -0,0 +1,10 @@ +import Foundation +@testable import Frisbee + +struct BodyThrowErrorFakeBuilder: BodyBuildable { + private let errorToThrow = FrisbeeError.invalidEntity + + func build(withBody body: Entity) throws -> [String: Any] { + throw errorToThrow + } +} diff --git a/Tests/Support/Doubles/FrisbeeThrowErrorFakeDecodable.swift b/Tests/Support/Doubles/FrisbeeThrowErrorFakeDecodable.swift new file mode 100644 index 0000000..e62a0ea --- /dev/null +++ b/Tests/Support/Doubles/FrisbeeThrowErrorFakeDecodable.swift @@ -0,0 +1,11 @@ +import Foundation +@testable import Frisbee + +class FrisbeeThrowErrorFakeDecodable: FrisbeeDecodable { + private let error = FrisbeeError.invalidEntity + + func decode(_ type: T.Type, from data: Data) throws -> T { + throw error + } + +} diff --git a/Tests/FrisbeeTests/Helpers/MockURLSession.swift b/Tests/Support/Doubles/MockURLSession.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/MockURLSession.swift rename to Tests/Support/Doubles/MockURLSession.swift diff --git a/Tests/Support/Doubles/URLWithQueryTrhrowErrorFakeBuildable.swift b/Tests/Support/Doubles/URLWithQueryTrhrowErrorFakeBuildable.swift new file mode 100644 index 0000000..994963e --- /dev/null +++ b/Tests/Support/Doubles/URLWithQueryTrhrowErrorFakeBuildable.swift @@ -0,0 +1,14 @@ +import Foundation +@testable import Frisbee + +class URLWithQueryTrhrowErrorFakeBuildable: URLWithQueryBuildable { + var errorToThrow: FrisbeeError! + + func build(withUrl url: String, query: Query) throws -> URL { + throw errorToThrow + } + + func build(withUrl url: URL, query: Query) throws -> URL { + throw errorToThrow + } +} diff --git a/Tests/FrisbeeTests/Helpers/Empty.swift b/Tests/Support/Entities/Empty.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/Empty.swift rename to Tests/Support/Entities/Empty.swift diff --git a/Tests/Support/Entities/Fake.swift b/Tests/Support/Entities/Fake.swift new file mode 100644 index 0000000..dfc30e9 --- /dev/null +++ b/Tests/Support/Entities/Fake.swift @@ -0,0 +1,5 @@ +import Foundation + +struct Fake: Codable { + let fake: String +} diff --git a/Tests/FrisbeeTests/Helpers/Movie.swift b/Tests/Support/Entities/Movie.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/Movie.swift rename to Tests/Support/Entities/Movie.swift diff --git a/Tests/FrisbeeTests/Helpers/MovieQuery.swift b/Tests/Support/Entities/MovieQuery.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/MovieQuery.swift rename to Tests/Support/Entities/MovieQuery.swift diff --git a/Tests/FrisbeeTests/Helpers/SomeEntity.swift b/Tests/Support/Entities/SomeEntity.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/SomeEntity.swift rename to Tests/Support/Entities/SomeEntity.swift diff --git a/Tests/FrisbeeTests/Helpers/SomeError.swift b/Tests/Support/Entities/SomeError.swift similarity index 100% rename from Tests/FrisbeeTests/Helpers/SomeError.swift rename to Tests/Support/Entities/SomeError.swift diff --git a/Tests/FrisbeeTests/Extensions/FrisbeeError+All.swift b/Tests/Support/Extensions/FrisbeeError+All.swift similarity index 100% rename from Tests/FrisbeeTests/Extensions/FrisbeeError+All.swift rename to Tests/Support/Extensions/FrisbeeError+All.swift diff --git a/Tests/FrisbeeTests/Extensions/SequenceExtensions.swift b/Tests/Support/Extensions/SequenceExtensions.swift similarity index 100% rename from Tests/FrisbeeTests/Extensions/SequenceExtensions.swift rename to Tests/Support/Extensions/SequenceExtensions.swift diff --git a/Tests/FrisbeeTests/Extensions/XCTestCase+AssertContains.swift b/Tests/Support/Extensions/XCTestCase+AssertContains.swift similarity index 100% rename from Tests/FrisbeeTests/Extensions/XCTestCase+AssertContains.swift rename to Tests/Support/Extensions/XCTestCase+AssertContains.swift From 60d9efbf90341d1eed80d6f06ef8053ec47c6684 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 10:04:36 -0200 Subject: [PATCH 07/12] Update test assert --- .../FrisbeeTests/Integration/IntegrationNetworkPostTests.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift index 37f7e91..d4e0c60 100644 --- a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift +++ b/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift @@ -11,7 +11,6 @@ final class IntegrationNetworkPostTests: XCTestCase { func testPostWhenHasValidURLThenRequestAndTransformData() { let url = URL(string: "https://putsreq.com/RrJlwsma8cM8TjC1ipmB")! let longRunningExpectation = expectation(description: "RequestMoviesWithSuccess") - let expectedUrlAtResponse = url.absoluteString var returnedData: Json? NetworkPost().post(url: url) { (result: Result) in @@ -21,7 +20,7 @@ final class IntegrationNetworkPostTests: XCTestCase { waitForExpectations(timeout: 20) { expectationError in XCTAssertNil(expectationError, expectationError!.localizedDescription) - XCTAssertEqual(returnedData?.url, expectedUrlAtResponse) + XCTAssertEqual(returnedData?.url, url.absoluteString) XCTAssertEqual(returnedData?.content, "content") } } From f23978fcf55e37aa81803f0b3c8cc989b7197e76 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 10:05:18 -0200 Subject: [PATCH 08/12] Move integration tests to Requestables folder --- Frisbee.xcodeproj/project.pbxproj | 13 ++----------- .../IntegrationNetworkGetTests.swift | 0 .../IntegrationNetworkPostTests.swift | 0 3 files changed, 2 insertions(+), 11 deletions(-) rename Tests/FrisbeeTests/{Integration => Requestables}/IntegrationNetworkGetTests.swift (100%) rename Tests/FrisbeeTests/{Integration => Requestables}/IntegrationNetworkPostTests.swift (100%) diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index 047111b..dfe859e 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -209,16 +209,6 @@ path = Tests/FrisbeeTests/Factories; sourceTree = SOURCE_ROOT; }; - 3434A0BD1FE7DFEF000659E5 /* Integration */ = { - isa = PBXGroup; - children = ( - 3434A0BE1FE7E025000659E5 /* IntegrationNetworkGetTests.swift */, - 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */, - ); - name = Integration; - path = Tests/FrisbeeTests/Integration; - sourceTree = SOURCE_ROOT; - }; 344FC7211FE5BDAE00958CE4 /* Extensions */ = { isa = PBXGroup; children = ( @@ -258,6 +248,8 @@ 344FC7321FE5DFD400958CE4 /* Requestables */ = { isa = PBXGroup; children = ( + 3434A0BE1FE7E025000659E5 /* IntegrationNetworkGetTests.swift */, + 3409C9E42009F4E900353DC4 /* IntegrationNetworkPostTests.swift */, OBJ_12 /* NetworkGetTests.swift */, 3409C9E22009EFE000353DC4 /* NetworkPostTests.swift */, ); @@ -326,7 +318,6 @@ children = ( 578D2CA12001998500EE3865 /* Entities */, 3434A0B71FE7DBA8000659E5 /* Factories */, - 3434A0BD1FE7DFEF000659E5 /* Integration */, 34F9C7241FE895F6002C1EB0 /* Interactors */, 344FC7321FE5DFD400958CE4 /* Requestables */, ); diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkGetTests.swift b/Tests/FrisbeeTests/Requestables/IntegrationNetworkGetTests.swift similarity index 100% rename from Tests/FrisbeeTests/Integration/IntegrationNetworkGetTests.swift rename to Tests/FrisbeeTests/Requestables/IntegrationNetworkGetTests.swift diff --git a/Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift b/Tests/FrisbeeTests/Requestables/IntegrationNetworkPostTests.swift similarity index 100% rename from Tests/FrisbeeTests/Integration/IntegrationNetworkPostTests.swift rename to Tests/FrisbeeTests/Requestables/IntegrationNetworkPostTests.swift From df706c4a652f3f72a2d1a89cb9b0f69d1fcd2b75 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 10:24:18 -0200 Subject: [PATCH 09/12] Create OnComplete typealias + Replace generic types placeholder --- Frisbee.xcodeproj/project.pbxproj | 4 ++++ Sources/Frisbee/Entities/Result.swift | 8 ++++---- .../Factories/ResultGeneratorFactory.swift | 2 +- Sources/Frisbee/Interactors/BodyBuildable.swift | 2 +- Sources/Frisbee/Interactors/BodyBuilder.swift | 2 +- .../Frisbee/Interactors/QueryItemBuilder.swift | 4 ++-- .../Frisbee/Interactors/ResultGenerator.swift | 8 ++++---- .../Interactors/URLWithQueryBuildable.swift | 4 ++-- .../Interactors/URLWithQueryBuilder.swift | 4 ++-- Sources/Frisbee/Requestables/Getable.swift | 10 ++++------ Sources/Frisbee/Requestables/NetworkGet.swift | 12 +++++------- Sources/Frisbee/Requestables/NetworkPost.swift | 17 +++++++---------- Sources/Frisbee/Requestables/OnComplete.swift | 1 + Sources/Frisbee/Requestables/Postable.swift | 10 ++++------ .../Doubles/BodyThrowErrorFakeBuilder.swift | 2 +- 15 files changed, 43 insertions(+), 47 deletions(-) create mode 100644 Sources/Frisbee/Requestables/OnComplete.swift diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index dfe859e..5f81a7f 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -52,6 +52,7 @@ 344FC7201FE5BBFE00958CE4 /* NetworkGet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC71F1FE5BBFE00958CE4 /* NetworkGet.swift */; }; 344FC7261FE5D76B00958CE4 /* ResultGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7251FE5D76B00958CE4 /* ResultGenerator.swift */; }; 344FC7291FE5D7FC00958CE4 /* ResultGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */; }; + 3473C852200CD3810014C66E /* OnComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3473C851200CD3810014C66E /* OnComplete.swift */; }; 34C52E832009844400DCD88C /* URLWithQueryBuildableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */; }; 34C52E852009895D00DCD88C /* FrisbeeDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */; }; 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */; }; @@ -120,6 +121,7 @@ 344FC71F1FE5BBFE00958CE4 /* NetworkGet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkGet.swift; sourceTree = ""; }; 344FC7251FE5D76B00958CE4 /* ResultGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGenerator.swift; sourceTree = ""; }; 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorTests.swift; sourceTree = ""; }; + 3473C851200CD3810014C66E /* OnComplete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnComplete.swift; sourceTree = ""; }; 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuildableFactory.swift; sourceTree = ""; }; 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeDecodable.swift; sourceTree = ""; }; 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorFactory.swift; sourceTree = ""; }; @@ -227,6 +229,7 @@ 344FC71F1FE5BBFE00958CE4 /* NetworkGet.swift */, 3409C9DE2009EFBA00353DC4 /* Postable.swift */, 3409C9DF2009EFBA00353DC4 /* NetworkPost.swift */, + 3473C851200CD3810014C66E /* OnComplete.swift */, ); name = Requestables; path = Sources/Frisbee/Requestables; @@ -527,6 +530,7 @@ 344DD87B1FFEFBE40021350B /* URLWithQueryBuilder.swift in Sources */, 34C52E832009844400DCD88C /* URLWithQueryBuildableFactory.swift in Sources */, 3434A0B41FE7D9FF000659E5 /* URLSessionFactory.swift in Sources */, + 3473C852200CD3810014C66E /* OnComplete.swift in Sources */, 344FC71E1FE5BA0200958CE4 /* Result.swift in Sources */, 3409C9E7200C385100353DC4 /* BodyBuildable.swift in Sources */, 344FC7261FE5D76B00958CE4 /* ResultGenerator.swift in Sources */, diff --git a/Sources/Frisbee/Entities/Result.swift b/Sources/Frisbee/Entities/Result.swift index 4aa64a6..c5a14f0 100644 --- a/Sources/Frisbee/Entities/Result.swift +++ b/Sources/Frisbee/Entities/Result.swift @@ -1,10 +1,10 @@ -public enum Result { - case success(Entity) +public enum Result { + case success(T) case fail(FrisbeeError) } extension Result { - public var data: Entity? { + public var data: T? { guard case let .success(data) = self else { return nil } @@ -30,7 +30,7 @@ extension Result: Equatable { } } -extension Result where Entity: Equatable { +extension Result where T: Equatable { public static func == (lhs: Result, rhs: Result) -> Bool { switch (lhs, rhs) { case let (.success(lhs), .success(rhs)): diff --git a/Sources/Frisbee/Factories/ResultGeneratorFactory.swift b/Sources/Frisbee/Factories/ResultGeneratorFactory.swift index 7c448d6..b2d3d9a 100644 --- a/Sources/Frisbee/Factories/ResultGeneratorFactory.swift +++ b/Sources/Frisbee/Factories/ResultGeneratorFactory.swift @@ -1,6 +1,6 @@ struct ResultGeneratorFactory { - static func make() -> ResultGenerator { + static func make() -> ResultGenerator { return ResultGenerator(decoder: FrisbeeDecodableFacotry.make()) } diff --git a/Sources/Frisbee/Interactors/BodyBuildable.swift b/Sources/Frisbee/Interactors/BodyBuildable.swift index f4455b5..3e1d5a9 100644 --- a/Sources/Frisbee/Interactors/BodyBuildable.swift +++ b/Sources/Frisbee/Interactors/BodyBuildable.swift @@ -1,5 +1,5 @@ import Foundation protocol BodyBuildable { - func build(withBody body: Entity) throws -> [String: Any] + func build(withBody body: T) throws -> [String: Any] } diff --git a/Sources/Frisbee/Interactors/BodyBuilder.swift b/Sources/Frisbee/Interactors/BodyBuilder.swift index 9abc4f8..7ee6823 100644 --- a/Sources/Frisbee/Interactors/BodyBuilder.swift +++ b/Sources/Frisbee/Interactors/BodyBuilder.swift @@ -2,7 +2,7 @@ import Foundation struct BodyBuilder: BodyBuildable { - func build(withBody body: Entity) throws -> [String: Any] { + func build(withBody body: T) throws -> [String: Any] { var json: [String: Any] = [:] let data = try JSONEncoder().encode(body) diff --git a/Sources/Frisbee/Interactors/QueryItemBuilder.swift b/Sources/Frisbee/Interactors/QueryItemBuilder.swift index dbe261e..a75fa5a 100644 --- a/Sources/Frisbee/Interactors/QueryItemBuilder.swift +++ b/Sources/Frisbee/Interactors/QueryItemBuilder.swift @@ -1,8 +1,8 @@ import Foundation -struct QueryItemBuilder { +struct QueryItemBuilder { - static func build(withEntity entity: Entity) throws -> [URLQueryItem] { + static func build(withEntity entity: T) throws -> [URLQueryItem] { var json: [String: Any] = [:] let data = try JSONEncoder().encode(entity) diff --git a/Sources/Frisbee/Interactors/ResultGenerator.swift b/Sources/Frisbee/Interactors/ResultGenerator.swift index 770c6b0..77ea1e8 100644 --- a/Sources/Frisbee/Interactors/ResultGenerator.swift +++ b/Sources/Frisbee/Interactors/ResultGenerator.swift @@ -1,6 +1,6 @@ import Foundation -struct ResultGenerator { +struct ResultGenerator { private let decoder: FrisbeeDecodable @@ -8,11 +8,11 @@ struct ResultGenerator { self.decoder = decoder } - func generate(data: Data?, error: Error?) -> Result { + func generate(data: Data?, error: Error?) -> Result { if let data = data { - let result: Result + let result: Result do { - let entityDecoded = try decoder.decode(Entity.self, from: data) + let entityDecoded = try decoder.decode(T.self, from: data) result = Result.success(entityDecoded) } catch { let noDataError = FrisbeeError.noData diff --git a/Sources/Frisbee/Interactors/URLWithQueryBuildable.swift b/Sources/Frisbee/Interactors/URLWithQueryBuildable.swift index bbaa1eb..764e944 100644 --- a/Sources/Frisbee/Interactors/URLWithQueryBuildable.swift +++ b/Sources/Frisbee/Interactors/URLWithQueryBuildable.swift @@ -1,6 +1,6 @@ import Foundation protocol URLWithQueryBuildable { - func build(withUrl url: String, query: Query) throws -> URL - func build(withUrl url: URL, query: Query) throws -> URL + func build(withUrl url: String, query: T) throws -> URL + func build(withUrl url: URL, query: T) throws -> URL } diff --git a/Sources/Frisbee/Interactors/URLWithQueryBuilder.swift b/Sources/Frisbee/Interactors/URLWithQueryBuilder.swift index 8d080f8..d39189b 100644 --- a/Sources/Frisbee/Interactors/URLWithQueryBuilder.swift +++ b/Sources/Frisbee/Interactors/URLWithQueryBuilder.swift @@ -2,14 +2,14 @@ import Foundation struct URLWithQueryBuilder: URLWithQueryBuildable { - func build(withUrl url: String, query: Query) throws -> URL { + func build(withUrl url: String, query: T) throws -> URL { guard let actualUrl = URL(string: url) else { throw FrisbeeError.invalidUrl } return try build(withUrl: actualUrl, query: query) } - func build(withUrl url: URL, query: Query) throws -> URL { + func build(withUrl url: URL, query: T) throws -> URL { var url = url var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true) urlComponents?.queryItems = try QueryItemBuilder.build(withEntity: query) diff --git a/Sources/Frisbee/Requestables/Getable.swift b/Sources/Frisbee/Requestables/Getable.swift index da2eb84..d632f22 100644 --- a/Sources/Frisbee/Requestables/Getable.swift +++ b/Sources/Frisbee/Requestables/Getable.swift @@ -1,10 +1,8 @@ import Foundation public protocol Getable { - func get(url: String, onComplete: @escaping (Result) -> Void) - func get(url: URL, onComplete: @escaping (Result) -> Void) - func get(url: String, query: Query, - onComplete: @escaping (Result) -> Void) - func get(url: URL, query: Query, - onComplete: @escaping (Result) -> Void) + func get(url: String, onComplete: @escaping OnComplete) + func get(url: URL, onComplete: @escaping OnComplete) + func get(url: String, query: U, onComplete: @escaping OnComplete) + func get(url: URL, query: U, onComplete: @escaping OnComplete) } diff --git a/Sources/Frisbee/Requestables/NetworkGet.swift b/Sources/Frisbee/Requestables/NetworkGet.swift index e682562..c73090b 100644 --- a/Sources/Frisbee/Requestables/NetworkGet.swift +++ b/Sources/Frisbee/Requestables/NetworkGet.swift @@ -21,27 +21,25 @@ public class NetworkGet: Getable { self.urlSession = urlSession } - public func get(url: String, onComplete: @escaping (Result) -> Void) { + public func get(url: String, onComplete: @escaping OnComplete) { guard let url = URL(string: url) else { return onComplete(.fail(FrisbeeError.invalidUrl)) } makeRequest(url: url, onComplete: onComplete) } - public func get(url: URL, onComplete: @escaping (Result) -> Void) { + public func get(url: URL, onComplete: @escaping OnComplete) { makeRequest(url: url, onComplete: onComplete) } - public func get(url: String, query: Query, - onComplete: @escaping (Result) -> Void) { + public func get(url: String, query: U, onComplete: @escaping OnComplete) { guard let url = URL(string: url) else { return onComplete(.fail(FrisbeeError.invalidUrl)) } get(url: url, query: query, onComplete: onComplete) } - public func get(url: URL, query: Query, - onComplete: @escaping (Result) -> Void) { + public func get(url: URL, query: U, onComplete: @escaping OnComplete) { do { let url = try queryBuilder.build(withUrl: url, query: query) makeRequest(url: url, onComplete: onComplete) @@ -50,7 +48,7 @@ public class NetworkGet: Getable { } } - private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { + private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { let request = URLRequestFactory.make(.GET, url) let task = urlSession.dataTask(with: request) { data, _, error in diff --git a/Sources/Frisbee/Requestables/NetworkPost.swift b/Sources/Frisbee/Requestables/NetworkPost.swift index a1a1b8e..499c356 100644 --- a/Sources/Frisbee/Requestables/NetworkPost.swift +++ b/Sources/Frisbee/Requestables/NetworkPost.swift @@ -18,37 +18,34 @@ public final class NetworkPost: Postable { self.bodyBuilder = bodyBuilder } - public func post(url: String, onComplete: @escaping (Result) -> Void) { + public func post(url: String, onComplete: @escaping OnComplete) { guard let url = URL(string: url) else { return onComplete(.fail(FrisbeeError.invalidUrl)) } makeRequest(url: url, onComplete: onComplete) } - public func post(url: URL, onComplete: @escaping (Result) -> Void) { + public func post(url: URL, onComplete: @escaping OnComplete) { makeRequest(url: url, onComplete: onComplete) } - public func post(url: String, body: Body, - onComplete: @escaping (Result) -> Void) { + public func post(url: String, body: U, onComplete: @escaping OnComplete) { guard let url = URL(string: url) else { return onComplete(.fail(FrisbeeError.invalidUrl)) } makeRequest(url: url, body: body, onComplete: onComplete) } - public func post(url: URL, body: Body, - onComplete: @escaping (Result) -> Void) { + public func post(url: URL, body: U, onComplete: @escaping OnComplete) { makeRequest(url: url, body: body, onComplete: onComplete) } - private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { + private func makeRequest(url: URL, onComplete: @escaping OnComplete) { let request = URLRequestFactory.make(.POST, url) runTask(with: request, onComplete: onComplete) } - private func makeRequest(url: URL, body: Body, - onComplete: @escaping (Result) -> Void) { + private func makeRequest(url: URL, body: U, onComplete: @escaping OnComplete) { var request = URLRequestFactory.make(.POST, url) do { let bodyObject = try bodyBuilder.build(withBody: body) @@ -60,7 +57,7 @@ public final class NetworkPost: Postable { runTask(with: request, onComplete: onComplete) } - private func runTask(with request: URLRequest, onComplete: @escaping (Result) -> Void) { + private func runTask(with request: URLRequest, onComplete: @escaping OnComplete) { let task = urlSession.dataTask(with: request) { data, _, error in onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) } diff --git a/Sources/Frisbee/Requestables/OnComplete.swift b/Sources/Frisbee/Requestables/OnComplete.swift new file mode 100644 index 0000000..f653dde --- /dev/null +++ b/Sources/Frisbee/Requestables/OnComplete.swift @@ -0,0 +1 @@ +public typealias OnComplete = (Result) -> Void diff --git a/Sources/Frisbee/Requestables/Postable.swift b/Sources/Frisbee/Requestables/Postable.swift index e781a68..4e8b61e 100644 --- a/Sources/Frisbee/Requestables/Postable.swift +++ b/Sources/Frisbee/Requestables/Postable.swift @@ -1,10 +1,8 @@ import Foundation protocol Postable { - func post(url: String, onComplete: @escaping (Result) -> Void) - func post(url: URL, onComplete: @escaping (Result) -> Void) - func post(url: String, body: Body, - onComplete: @escaping (Result) -> Void) - func post(url: URL, body: Body, - onComplete: @escaping (Result) -> Void) + func post(url: String, onComplete: @escaping OnComplete) + func post(url: URL, onComplete: @escaping OnComplete) + func post(url: String, body: U, onComplete: @escaping OnComplete) + func post(url: URL, body: U, onComplete: @escaping OnComplete) } diff --git a/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift b/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift index 130e9a0..28217dd 100644 --- a/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift +++ b/Tests/Support/Doubles/BodyThrowErrorFakeBuilder.swift @@ -4,7 +4,7 @@ import Foundation struct BodyThrowErrorFakeBuilder: BodyBuildable { private let errorToThrow = FrisbeeError.invalidEntity - func build(withBody body: Entity) throws -> [String: Any] { + func build(withBody body: T) throws -> [String: Any] { throw errorToThrow } } From b1b021efa044fd5662606db9e31dec46c759ba42 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 10:39:46 -0200 Subject: [PATCH 10/12] Create DataTaskRunner extracting urlSession.dataTask --- Frisbee.xcodeproj/project.pbxproj | 4 ++++ Sources/Frisbee/Interactors/DataTaskRunner.swift | 14 ++++++++++++++ Sources/Frisbee/Requestables/NetworkGet.swift | 6 +----- Sources/Frisbee/Requestables/NetworkPost.swift | 12 ++---------- 4 files changed, 21 insertions(+), 15 deletions(-) create mode 100644 Sources/Frisbee/Interactors/DataTaskRunner.swift diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index 5f81a7f..df38805 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -53,6 +53,7 @@ 344FC7261FE5D76B00958CE4 /* ResultGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7251FE5D76B00958CE4 /* ResultGenerator.swift */; }; 344FC7291FE5D7FC00958CE4 /* ResultGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */; }; 3473C852200CD3810014C66E /* OnComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3473C851200CD3810014C66E /* OnComplete.swift */; }; + 3473C854200CD7570014C66E /* DataTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3473C853200CD7570014C66E /* DataTaskRunner.swift */; }; 34C52E832009844400DCD88C /* URLWithQueryBuildableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */; }; 34C52E852009895D00DCD88C /* FrisbeeDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */; }; 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */; }; @@ -122,6 +123,7 @@ 344FC7251FE5D76B00958CE4 /* ResultGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGenerator.swift; sourceTree = ""; }; 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorTests.swift; sourceTree = ""; }; 3473C851200CD3810014C66E /* OnComplete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnComplete.swift; sourceTree = ""; }; + 3473C853200CD7570014C66E /* DataTaskRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTaskRunner.swift; sourceTree = ""; }; 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuildableFactory.swift; sourceTree = ""; }; 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeDecodable.swift; sourceTree = ""; }; 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorFactory.swift; sourceTree = ""; }; @@ -269,6 +271,7 @@ 344DD8791FFEFB120021350B /* URLWithQueryBuilder.swift */, 3409C9E6200C385100353DC4 /* BodyBuildable.swift */, 3409C9E8200C385900353DC4 /* BodyBuilder.swift */, + 3473C853200CD7570014C66E /* DataTaskRunner.swift */, ); name = Interactors; path = Sources/Frisbee/Interactors; @@ -543,6 +546,7 @@ 34C52E8B20098D4100DCD88C /* FrisbeeJSONDecoder.swift in Sources */, 344FC71C1FE5B9D500958CE4 /* FrisbeeError.swift in Sources */, 3409C9E02009EFBA00353DC4 /* Postable.swift in Sources */, + 3473C854200CD7570014C66E /* DataTaskRunner.swift in Sources */, 34F9C72C1FE89F44002C1EB0 /* QueryItemBuilder.swift in Sources */, 34C52E8D20098D8D00DCD88C /* URLWithQueryBuildable.swift in Sources */, ); diff --git a/Sources/Frisbee/Interactors/DataTaskRunner.swift b/Sources/Frisbee/Interactors/DataTaskRunner.swift new file mode 100644 index 0000000..b1573b8 --- /dev/null +++ b/Sources/Frisbee/Interactors/DataTaskRunner.swift @@ -0,0 +1,14 @@ +import Foundation + +final class DataTaskRunner { + + static func run(with urlSession: URLSession, request: URLRequest, + onComplete: @escaping OnComplete) { + let task = urlSession.dataTask(with: request) { data, _, error in + onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) + } + + task.resume() + } + +} diff --git a/Sources/Frisbee/Requestables/NetworkGet.swift b/Sources/Frisbee/Requestables/NetworkGet.swift index c73090b..866b6fd 100644 --- a/Sources/Frisbee/Requestables/NetworkGet.swift +++ b/Sources/Frisbee/Requestables/NetworkGet.swift @@ -51,11 +51,7 @@ public class NetworkGet: Getable { private func makeRequest(url: URL, onComplete: @escaping (Result) -> Void) { let request = URLRequestFactory.make(.GET, url) - let task = urlSession.dataTask(with: request) { data, _, error in - onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) - } - - task.resume() + DataTaskRunner.run(with: urlSession, request: request, onComplete: onComplete) } } diff --git a/Sources/Frisbee/Requestables/NetworkPost.swift b/Sources/Frisbee/Requestables/NetworkPost.swift index 499c356..b67a9a6 100644 --- a/Sources/Frisbee/Requestables/NetworkPost.swift +++ b/Sources/Frisbee/Requestables/NetworkPost.swift @@ -42,7 +42,7 @@ public final class NetworkPost: Postable { private func makeRequest(url: URL, onComplete: @escaping OnComplete) { let request = URLRequestFactory.make(.POST, url) - runTask(with: request, onComplete: onComplete) + DataTaskRunner.run(with: urlSession, request: request, onComplete: onComplete) } private func makeRequest(url: URL, body: U, onComplete: @escaping OnComplete) { @@ -54,15 +54,7 @@ public final class NetworkPost: Postable { return onComplete(.fail(FrisbeeError(error))) } - runTask(with: request, onComplete: onComplete) - } - - private func runTask(with request: URLRequest, onComplete: @escaping OnComplete) { - let task = urlSession.dataTask(with: request) { data, _, error in - onComplete(ResultGeneratorFactory.make().generate(data: data, error: error)) - } - - task.resume() + DataTaskRunner.run(with: urlSession, request: request, onComplete: onComplete) } } From d04b354ca876626f6325536aaa78c59e978033d3 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 10:54:07 -0200 Subject: [PATCH 11/12] Add swift flag for warn compile time under 100 in function bodies and expression type check --- Frisbee.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index df38805..f2c79e7 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -656,7 +656,7 @@ INFOPLIST_FILE = Frisbee.xcodeproj/Frisbee_Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-function-bodies=100 -Xfrontend -warn-long-expression-type-checking=100"; PRODUCT_BUNDLE_IDENTIFIER = Frisbee; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; @@ -678,7 +678,7 @@ INFOPLIST_FILE = Frisbee.xcodeproj/Frisbee_Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; OTHER_LDFLAGS = "$(inherited)"; - OTHER_SWIFT_FLAGS = "$(inherited)"; + OTHER_SWIFT_FLAGS = "$(inherited) -Xfrontend -warn-long-function-bodies=100 -Xfrontend -warn-long-expression-type-checking=100"; PRODUCT_BUNDLE_IDENTIFIER = Frisbee; PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; From ff4e7cbeabf8d4f48dc36f4364329f0efdd37c82 Mon Sep 17 00:00:00 2001 From: Ronan Rodrigo Nunes Date: Mon, 15 Jan 2018 23:31:25 -0200 Subject: [PATCH 12/12] Create BodyBuilder tests + Abstract JSON Encoder and Serializable --- Frisbee.xcodeproj/project.pbxproj | 40 ++++++++++++++++++- .../Frisbee/Entities/FrisbeeEncodable.swift | 5 +++ .../Frisbee/Entities/FrisbeeJSONEncoder.swift | 7 ++++ .../Entities/FrisbeeJSONSerializable.swift | 7 ++++ .../Entities/FrisbeeSerializable.swift | 5 +++ .../Factories/BodyBuildableFactory.swift | 3 +- .../Factories/FrisbeeEncodableFactory.swift | 7 ++++ .../FrisbeeJSONSerializableFactroy.swift | 7 ++++ Sources/Frisbee/Interactors/BodyBuilder.swift | 12 +++++- .../Interactors/BodyBuilderTests.swift | 31 ++++++++++++++ Tests/LinuxMain.swift | 1 + .../FrisbeeThrowErrorFakeEncoder.swift | 8 ++++ .../FrisbeeThrowErrorFakeSerializer.swift | 8 ++++ 13 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 Sources/Frisbee/Entities/FrisbeeEncodable.swift create mode 100644 Sources/Frisbee/Entities/FrisbeeJSONEncoder.swift create mode 100644 Sources/Frisbee/Entities/FrisbeeJSONSerializable.swift create mode 100644 Sources/Frisbee/Entities/FrisbeeSerializable.swift create mode 100644 Sources/Frisbee/Factories/FrisbeeEncodableFactory.swift create mode 100644 Sources/Frisbee/Factories/FrisbeeJSONSerializableFactroy.swift create mode 100644 Tests/FrisbeeTests/Interactors/BodyBuilderTests.swift create mode 100644 Tests/Support/Doubles/FrisbeeThrowErrorFakeEncoder.swift create mode 100644 Tests/Support/Doubles/FrisbeeThrowErrorFakeSerializer.swift diff --git a/Frisbee.xcodeproj/project.pbxproj b/Frisbee.xcodeproj/project.pbxproj index f2c79e7..ea5baeb 100644 --- a/Frisbee.xcodeproj/project.pbxproj +++ b/Frisbee.xcodeproj/project.pbxproj @@ -54,6 +54,15 @@ 344FC7291FE5D7FC00958CE4 /* ResultGeneratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */; }; 3473C852200CD3810014C66E /* OnComplete.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3473C851200CD3810014C66E /* OnComplete.swift */; }; 3473C854200CD7570014C66E /* DataTaskRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3473C853200CD7570014C66E /* DataTaskRunner.swift */; }; + 3481FE9A200D575000D0AD6D /* BodyBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FE99200D575000D0AD6D /* BodyBuilderTests.swift */; }; + 3481FE9E200D59ED00D0AD6D /* FrisbeeJSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FE9D200D59ED00D0AD6D /* FrisbeeJSONEncoder.swift */; }; + 3481FEA0200D5A0100D0AD6D /* FrisbeeEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FE9F200D5A0100D0AD6D /* FrisbeeEncodable.swift */; }; + 3481FEA4200D5A6D00D0AD6D /* FrisbeeEncodableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEA3200D5A6D00D0AD6D /* FrisbeeEncodableFactory.swift */; }; + 3481FEA6200D892F00D0AD6D /* FrisbeeSerializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEA5200D892F00D0AD6D /* FrisbeeSerializable.swift */; }; + 3481FEA8200D894400D0AD6D /* FrisbeeJSONSerializable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEA7200D894400D0AD6D /* FrisbeeJSONSerializable.swift */; }; + 3481FEAA200D895300D0AD6D /* FrisbeeJSONSerializableFactroy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEA9200D895300D0AD6D /* FrisbeeJSONSerializableFactroy.swift */; }; + 3481FEAC200D8C8200D0AD6D /* FrisbeeThrowErrorFakeEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEAB200D8C8200D0AD6D /* FrisbeeThrowErrorFakeEncoder.swift */; }; + 3481FEAE200D8C9700D0AD6D /* FrisbeeThrowErrorFakeSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3481FEAD200D8C9700D0AD6D /* FrisbeeThrowErrorFakeSerializer.swift */; }; 34C52E832009844400DCD88C /* URLWithQueryBuildableFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */; }; 34C52E852009895D00DCD88C /* FrisbeeDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */; }; 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */; }; @@ -124,6 +133,15 @@ 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorTests.swift; sourceTree = ""; }; 3473C851200CD3810014C66E /* OnComplete.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnComplete.swift; sourceTree = ""; }; 3473C853200CD7570014C66E /* DataTaskRunner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataTaskRunner.swift; sourceTree = ""; }; + 3481FE99200D575000D0AD6D /* BodyBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BodyBuilderTests.swift; sourceTree = ""; }; + 3481FE9D200D59ED00D0AD6D /* FrisbeeJSONEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeJSONEncoder.swift; sourceTree = ""; }; + 3481FE9F200D5A0100D0AD6D /* FrisbeeEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeEncodable.swift; sourceTree = ""; }; + 3481FEA3200D5A6D00D0AD6D /* FrisbeeEncodableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeEncodableFactory.swift; sourceTree = ""; }; + 3481FEA5200D892F00D0AD6D /* FrisbeeSerializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeSerializable.swift; sourceTree = ""; }; + 3481FEA7200D894400D0AD6D /* FrisbeeJSONSerializable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeJSONSerializable.swift; sourceTree = ""; }; + 3481FEA9200D895300D0AD6D /* FrisbeeJSONSerializableFactroy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeJSONSerializableFactroy.swift; sourceTree = ""; }; + 3481FEAB200D8C8200D0AD6D /* FrisbeeThrowErrorFakeEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeThrowErrorFakeEncoder.swift; sourceTree = ""; }; + 3481FEAD200D8C9700D0AD6D /* FrisbeeThrowErrorFakeSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeThrowErrorFakeSerializer.swift; sourceTree = ""; }; 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLWithQueryBuildableFactory.swift; sourceTree = ""; }; 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrisbeeDecodable.swift; sourceTree = ""; }; 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultGeneratorFactory.swift; sourceTree = ""; }; @@ -170,6 +188,8 @@ 3409C9ED200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift */, 3409C9EF200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift */, 3409C9F1200CC72300353DC4 /* URLWithQueryTrhrowErrorFakeBuildable.swift */, + 3481FEAB200D8C8200D0AD6D /* FrisbeeThrowErrorFakeEncoder.swift */, + 3481FEAD200D8C9700D0AD6D /* FrisbeeThrowErrorFakeSerializer.swift */, ); name = Doubles; path = Tests/Support/Doubles; @@ -192,12 +212,14 @@ 3434A0AF1FE7D912000659E5 /* Factories */ = { isa = PBXGroup; children = ( + 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */, 34C52E8820098A3100DCD88C /* FrisbeeDecodableFacotry.swift */, + 3481FEA3200D5A6D00D0AD6D /* FrisbeeEncodableFactory.swift */, + 3481FEA9200D895300D0AD6D /* FrisbeeJSONSerializableFactroy.swift */, 34C52E8620098A0F00DCD88C /* ResultGeneratorFactory.swift */, 3434A0B01FE7D952000659E5 /* URLRequestFactory.swift */, 3434A0B31FE7D9FF000659E5 /* URLSessionFactory.swift */, 34C52E802009841200DCD88C /* URLWithQueryBuildableFactory.swift */, - 3409C9EA200C388E00353DC4 /* BodyBuildableFactory.swift */, ); name = Factories; path = Sources/Frisbee/Factories; @@ -241,8 +263,12 @@ isa = PBXGroup; children = ( 34C52E842009895D00DCD88C /* FrisbeeDecodable.swift */, - 34C52E8A20098D4100DCD88C /* FrisbeeJSONDecoder.swift */, + 3481FE9F200D5A0100D0AD6D /* FrisbeeEncodable.swift */, 344FC71B1FE5B9D500958CE4 /* FrisbeeError.swift */, + 34C52E8A20098D4100DCD88C /* FrisbeeJSONDecoder.swift */, + 3481FE9D200D59ED00D0AD6D /* FrisbeeJSONEncoder.swift */, + 3481FEA7200D894400D0AD6D /* FrisbeeJSONSerializable.swift */, + 3481FEA5200D892F00D0AD6D /* FrisbeeSerializable.swift */, 3434A0B51FE7DA5A000659E5 /* HTTPMethod.swift */, 344FC71D1FE5BA0200958CE4 /* Result.swift */, ); @@ -283,6 +309,7 @@ 34F9C7291FE89EF5002C1EB0 /* QueryItemBuilderTests.swift */, 344FC7271FE5D7F900958CE4 /* ResultGeneratorTests.swift */, 344DD87C1FFEFC910021350B /* URLWithQueryBuilderTests.swift */, + 3481FE99200D575000D0AD6D /* BodyBuilderTests.swift */, ); name = Interactors; path = Tests/FrisbeeTests/Interactors; @@ -509,13 +536,16 @@ 343ECBA8200CC90500320259 /* MovieQuery.swift in Sources */, 3409C9EE200CC66A00353DC4 /* BodyThrowErrorFakeBuilder.swift in Sources */, 343ECBA9200CC90500320259 /* SomeEntity.swift in Sources */, + 3481FEAE200D8C9700D0AD6D /* FrisbeeThrowErrorFakeSerializer.swift in Sources */, OBJ_27 /* NetworkGetTests.swift in Sources */, + 3481FE9A200D575000D0AD6D /* BodyBuilderTests.swift in Sources */, 34F9C72A1FE89EF5002C1EB0 /* QueryItemBuilderTests.swift in Sources */, 343ECBAA200CC90500320259 /* SomeError.swift in Sources */, 343ECBA7200CC90500320259 /* Movie.swift in Sources */, 34F91DA6200821B900FFAE20 /* XCTestCase+AssertContains.swift in Sources */, 3434A0BC1FE7DD74000659E5 /* URLSessionFactoryTests.swift in Sources */, 343ECBA6200CC90500320259 /* Fake.swift in Sources */, + 3481FEAC200D8C8200D0AD6D /* FrisbeeThrowErrorFakeEncoder.swift in Sources */, 578D2CA3200199A500EE3865 /* FrisbeeErrorTests.swift in Sources */, 34F91DA9200822F500FFAE20 /* FrisbeeError+All.swift in Sources */, 3409C9F0200CC6AB00353DC4 /* FrisbeeThrowErrorFakeDecodable.swift in Sources */, @@ -526,8 +556,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( + 3481FEA0200D5A0100D0AD6D /* FrisbeeEncodable.swift in Sources */, 3409C9E12009EFBA00353DC4 /* NetworkPost.swift in Sources */, 3409C9E9200C385900353DC4 /* BodyBuilder.swift in Sources */, + 3481FEA6200D892F00D0AD6D /* FrisbeeSerializable.swift in Sources */, 34C52E8720098A0F00DCD88C /* ResultGeneratorFactory.swift in Sources */, 344FC71A1FE5B93200958CE4 /* Getable.swift in Sources */, 344DD87B1FFEFBE40021350B /* URLWithQueryBuilder.swift in Sources */, @@ -541,10 +573,14 @@ 3434A0B61FE7DA5A000659E5 /* HTTPMethod.swift in Sources */, 344FC7201FE5BBFE00958CE4 /* NetworkGet.swift in Sources */, 3434A0B21FE7D9CC000659E5 /* URLRequestFactory.swift in Sources */, + 3481FEAA200D895300D0AD6D /* FrisbeeJSONSerializableFactroy.swift in Sources */, + 3481FEA8200D894400D0AD6D /* FrisbeeJSONSerializable.swift in Sources */, 34C52E852009895D00DCD88C /* FrisbeeDecodable.swift in Sources */, 34C52E8920098A3100DCD88C /* FrisbeeDecodableFacotry.swift in Sources */, + 3481FE9E200D59ED00D0AD6D /* FrisbeeJSONEncoder.swift in Sources */, 34C52E8B20098D4100DCD88C /* FrisbeeJSONDecoder.swift in Sources */, 344FC71C1FE5B9D500958CE4 /* FrisbeeError.swift in Sources */, + 3481FEA4200D5A6D00D0AD6D /* FrisbeeEncodableFactory.swift in Sources */, 3409C9E02009EFBA00353DC4 /* Postable.swift in Sources */, 3473C854200CD7570014C66E /* DataTaskRunner.swift in Sources */, 34F9C72C1FE89F44002C1EB0 /* QueryItemBuilder.swift in Sources */, diff --git a/Sources/Frisbee/Entities/FrisbeeEncodable.swift b/Sources/Frisbee/Entities/FrisbeeEncodable.swift new file mode 100644 index 0000000..1ccc6da --- /dev/null +++ b/Sources/Frisbee/Entities/FrisbeeEncodable.swift @@ -0,0 +1,5 @@ +import Foundation + +protocol FrisbeeEncodable { + func encode(_ value: T) throws -> Data +} diff --git a/Sources/Frisbee/Entities/FrisbeeJSONEncoder.swift b/Sources/Frisbee/Entities/FrisbeeJSONEncoder.swift new file mode 100644 index 0000000..a3f8253 --- /dev/null +++ b/Sources/Frisbee/Entities/FrisbeeJSONEncoder.swift @@ -0,0 +1,7 @@ +import Foundation + +class FrisbeeJSONEncoder: FrisbeeEncodable { + func encode(_ value: T) throws -> Data { + return try JSONEncoder().encode(value) + } +} diff --git a/Sources/Frisbee/Entities/FrisbeeJSONSerializable.swift b/Sources/Frisbee/Entities/FrisbeeJSONSerializable.swift new file mode 100644 index 0000000..02db8f8 --- /dev/null +++ b/Sources/Frisbee/Entities/FrisbeeJSONSerializable.swift @@ -0,0 +1,7 @@ +import Foundation + +class FrisbeeJSONSerializable: FrisbeeSerializable { + func object(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any { + return try JSONSerialization.jsonObject(with: data, options: opt) + } +} diff --git a/Sources/Frisbee/Entities/FrisbeeSerializable.swift b/Sources/Frisbee/Entities/FrisbeeSerializable.swift new file mode 100644 index 0000000..c46671e --- /dev/null +++ b/Sources/Frisbee/Entities/FrisbeeSerializable.swift @@ -0,0 +1,5 @@ +import Foundation + +protocol FrisbeeSerializable { + func object(with data: Data, options opt: JSONSerialization.ReadingOptions) throws -> Any +} diff --git a/Sources/Frisbee/Factories/BodyBuildableFactory.swift b/Sources/Frisbee/Factories/BodyBuildableFactory.swift index 221a619..a3cdc40 100644 --- a/Sources/Frisbee/Factories/BodyBuildableFactory.swift +++ b/Sources/Frisbee/Factories/BodyBuildableFactory.swift @@ -1,7 +1,8 @@ struct BodyBuildableFactory { static func make() -> BodyBuildable { - return BodyBuilder() + return BodyBuilder(encoder: FrisbeeEncodableFactory.make(), + serializer: FrisbeeJSONSerializableFactroy.make()) } } diff --git a/Sources/Frisbee/Factories/FrisbeeEncodableFactory.swift b/Sources/Frisbee/Factories/FrisbeeEncodableFactory.swift new file mode 100644 index 0000000..1468486 --- /dev/null +++ b/Sources/Frisbee/Factories/FrisbeeEncodableFactory.swift @@ -0,0 +1,7 @@ +class FrisbeeEncodableFactory { + + static func make() -> FrisbeeEncodable { + return FrisbeeJSONEncoder() + } + +} diff --git a/Sources/Frisbee/Factories/FrisbeeJSONSerializableFactroy.swift b/Sources/Frisbee/Factories/FrisbeeJSONSerializableFactroy.swift new file mode 100644 index 0000000..a3fffc1 --- /dev/null +++ b/Sources/Frisbee/Factories/FrisbeeJSONSerializableFactroy.swift @@ -0,0 +1,7 @@ +class FrisbeeJSONSerializableFactroy { + + static func make() -> FrisbeeSerializable { + return FrisbeeJSONSerializable() + } + +} diff --git a/Sources/Frisbee/Interactors/BodyBuilder.swift b/Sources/Frisbee/Interactors/BodyBuilder.swift index 7ee6823..ff6dfe4 100644 --- a/Sources/Frisbee/Interactors/BodyBuilder.swift +++ b/Sources/Frisbee/Interactors/BodyBuilder.swift @@ -2,11 +2,19 @@ import Foundation struct BodyBuilder: BodyBuildable { + private let encoder: FrisbeeEncodable + private let serializer: FrisbeeSerializable + + init(encoder: FrisbeeEncodable, serializer: FrisbeeSerializable) { + self.encoder = encoder + self.serializer = serializer + } + func build(withBody body: T) throws -> [String: Any] { var json: [String: Any] = [:] - let data = try JSONEncoder().encode(body) - let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) + let data = try encoder.encode(body) + let jsonObject = try serializer.object(with: data, options: []) if let jsonDictionary = jsonObject as? [String: Any] { json = jsonDictionary } return json diff --git a/Tests/FrisbeeTests/Interactors/BodyBuilderTests.swift b/Tests/FrisbeeTests/Interactors/BodyBuilderTests.swift new file mode 100644 index 0000000..4ae0380 --- /dev/null +++ b/Tests/FrisbeeTests/Interactors/BodyBuilderTests.swift @@ -0,0 +1,31 @@ +import XCTest +@testable import Frisbee + +final class BodyBuilderTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + func testBuildWithBodyWhenEncoderThrowsAnErrorThenThrows() { + let builder = BodyBuilder(encoder: FrisbeeThrowErrorFakeEncoder(), + serializer: FrisbeeJSONSerializableFactroy.make()) + + XCTAssertThrowsError(try builder.build(withBody: Fake(fake: ""))) + } + + func testBuildWithBodyWhenSerializerThrowsAnErrorThenThrows() { + let builder = BodyBuilder(encoder: FrisbeeEncodableFactory.make(), + serializer: FrisbeeThrowErrorFakeSerializer()) + + XCTAssertThrowsError(try builder.build(withBody: Fake(fake: ""))) + } + + static let allTests = [ + ("testBuildWithBodyWhenEncoderThrowsAnErrorThenThrows", + testBuildWithBodyWhenEncoderThrowsAnErrorThenThrows), + ("testBuildWithBodyWhenSerializerThrowsAnErrorThenThrows", + testBuildWithBodyWhenSerializerThrowsAnErrorThenThrows) + ] + +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index b9073b8..b160cc7 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -10,6 +10,7 @@ var allTests = [ testCase(URLWithQueryBuilderTests.allTests), testCase(ResultGeneratorTests.allTests), testCase(FrisbeeErrorTests.allTests), + testCase(BodyBuilderTests.allTests), testCase(ResultTests.allTests) ] diff --git a/Tests/Support/Doubles/FrisbeeThrowErrorFakeEncoder.swift b/Tests/Support/Doubles/FrisbeeThrowErrorFakeEncoder.swift new file mode 100644 index 0000000..1817188 --- /dev/null +++ b/Tests/Support/Doubles/FrisbeeThrowErrorFakeEncoder.swift @@ -0,0 +1,8 @@ +import Foundation +@testable import Frisbee + +class FrisbeeThrowErrorFakeEncoder: FrisbeeEncodable { + func encode(_ value: T) throws -> Data { + throw FrisbeeError.invalidEntity + } +} diff --git a/Tests/Support/Doubles/FrisbeeThrowErrorFakeSerializer.swift b/Tests/Support/Doubles/FrisbeeThrowErrorFakeSerializer.swift new file mode 100644 index 0000000..16963c8 --- /dev/null +++ b/Tests/Support/Doubles/FrisbeeThrowErrorFakeSerializer.swift @@ -0,0 +1,8 @@ +import Foundation +@testable import Frisbee + +class FrisbeeThrowErrorFakeSerializer: FrisbeeSerializable { + func object(with data: Data, options opt: JSONSerialization.ReadingOptions = []) throws -> Any { + throw FrisbeeError.invalidEntity + } +}