diff --git a/Changelog.md b/Changelog.md index 5d4da13de..fb6a8455f 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,8 +1,10 @@ # Next -## Fixed -- Fixes Alamofire validation not being performed on `.uploadMultipart` requests. +### Fixed +- Fixed Alamofire validation not being performed on `.uploadMultipart` requests. [#1591](https://github.com/Moya/Moya/pull/1591) by [@SD10](https://github.com/SD10). +- Fixed Alamofire validation not being performed on stubbed requests. +[#1593](https://github.com/Moya/Moya/pull/1593) by [@SD10](https://github.com/sd10). # [11.0.0] - 2018-02-07 - No changes diff --git a/Sources/Moya/MoyaProvider+Internal.swift b/Sources/Moya/MoyaProvider+Internal.swift index 67dfb1729..e8bb4d218 100644 --- a/Sources/Moya/MoyaProvider+Internal.swift +++ b/Sources/Moya/MoyaProvider+Internal.swift @@ -122,15 +122,29 @@ public extension MoyaProvider { return } + let validate = { (response: Moya.Response) -> Result in + let validCodes = target.validationType.statusCodes + guard !validCodes.isEmpty else { return .success(response) } + if validCodes.contains(response.statusCode) { + return .success(response) + } else { + let statusError = MoyaError.statusCode(response) + let error = MoyaError.underlying(statusError, response) + return .failure(error) + } + } + switch endpoint.sampleResponseClosure() { case .networkResponse(let statusCode, let data): let response = Moya.Response(statusCode: statusCode, data: data, request: request, response: nil) - plugins.forEach { $0.didReceive(.success(response), target: target) } - completion(.success(response)) + let result = validate(response) + plugins.forEach { $0.didReceive(result, target: target) } + completion(result) case .response(let customResponse, let data): let response = Moya.Response(statusCode: customResponse.statusCode, data: data, request: request, response: customResponse) - plugins.forEach { $0.didReceive(.success(response), target: target) } - completion(.success(response)) + let result = validate(response) + plugins.forEach { $0.didReceive(result, target: target) } + completion(result) case .networkError(let error): let error = MoyaError.underlying(error, nil) plugins.forEach { $0.didReceive(.failure(error), target: target) } diff --git a/Tests/MoyaProviderSpec.swift b/Tests/MoyaProviderSpec.swift index 1fe154a27..b3b08a244 100644 --- a/Tests/MoyaProviderSpec.swift +++ b/Tests/MoyaProviderSpec.swift @@ -409,10 +409,9 @@ final class MoyaProviderSpec: QuickSpec { } it("returns identical sample response") { - let response = HTTPURLResponse(url: URL(string: "http://example.com")!, mimeType: nil, expectedContentLength: 0, textEncodingName: nil) + let response = HTTPURLResponse(url: URL(string: "http://example.com")!, statusCode: 200, httpVersion: nil, headerFields: nil)! let endpointResolution: MoyaProvider.EndpointClosure = { target in - let url = target.baseURL.appendingPathComponent(target.path).absoluteString - return Endpoint(url: url, sampleResponseClosure: { .response(response, Data()) }, method: target.method, task: target.task, httpHeaderFields: target.headers) + return Endpoint(url: URL(target: target).absoluteString, sampleResponseClosure: { .response(response, target.sampleData) }, method: target.method, task: target.task, httpHeaderFields: target.headers) } let provider = MoyaProvider(endpointClosure: endpointResolution, stubClosure: MoyaProvider.immediatelyStub) @@ -603,7 +602,7 @@ final class MoyaProviderSpec: QuickSpec { } } - expect(dataString) == "sample data" + expect(dataString).to(equal("sample data")) } it("uses correct headers") { @@ -968,5 +967,79 @@ final class MoyaProviderSpec: QuickSpec { } } } + + // Resolves #1592 where validation is not performed on a stubbed request + describe("a provider for stubbed requests with validation") { + var stubbedProvider: MoyaProvider! + + context("response contains invalid status code") { + it("returns an error") { + let endpointClosure = { (target: GitHub) -> Endpoint in + return Endpoint( + url: URL(target: target).absoluteString, + sampleResponseClosure: { .networkResponse(400, target.sampleData) }, + method: target.method, + task: target.task, + httpHeaderFields: target.headers + ) + } + + stubbedProvider = MoyaProvider(endpointClosure: endpointClosure, stubClosure: MoyaProvider.immediatelyStub) + + var receivedError: Error? + var receivedResponse: Response? + + waitUntil { done in + stubbedProvider.request(.zen) { result in + switch result { + case .success(let response): + receivedResponse = response + case .failure(let error): + receivedError = error + } + done() + } + } + + expect(receivedResponse).to(beNil()) + expect(receivedError).toNot(beNil()) + } + } + + context("response contains valid status code") { + it("returns a response") { + let endpointClosure = { (target: GitHub) -> Endpoint in + return Endpoint( + url: URL(target: target).absoluteString, + sampleResponseClosure: { .networkResponse(200, target.sampleData) }, + method: target.method, + task: target.task, + httpHeaderFields: target.headers + ) + } + + stubbedProvider = MoyaProvider(endpointClosure: endpointClosure, stubClosure: MoyaProvider.immediatelyStub) + + var receivedError: Error? + var receivedResponse: Response? + + waitUntil { done in + stubbedProvider.request(.zen) { result in + switch result { + case .success(let response): + receivedResponse = response + case .failure(let error): + receivedError = error + } + done() + } + } + + expect(receivedResponse).toNot(beNil()) + expect(receivedError).to(beNil()) + expect(GitHub.zen.validationType.statusCodes).to(contain(receivedResponse!.statusCode)) + } + } + } } }