From 63b9ad227dccfecc70ad7a1188167d3e1794d823 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Mon, 14 Dec 2020 12:42:09 +0100 Subject: [PATCH 01/14] Update tests to use a URLProtocolMock --- Sources/SwiftQuests/Request.swift | 2 +- .../Mocks/URLProtocolMock.swift | 42 +++++++++++++++++++ .../Mocks/URLSessionCodableMock.swift | 17 -------- .../Mocks/URLSessionDataTaskMock.swift | 20 --------- .../Mocks/URLSessionMock.swift | 21 ---------- Tests/SwiftQuestsTests/RequestTests.swift | 33 +++++++++------ 6 files changed, 63 insertions(+), 72 deletions(-) create mode 100644 Tests/SwiftQuestsTests/Mocks/URLProtocolMock.swift delete mode 100644 Tests/SwiftQuestsTests/Mocks/URLSessionCodableMock.swift delete mode 100644 Tests/SwiftQuestsTests/Mocks/URLSessionDataTaskMock.swift delete mode 100644 Tests/SwiftQuestsTests/Mocks/URLSessionMock.swift diff --git a/Sources/SwiftQuests/Request.swift b/Sources/SwiftQuests/Request.swift index c5dcb9a..b2cf388 100644 --- a/Sources/SwiftQuests/Request.swift +++ b/Sources/SwiftQuests/Request.swift @@ -69,7 +69,7 @@ open class Request: AbstractRequest { /// The request `URLSession`. /// /// Defaults to a session with a `default` `URLSessionConfiguration` unless otherwise specified. - public var session = URLSession(configuration: .default) + public var session = URLSession.shared /// The wrapped `URLRequest` object. public var urlRequest: URLRequest! diff --git a/Tests/SwiftQuestsTests/Mocks/URLProtocolMock.swift b/Tests/SwiftQuestsTests/Mocks/URLProtocolMock.swift new file mode 100644 index 0000000..5ffac51 --- /dev/null +++ b/Tests/SwiftQuestsTests/Mocks/URLProtocolMock.swift @@ -0,0 +1,42 @@ +// +// URLProtocolMock.swift +// +// +// Created by Andrea Sacerdoti on 05/02/2020. +// + +import Foundation + +class URLProtocolMock: URLProtocol { + static var response: (data: Data?, response: URLResponse?, error: Error?)? + + override class func canInit(with request: URLRequest) -> Bool { + true + } + + override class func canonicalRequest(for request: URLRequest) -> URLRequest { + request + } + + override func startLoading() { + if let (data, response, error) = URLProtocolMock.response { + + if let response = response { + client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed) + } + + if let data = data { + client?.urlProtocol(self, didLoad: data) + } + + if let error = error { + client?.urlProtocol(self, didFailWithError: error) + } + } + + client?.urlProtocolDidFinishLoading(self) + } + + override func stopLoading() { + } +} diff --git a/Tests/SwiftQuestsTests/Mocks/URLSessionCodableMock.swift b/Tests/SwiftQuestsTests/Mocks/URLSessionCodableMock.swift deleted file mode 100644 index 82659d0..0000000 --- a/Tests/SwiftQuestsTests/Mocks/URLSessionCodableMock.swift +++ /dev/null @@ -1,17 +0,0 @@ -// -// URLSessionCodableMock.swift -// -// -// Created by Andrea Sacerdoti on 06/02/2020. -// - -import Foundation - -class URLSessionCodableMock: URLSessionMock { - override init() { - super.init() - let user = User() - user.username = "test" - self.data = try? JSONEncoder().encode(user) - } -} diff --git a/Tests/SwiftQuestsTests/Mocks/URLSessionDataTaskMock.swift b/Tests/SwiftQuestsTests/Mocks/URLSessionDataTaskMock.swift deleted file mode 100644 index c659643..0000000 --- a/Tests/SwiftQuestsTests/Mocks/URLSessionDataTaskMock.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// URLSessionDataTaskMock.swift -// -// -// Created by Andrea Sacerdoti on 05/02/2020. -// - -import Foundation - -class URLSessionDataTaskMock: URLSessionDataTask { - private let completion: () -> Void - - init(completion: @escaping () -> Void) { - self.completion = completion - } - - override func resume() { - completion() - } -} diff --git a/Tests/SwiftQuestsTests/Mocks/URLSessionMock.swift b/Tests/SwiftQuestsTests/Mocks/URLSessionMock.swift deleted file mode 100644 index e0abb73..0000000 --- a/Tests/SwiftQuestsTests/Mocks/URLSessionMock.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// URLSessionMock.swift -// -// -// Created by Andrea Sacerdoti on 05/02/2020. -// - -import Foundation - -class URLSessionMock: URLSession { - var data: Data? - var response: URLResponse? - var error: Error? - - override func dataTask(with request: URLRequest, - completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask { - URLSessionDataTaskMock { - completionHandler(self.data, self.response, self.error) - } - } -} diff --git a/Tests/SwiftQuestsTests/RequestTests.swift b/Tests/SwiftQuestsTests/RequestTests.swift index d664591..2494561 100644 --- a/Tests/SwiftQuestsTests/RequestTests.swift +++ b/Tests/SwiftQuestsTests/RequestTests.swift @@ -11,8 +11,14 @@ import XCTest final class RequestTests: XCTestCase { var request: Request? + var session = URLSession(configuration: .ephemeral) + override func setUp() { super.setUp() + URLProtocolMock.response = nil + let configuration = URLSessionConfiguration.ephemeral + configuration.protocolClasses = [URLProtocolMock.self] + session = URLSession(configuration: configuration) request = try? Request(.get, atPath: "/user", parameters: ["user": "12345"], @@ -22,7 +28,7 @@ final class RequestTests: XCTestCase { using: URLCredential(user: "test", password: "testPassword", persistence: .forSession), - onSession: URLSessionMock(), + onSession: session, configuration: DefaultRequestConfiguration()) } @@ -76,8 +82,10 @@ final class RequestTests: XCTestCase { func testPerformErrorReturn() { let throwExpectation = expectation(description: "Perform should throw an error") - let session = URLSessionMock() - session.error = NSError(domain: "test", code: 42, userInfo: [NSLocalizedDescriptionKey: "Test error"]) + URLProtocolMock.response = (nil, nil, NSError(domain: "test", + code: 42, + userInfo: [NSLocalizedDescriptionKey: "Test error"])) + try? Request(.get, atPath: "/test", @@ -93,10 +101,13 @@ final class RequestTests: XCTestCase { func testPerformDecoding() { let decodingExpectation = expectation(description: "Object should decode correctly") + let user = User() + user.username = "test" + URLProtocolMock.response = (try? JSONEncoder().encode(user), nil, nil) try? Request(.get, atPath: "/user", - onSession: URLSessionCodableMock()) + onSession: session) .perform(decoding: User.self) { result in if let response = try? result.get(), @@ -111,12 +122,11 @@ final class RequestTests: XCTestCase { func testPerformDecodingError() { let throwingExpectation = expectation(description: "Perform should throw an error") - let sessionMock = URLSessionCodableMock() - sessionMock.data = Data(base64Encoded: "VEhJU0lTV1JPTkc=") + URLProtocolMock.response = (Data(base64Encoded: "VEhJU0lTV1JPTkc="), nil, nil) try? Request(.get, atPath: "/user", - onSession: sessionMock) + onSession: session) .perform(decoding: User.self) { result in XCTAssertThrowsError(try result.get()) @@ -128,12 +138,10 @@ final class RequestTests: XCTestCase { func testPerformDecodingNoDataError() { let throwingExpectation = expectation(description: "Perform should throw an error") - let sessionMock = URLSessionCodableMock() - sessionMock.data = nil try? Request(.get, atPath: "/user", - onSession: sessionMock) + onSession: session) .perform(decoding: User.self) { result in XCTAssertThrowsError(try result.get()) @@ -145,12 +153,11 @@ final class RequestTests: XCTestCase { func testPerformDecodingPerformError() { let throwingExpectation = expectation(description: "Perform should throw an error") - let sessionMock = URLSessionCodableMock() - sessionMock.error = NSError(domain: "test", code: 42, userInfo: [NSLocalizedDescriptionKey: "Test error"]) + URLProtocolMock.response = (nil, nil, NSError(domain: "test", code: 42, userInfo: [NSLocalizedDescriptionKey: "Test error"])) try? Request(.get, atPath: "/user", - onSession: sessionMock) + onSession: session) .perform(decoding: User.self) { result in XCTAssertThrowsError(try result.get()) From e4b260a053bc7ba03b0013d6df97c71408d05592 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 19 Mar 2021 17:21:28 +0100 Subject: [PATCH 02/14] Update Request documentation --- Package.swift | 30 +++++++++++++++--------------- Sources/SwiftQuests/Request.swift | 2 -- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/Package.swift b/Package.swift index 462532c..7be2232 100644 --- a/Package.swift +++ b/Package.swift @@ -1,20 +1,20 @@ -// swift-tools-version:5.1 +// swift-tools-version:5.3 import PackageDescription let package = Package( - name: "SwiftQuests", - products: [ - .library( - name: "SwiftQuests", - targets: ["SwiftQuests"]), - ], - targets: [ - .target( - name: "SwiftQuests", - dependencies: []), - .testTarget( - name: "SwiftQuestsTests", - dependencies: ["SwiftQuests"]), - ] + name: "SwiftQuests", + products: [ + .library( + name: "SwiftQuests", + targets: ["SwiftQuests"]), + ], + targets: [ + .target( + name: "SwiftQuests", + dependencies: []), + .testTarget( + name: "SwiftQuestsTests", + dependencies: ["SwiftQuests"]), + ] ) diff --git a/Sources/SwiftQuests/Request.swift b/Sources/SwiftQuests/Request.swift index 2ea65ec..d0e7d27 100644 --- a/Sources/SwiftQuests/Request.swift +++ b/Sources/SwiftQuests/Request.swift @@ -123,7 +123,6 @@ open class Request: AbstractRequest { /// - Parameters: /// - completionHandler: An handler called upon completion. /// - result: The response result. - /// - error: The task error. /// - Throws: An error if either the `urlRequest` property was not properly initialised, or the `completionHandler` /// throws. open func perform(_ completionHandler: @escaping (_ result: Result) throws -> Void) { @@ -153,7 +152,6 @@ open class Request: AbstractRequest { /// - object: An object type to decode from the response data. /// - completionHandler: An handler called upon completion. /// - result: The response result. - /// - error: The task error. open func perform(decoding object: T.Type, _ completionHandler: @escaping ( _ result: Result<(T, URLResponse?), Error>) throws -> Void) { From f02a04b73072c8937edfba998fd05dc0be84bc7c Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 19 Mar 2021 17:21:48 +0100 Subject: [PATCH 03/14] Rename GitHub action --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index b127bd8..4f6d0c9 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -1,4 +1,4 @@ -name: Swift +name: tests on: [pull_request] From 6c8eba3aec9a664a9a65c91166a5c540888828f3 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 16:39:16 +0200 Subject: [PATCH 04/14] Add NetworkError, make Requests throw HTTP errors --- Sources/SwiftQuests/NetworkError.swift | 73 +++++++++++++++++++ Sources/SwiftQuests/Request.swift | 7 ++ .../SwiftQuestsTests/NetworkErrorTests.swift | 31 ++++++++ Tests/SwiftQuestsTests/RequestTests.swift | 25 +++++++ 4 files changed, 136 insertions(+) create mode 100644 Sources/SwiftQuests/NetworkError.swift create mode 100644 Tests/SwiftQuestsTests/NetworkErrorTests.swift diff --git a/Sources/SwiftQuests/NetworkError.swift b/Sources/SwiftQuests/NetworkError.swift new file mode 100644 index 0000000..8ee4b43 --- /dev/null +++ b/Sources/SwiftQuests/NetworkError.swift @@ -0,0 +1,73 @@ +// +// NetworkError.swift +// +// +// Created by Andrea Sacerdoti on 17/12/20. +// + +import Foundation + +/// A specialized error for network purposes. +public enum NetworkError: LocalizedError { + + /// A generic network error. + case generic + + /// An error identifying the 400 HTTP status code. + case badRequest + + /// An error identifying the 401 HTTP status code. + case unauthorized + + /// An error identifying the 403 HTTP status code. + case forbidden + + /// An error identifying the 404 HTTP status code. + case notFound + + /// An error identifying the 500 HTTP status code. + case internalServerError + + /// An error including a description provided by the backend. + case withDescription(String) + + public var errorDescription: String? { + switch self { + case .generic: + return NSLocalizedString("Generic error.", comment: "") + case .badRequest: + return NSLocalizedString("Bad request.", comment: "") + case .unauthorized: + return NSLocalizedString("Unauthorized.", comment: "") + case .forbidden: + return NSLocalizedString("Access denied.", comment: "") + case .notFound: + return NSLocalizedString("Resource not found.", comment: "") + case .internalServerError: + return NSLocalizedString("Internal server error.", comment: "") + case .withDescription(let description): + return NSLocalizedString(description, comment: "") + } + } + + public static func identifying(statusCode: Int) -> NetworkError { + switch statusCode { + case 400: + return NetworkError.badRequest + case 401: + return NetworkError.unauthorized + case 403: + return NetworkError.forbidden + case 404: + return NetworkError.notFound + case 500: + return NetworkError.internalServerError + default: + return NetworkError.generic + } + } +} + +// MARK: - +extension NetworkError: Equatable { +} diff --git a/Sources/SwiftQuests/Request.swift b/Sources/SwiftQuests/Request.swift index 2ea65ec..f0c591f 100644 --- a/Sources/SwiftQuests/Request.swift +++ b/Sources/SwiftQuests/Request.swift @@ -134,6 +134,13 @@ open class Request: AbstractRequest { return } + if let statusCode = (response as? HTTPURLResponse)?.statusCode, + !(200..<300 ~= statusCode) { + + try? completionHandler(.failure(NetworkError.identifying(statusCode: statusCode))) + return + } + try? completionHandler(.success((data, response))) } diff --git a/Tests/SwiftQuestsTests/NetworkErrorTests.swift b/Tests/SwiftQuestsTests/NetworkErrorTests.swift new file mode 100644 index 0000000..859969c --- /dev/null +++ b/Tests/SwiftQuestsTests/NetworkErrorTests.swift @@ -0,0 +1,31 @@ +// +// NetworkErrorTests.swift +// +// +// Created by Andrea Sacerdoti on 02/07/21. +// + +import XCTest +@testable import SwiftQuests + +final class NetworkErrorTests: XCTestCase { + + func testErrorDescription() { + XCTAssertNotNil(NetworkError.generic.errorDescription) + XCTAssertNotNil(NetworkError.badRequest.errorDescription) + XCTAssertNotNil(NetworkError.unauthorized.errorDescription) + XCTAssertNotNil(NetworkError.forbidden.errorDescription) + XCTAssertNotNil(NetworkError.notFound.errorDescription) + XCTAssertNotNil(NetworkError.internalServerError.errorDescription) + XCTAssertEqual(NetworkError.withDescription("Test Description").localizedDescription, "Test Description") + } + + func testIdentifying() { + XCTAssertEqual(NetworkError.identifying(statusCode: 400), .badRequest) + XCTAssertEqual(NetworkError.identifying(statusCode: 401), .unauthorized) + XCTAssertEqual(NetworkError.identifying(statusCode: 403), .forbidden) + XCTAssertEqual(NetworkError.identifying(statusCode: 404), .notFound) + XCTAssertEqual(NetworkError.identifying(statusCode: 405), .generic) + XCTAssertEqual(NetworkError.identifying(statusCode: 500), .internalServerError) + } +} diff --git a/Tests/SwiftQuestsTests/RequestTests.swift b/Tests/SwiftQuestsTests/RequestTests.swift index d664591..57ec545 100644 --- a/Tests/SwiftQuestsTests/RequestTests.swift +++ b/Tests/SwiftQuestsTests/RequestTests.swift @@ -91,6 +91,31 @@ final class RequestTests: XCTestCase { wait(for: [throwExpectation], timeout: 5) } + func testPerformStatusCodeErrorReturn() { + let throwExpectation = expectation(description: "Perform should throw an error") + let session = URLSessionMock() + session.response = HTTPURLResponse(url: URL(string: "https://test.com/test")!, + statusCode: 404, + httpVersion: nil, + headerFields: [:]) + + try? Request(.get, + atPath: "/test", + onSession: session) + .perform { result in + + switch result { + case .failure(let error): + XCTAssertEqual(error as? NetworkError, NetworkError.notFound) + throwExpectation.fulfill() + case .success: + XCTFail("Request should throw an error with status code 404") + } + } + + wait(for: [throwExpectation], timeout: 5) + } + func testPerformDecoding() { let decodingExpectation = expectation(description: "Object should decode correctly") From b08945e0000151c9849e9039d8ee9bdef5b19d97 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 16:45:59 +0200 Subject: [PATCH 05/14] Add documentation --- Package.swift | 28 +++++++++++++------------- Sources/SwiftQuests/NetworkError.swift | 3 +++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/Package.swift b/Package.swift index 462532c..144695e 100644 --- a/Package.swift +++ b/Package.swift @@ -3,18 +3,18 @@ import PackageDescription let package = Package( - name: "SwiftQuests", - products: [ - .library( - name: "SwiftQuests", - targets: ["SwiftQuests"]), - ], - targets: [ - .target( - name: "SwiftQuests", - dependencies: []), - .testTarget( - name: "SwiftQuestsTests", - dependencies: ["SwiftQuests"]), - ] + name: "SwiftQuests", + products: [ + .library( + name: "SwiftQuests", + targets: ["SwiftQuests"]), + ], + targets: [ + .target( + name: "SwiftQuests", + dependencies: []), + .testTarget( + name: "SwiftQuestsTests", + dependencies: ["SwiftQuests"]), + ] ) diff --git a/Sources/SwiftQuests/NetworkError.swift b/Sources/SwiftQuests/NetworkError.swift index 8ee4b43..213e854 100644 --- a/Sources/SwiftQuests/NetworkError.swift +++ b/Sources/SwiftQuests/NetworkError.swift @@ -50,6 +50,9 @@ public enum NetworkError: LocalizedError { } } + /// Returns a NetworkError identifying a given HTTP error. + /// - Parameter statusCode: The given HTTP status code. + /// - Returns: A NetworkError identified by the given status code. public static func identifying(statusCode: Int) -> NetworkError { switch statusCode { case 400: From 5e71242ecbc0f18606c960b3c693ae3d3b2dedf8 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 16:50:06 +0200 Subject: [PATCH 06/14] Update GitHub workflow --- .github/workflows/swift.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index b127bd8..19c3f39 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -1,4 +1,4 @@ -name: Swift +name: Test on: [pull_request] @@ -10,16 +10,8 @@ jobs: - uses: actions/checkout@v2 - name: Build run: swift build -v - test: - runs-on: macos-latest - steps: - - uses: actions/checkout@v2 - name: Run tests run: swift test -v --enable-code-coverage - - codecov: - runs-on: macos-latest - steps: - uses: actions/checkout@v2 - name: Generate coverage report run: xcodebuild -scheme SwiftQuests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11 Pro' -enableCodeCoverage YES build test @@ -27,4 +19,4 @@ jobs: uses: codecov/codecov-action@v1.0.5 with: token: 44439f4d-d012-4000-a0c1-28647d07b545 - # file: + # file: From cb158942406e2116604b2380674147d6704eeabb Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 16:50:56 +0200 Subject: [PATCH 07/14] Fix typo --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 19c3f39..85e3c19 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -3,7 +3,7 @@ name: Test on: [pull_request] jobs: - build: + test: runs-on: macos-latest steps: From c582630598fb9e755b0c197ecc816336a2a117ff Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 16:55:34 +0200 Subject: [PATCH 08/14] Refactor GitHub workflow --- .github/workflows/swift.yml | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 85e3c19..de34443 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -8,15 +8,14 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Build - run: swift build -v - - name: Run tests - run: swift test -v --enable-code-coverage - - uses: actions/checkout@v2 - name: Generate coverage report - run: xcodebuild -scheme SwiftQuests -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 11 Pro' -enableCodeCoverage YES build test + run: | + swift test --enable-code-coverage + llvm-cov export -format="lcov" .build/debug/SwiftQuestsPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov - name: Codecov uses: codecov/codecov-action@v1.0.5 with: token: 44439f4d-d012-4000-a0c1-28647d07b545 - # file: + xcode_derived_data: build + functionalities: html + xcode_package: SwiftQuests From 3a608193a0841157fbac44ada3ca5eee3dc3f231 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:01:40 +0200 Subject: [PATCH 09/14] Fix llvm-cov script --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index de34443..56b8e4d 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -11,7 +11,7 @@ jobs: - name: Generate coverage report run: | swift test --enable-code-coverage - llvm-cov export -format="lcov" .build/debug/SwiftQuestsPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov + xcrun llvm-cov export -format="lcov" .build/debug/SwiftQuestsPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov - name: Codecov uses: codecov/codecov-action@v1.0.5 with: From 62f96dabfdf07be8050380f58e2764b2baf6a8a6 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:04:12 +0200 Subject: [PATCH 10/14] Fix llvm-cov script --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 56b8e4d..5152c06 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -11,7 +11,7 @@ jobs: - name: Generate coverage report run: | swift test --enable-code-coverage - xcrun llvm-cov export -format="lcov" .build/debug/SwiftQuestsPackageTests.xctest -instr-profile .build/debug/codecov/default.profdata > info.lcov + xcrun llvm-cov export -format="lcov" .build/debug/SwiftQuestsPackageTests.xctest/Contents/MacOS/SwiftQuestsPackageTests -instr-profile .build/debug/codecov/default.profdata > info.lcov - name: Codecov uses: codecov/codecov-action@v1.0.5 with: From 7825b405e2c8bcd57a2db094ee0ac5a8a45fb3b8 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:07:26 +0200 Subject: [PATCH 11/14] Refactor GitHub workflow --- .github/workflows/swift.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 5152c06..3e332df 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -16,6 +16,3 @@ jobs: uses: codecov/codecov-action@v1.0.5 with: token: 44439f4d-d012-4000-a0c1-28647d07b545 - xcode_derived_data: build - functionalities: html - xcode_package: SwiftQuests From 54d6b16ee56ef24c920099d5d12a12d8c5beadb2 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:15:43 +0200 Subject: [PATCH 12/14] Refactor tests --- Tests/SwiftQuestsTests/RequestTests.swift | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Tests/SwiftQuestsTests/RequestTests.swift b/Tests/SwiftQuestsTests/RequestTests.swift index 57ec545..53bb68b 100644 --- a/Tests/SwiftQuestsTests/RequestTests.swift +++ b/Tests/SwiftQuestsTests/RequestTests.swift @@ -104,12 +104,9 @@ final class RequestTests: XCTestCase { onSession: session) .perform { result in - switch result { - case .failure(let error): + if case .failure(let error) = result { XCTAssertEqual(error as? NetworkError, NetworkError.notFound) throwExpectation.fulfill() - case .success: - XCTFail("Request should throw an error with status code 404") } } From 2ccc98a793da94dc8ea80e7f0304f596c64f4a3e Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:21:31 +0200 Subject: [PATCH 13/14] Remove test manifests --- Tests/LinuxMain.swift | 7 ------- Tests/SwiftQuestsTests/RequestTests.swift | 9 --------- Tests/SwiftQuestsTests/XCTestManifests.swift | 10 ---------- 3 files changed, 26 deletions(-) delete mode 100644 Tests/LinuxMain.swift delete mode 100644 Tests/SwiftQuestsTests/XCTestManifests.swift diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift deleted file mode 100644 index f0d68d1..0000000 --- a/Tests/LinuxMain.swift +++ /dev/null @@ -1,7 +0,0 @@ -import XCTest - -import SwiftQuestsTests - -var tests = [XCTestCaseEntry]() -tests += SwiftQuestsTests.allTests() -XCTMain(tests) diff --git a/Tests/SwiftQuestsTests/RequestTests.swift b/Tests/SwiftQuestsTests/RequestTests.swift index 53bb68b..78c34bd 100644 --- a/Tests/SwiftQuestsTests/RequestTests.swift +++ b/Tests/SwiftQuestsTests/RequestTests.swift @@ -181,13 +181,4 @@ final class RequestTests: XCTestCase { wait(for: [throwingExpectation], timeout: 5) } - - static var allTests = [ - ("testInit", testInitMethod), - ("testInitResourcePath", testInitResourcePath), - ("testInitParameters", testInitParameters), - ("testInitHeaders", testInitHeaders), - ("testInitBody", testInitBody), - ("testPerform", testPerform), - ] } diff --git a/Tests/SwiftQuestsTests/XCTestManifests.swift b/Tests/SwiftQuestsTests/XCTestManifests.swift deleted file mode 100644 index 33ff12b..0000000 --- a/Tests/SwiftQuestsTests/XCTestManifests.swift +++ /dev/null @@ -1,10 +0,0 @@ -import XCTest - -#if !canImport(ObjectiveC) -public func allTests() -> [XCTestCaseEntry] { - return [ - testCase(RequestTests.allTests), - testCase(RequestConfigurationTests.allTests) - ] -} -#endif From 9813a6c4990792b3de43d8533fb45a81fcf34ab9 Mon Sep 17 00:00:00 2001 From: Andrea Sacerdoti Date: Fri, 2 Jul 2021 17:34:08 +0200 Subject: [PATCH 14/14] Fix tests --- Sources/SwiftQuests/Request.swift | 3 ++- Tests/SwiftQuestsTests/RequestTests.swift | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/Sources/SwiftQuests/Request.swift b/Sources/SwiftQuests/Request.swift index f0c591f..2491868 100644 --- a/Sources/SwiftQuests/Request.swift +++ b/Sources/SwiftQuests/Request.swift @@ -168,7 +168,8 @@ open class Request: AbstractRequest { perform { result in switch result { case .success(let response): - guard let data = response.data else { + guard let data = response.data, + !data.isEmpty else { try completionHandler(.failure(NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Data returned nil."]))) diff --git a/Tests/SwiftQuestsTests/RequestTests.swift b/Tests/SwiftQuestsTests/RequestTests.swift index 93bcbdf..9d229b6 100644 --- a/Tests/SwiftQuestsTests/RequestTests.swift +++ b/Tests/SwiftQuestsTests/RequestTests.swift @@ -94,18 +94,19 @@ final class RequestTests: XCTestCase { XCTAssertThrowsError(try result.get()) throwExpectation.fulfill() - } + } wait(for: [throwExpectation], timeout: 5) } func testPerformStatusCodeErrorReturn() { let throwExpectation = expectation(description: "Perform should throw an error") - let session = URLSessionMock() - session.response = HTTPURLResponse(url: URL(string: "https://test.com/test")!, - statusCode: 404, - httpVersion: nil, - headerFields: [:]) + URLProtocolMock.response = (nil, + HTTPURLResponse(url: URL(string: "https://test.com/test")!, + statusCode: 404, + httpVersion: nil, + headerFields: [:]), + nil) try? Request(.get, atPath: "/test", @@ -160,6 +161,12 @@ final class RequestTests: XCTestCase { func testPerformDecodingNoDataError() { let throwingExpectation = expectation(description: "Perform should throw an error") + URLProtocolMock.response = (nil, + HTTPURLResponse(url: URL(string: "https://test.com/test")!, + statusCode: 200, + httpVersion: nil, + headerFields: [:]), + nil) try? Request(.get, atPath: "/user",