From d77d124fb799802fe76adb8afad8daaaed5174e6 Mon Sep 17 00:00:00 2001 From: Sam Woolf Date: Thu, 25 Jul 2019 16:04:43 +0100 Subject: [PATCH 1/2] add allowCompletion to requestBehavior --- .../Webservice/WebserviceTests.swift | 41 +++++++++++++++++++ .../Webservice/Requests/RequestBehavior.swift | 9 +++- Sources/Webservice/Webservice.swift | 7 ++++ 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/NetworkingTests/Webservice/WebserviceTests.swift b/NetworkingTests/Webservice/WebserviceTests.swift index aac4c2b..a117dee 100644 --- a/NetworkingTests/Webservice/WebserviceTests.swift +++ b/NetworkingTests/Webservice/WebserviceTests.swift @@ -184,4 +184,45 @@ final class WebserviceTests: XCTestCase { waitForExpectations(timeout: 0.1, handler: nil) } + + struct CancelRequestBehavior: RequestBehavior { + + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { + return false + } + } + + func testCancelledBehavior() { + + let sessionMock = URLSessionDataTaskLoaderFake(data: nil, + response: HTTPURLResponse(url: URL.fake(), + statusCode: 200, + httpVersion: nil, + headerFields: nil), + error: nil) + + webservice = Webservice(baseURL: URL.fake(), + session: sessionMock, + defaultRequestBehavior: CancelRequestBehavior()) + + let resource = Resource(endpoint: "/", decoder: EmptyDecoder()) + + webservice.load(resource) { result in + switch result { + case .failure(let error): + if let error = error as? Webservice.Error { + switch error { + case .cancelled: + break + default: + XCTFail("wrong error returned") + } + } else { + XCTFail("wrong error returned") + } + case .success: + XCTFail("should return an error") + } + } + } } diff --git a/Sources/Webservice/Requests/RequestBehavior.swift b/Sources/Webservice/Requests/RequestBehavior.swift index 091f4e2..28f8be5 100644 --- a/Sources/Webservice/Requests/RequestBehavior.swift +++ b/Sources/Webservice/Requests/RequestBehavior.swift @@ -4,16 +4,17 @@ public protocol RequestBehavior { func modify(urlComponents: URLComponents) -> URLComponents func modify(planned request: URLRequest) -> URLRequest func before(sending request: URLRequest) - func modifyResponse(data: Data?, response: URLResponse?, error: Error?) -> (Data?, URLResponse?, Error?) + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool func after(completion result: Result) + } public extension RequestBehavior { func modify(urlComponents: URLComponents) -> URLComponents { return urlComponents } func modify(planned request: URLRequest) -> URLRequest { return request } func before(sending: URLRequest) {} - + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { return true } func modifyResponse(data: Data?, response: URLResponse?, error: Error?) -> (Data?, URLResponse?, Error?) { return (data, response, error) } func after(completion result: Result) {} @@ -74,4 +75,8 @@ private struct CompoundRequestBehavior: RequestBehavior { $0.after(completion: result) } } + + func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { + return !behaviors.map { $0.allowCompletion(data: data, response: response, error: error) }.contains(false) + } } diff --git a/Sources/Webservice/Webservice.swift b/Sources/Webservice/Webservice.swift index ed364c7..dee8ed0 100644 --- a/Sources/Webservice/Webservice.swift +++ b/Sources/Webservice/Webservice.swift @@ -14,6 +14,7 @@ public struct Webservice: ResourceRequestable { public enum Error: Swift.Error { case http(HTTP.StatusCode, Swift.Error?) case unknown(Swift.Error?) + case cancelled } private let baseURL: URL @@ -42,6 +43,12 @@ public struct Webservice: ResourceRequestable { requestBehavior.before(sending: request) session.dataTask(with: request) { data, response, error in + + guard requestBehavior.allowCompletion(data: data, response: response, error: error) else { + completion(.failure(Error.cancelled)) + return + } + let (data, response, error) = requestBehavior.modifyResponse(data: data, response: response, error: error) From d05dfb365b80f8aa40998d0d5cf9cc4f738dcdca Mon Sep 17 00:00:00 2001 From: Sam Woolf Date: Thu, 25 Jul 2019 17:18:55 +0100 Subject: [PATCH 2/2] remove call to completion, replace with call to after(). Update tests --- .../Webservice/WebserviceTests.swift | 33 +++++++++---------- .../Webservice/Requests/RequestBehavior.swift | 7 +++- Sources/Webservice/Webservice.swift | 2 +- 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/NetworkingTests/Webservice/WebserviceTests.swift b/NetworkingTests/Webservice/WebserviceTests.swift index a117dee..bf5c6eb 100644 --- a/NetworkingTests/Webservice/WebserviceTests.swift +++ b/NetworkingTests/Webservice/WebserviceTests.swift @@ -186,10 +186,22 @@ final class WebserviceTests: XCTestCase { } struct CancelRequestBehavior: RequestBehavior { - func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { return false } + + func after(completion result: Result) { + switch result { + case .success: + XCTFail("should not get called") + case .failure(let error): + if case Webservice.Error.cancelled = error { + print("request cancelled") + } else { + XCTFail("incorrect error") + } + } + } } func testCancelledBehavior() { @@ -207,22 +219,9 @@ final class WebserviceTests: XCTestCase { let resource = Resource(endpoint: "/", decoder: EmptyDecoder()) - webservice.load(resource) { result in - switch result { - case .failure(let error): - if let error = error as? Webservice.Error { - switch error { - case .cancelled: - break - default: - XCTFail("wrong error returned") - } - } else { - XCTFail("wrong error returned") - } - case .success: - XCTFail("should return an error") - } + webservice.load(resource) { _ in + XCTFail("completion should not get called") } } } + diff --git a/Sources/Webservice/Requests/RequestBehavior.swift b/Sources/Webservice/Requests/RequestBehavior.swift index 28f8be5..2a801ae 100644 --- a/Sources/Webservice/Requests/RequestBehavior.swift +++ b/Sources/Webservice/Requests/RequestBehavior.swift @@ -77,6 +77,11 @@ private struct CompoundRequestBehavior: RequestBehavior { } func allowCompletion(data: Data?, response: URLResponse?, error: Error?) -> Bool { - return !behaviors.map { $0.allowCompletion(data: data, response: response, error: error) }.contains(false) + for behaviour in behaviors { + if !behaviour.allowCompletion(data: data, response: response, error: error) { + return false + } + } + return true } } diff --git a/Sources/Webservice/Webservice.swift b/Sources/Webservice/Webservice.swift index dee8ed0..559354e 100644 --- a/Sources/Webservice/Webservice.swift +++ b/Sources/Webservice/Webservice.swift @@ -45,7 +45,7 @@ public struct Webservice: ResourceRequestable { session.dataTask(with: request) { data, response, error in guard requestBehavior.allowCompletion(data: data, response: response, error: error) else { - completion(.failure(Error.cancelled)) + requestBehavior.after(completion: Result.failure(Error.cancelled)) return }