|
|
@@ -26,81 +26,120 @@
|
|
|
import Foundation
|
|
|
import XCTest
|
|
|
|
|
|
+private let fileURL = URL(fileURLWithPath: FileManager.documentsDirectory + "/test_response.json")
|
|
|
+
|
|
|
class StatusCodeValidationTestCase: BaseTestCase {
|
|
|
func testThatValidationForRequestWithAcceptableStatusCodeResponseSucceeds() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/status/200"
|
|
|
- let expectation = self.expectation(description: "request should return 200 status code")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should return 200 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 200 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(statusCode: 200..<300)
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
}
|
|
|
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(statusCode: 200..<300)
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/status/404"
|
|
|
- let expectation = self.expectation(description: "request should return 404 status code")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should return 404 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 404 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(statusCode: [200])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
}
|
|
|
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(statusCode: [200])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
- XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
- XCTAssertEqual(statusCode, 404)
|
|
|
- } else {
|
|
|
- XCTFail("Error should not be nil, should be an AFError, and should have an associated statusCode.")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
+ XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
+ XCTAssertEqual(statusCode, 404)
|
|
|
+ } else {
|
|
|
+ XCTFail("Error should not be nil, should be an AFError, and should have an associated statusCode.")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithNoAcceptableStatusCodesFails() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/status/201"
|
|
|
- let expectation = self.expectation(description: "request should return 201 status code")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should return 201 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 201 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(statusCode: [])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
}
|
|
|
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(statusCode: [])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
- XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
- XCTAssertEqual(statusCode, 201)
|
|
|
- } else {
|
|
|
- XCTFail("Error should not be nil, should be an AFError, and should have an associated statusCode.")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
+ XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
+ XCTAssertEqual(statusCode, 201)
|
|
|
+ } else {
|
|
|
+ XCTFail("Error should not be nil, should be an AFError, and should have an associated statusCode.")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -111,9 +150,12 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
func testThatValidationForRequestWithAcceptableContentTypeResponseSucceeds() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/ip"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return ip")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return ip")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
@@ -121,22 +163,35 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
.validate(contentType: ["application/json;charset=utf8"])
|
|
|
.validate(contentType: ["application/json;q=0.8;charset=utf8"])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: ["application/json"])
|
|
|
+ .validate(contentType: ["application/json;charset=utf8"])
|
|
|
+ .validate(contentType: ["application/json;q=0.8;charset=utf8"])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceeds() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/ip"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return ip")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return ip")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
@@ -144,93 +199,140 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
.validate(contentType: ["application/*"])
|
|
|
.validate(contentType: ["*/json"])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: ["*/*"])
|
|
|
+ .validate(contentType: ["application/*"])
|
|
|
+ .validate(contentType: ["*/json"])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/xml"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return xml")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(contentType: ["application/octet-stream"])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: ["application/octet-stream"])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError {
|
|
|
- XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
- XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
- XCTAssertEqual(error.acceptableContentTypes?.first, "application/octet-stream")
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError {
|
|
|
+ XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
+ XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
+ XCTAssertEqual(error.acceptableContentTypes?.first, "application/octet-stream")
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithNoAcceptableContentTypeResponseFails() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/xml"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return xml")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(contentType: [])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: [])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error, "error should not be nil")
|
|
|
-
|
|
|
- if let error = error as? AFError {
|
|
|
- XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
- XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
- XCTAssertTrue(error.acceptableContentTypes?.isEmpty ?? false)
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError {
|
|
|
+ XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
+ XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
+ XCTAssertTrue(error.acceptableContentTypes?.isEmpty ?? false)
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithNoAcceptableContentTypeResponseSucceedsWhenNoDataIsReturned() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/status/204"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return no data")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return no data")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return no data")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(contentType: [])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: [])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceedsWhenResponseIsNil() {
|
|
|
@@ -243,7 +345,32 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
let task: URLSessionDataTask = queue.syncResult { session.dataTask(with: adaptedRequest) }
|
|
|
|
|
|
let originalTask = DataRequest.Requestable(urlRequest: originalRequest)
|
|
|
- let request = MockRequest(session: session, task: task, originalTask: originalTask)
|
|
|
+ let request = MockDataRequest(session: session, task: task, originalTask: originalTask)
|
|
|
+
|
|
|
+ delegate[request.delegate.task] = request
|
|
|
+
|
|
|
+ if startRequestsImmediately { request.resume() }
|
|
|
+
|
|
|
+ return request
|
|
|
+ }
|
|
|
+
|
|
|
+ override func download(
|
|
|
+ _ urlRequest: URLRequestConvertible,
|
|
|
+ to destination: DownloadRequest.DownloadFileDestination)
|
|
|
+ -> DownloadRequest
|
|
|
+ {
|
|
|
+ let originalRequest = urlRequest.urlRequest
|
|
|
+ let adaptedRequest = originalRequest.adapt(using: adapter)
|
|
|
+
|
|
|
+ var task: URLSessionDownloadTask!
|
|
|
+ queue.sync { task = self.session.downloadTask(with: adaptedRequest) }
|
|
|
+
|
|
|
+ let originalTask = DownloadRequest.Downloadable.request(originalRequest)
|
|
|
+ let request = MockDownloadRequest(session: session, task: task, originalTask: originalTask)
|
|
|
+
|
|
|
+ request.downloadDelegate.downloadTaskDidFinishDownloadingToURL = { session, task, URL in
|
|
|
+ return destination(URL, task.response as! HTTPURLResponse)
|
|
|
+ }
|
|
|
|
|
|
delegate[request.delegate.task] = request
|
|
|
|
|
|
@@ -253,7 +380,18 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- class MockRequest: DataRequest {
|
|
|
+ class MockDataRequest: DataRequest {
|
|
|
+ override var response: HTTPURLResponse? {
|
|
|
+ return MockHTTPURLResponse(
|
|
|
+ url: URL(string: request!.urlString)!,
|
|
|
+ statusCode: 204,
|
|
|
+ httpVersion: "HTTP/1.1",
|
|
|
+ headerFields: nil
|
|
|
+ )
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ class MockDownloadRequest: DownloadRequest {
|
|
|
override var response: HTTPURLResponse? {
|
|
|
return MockHTTPURLResponse(
|
|
|
url: URL(string: request!.urlString)!,
|
|
|
@@ -280,27 +418,44 @@ class ContentTypeValidationTestCase: BaseTestCase {
|
|
|
}()
|
|
|
|
|
|
let urlString = "https://httpbin.org/delete"
|
|
|
- let expectation = self.expectation(description: "request should be stubbed and return 204 status code")
|
|
|
|
|
|
- var response: DefaultDataResponse?
|
|
|
+ let expectation1 = self.expectation(description: "request should be stubbed and return 204 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should be stubbed and return 204 status code")
|
|
|
+
|
|
|
+ var requestResponse: DefaultDataResponse?
|
|
|
+ var downloadResponse: DefaultDownloadResponse?
|
|
|
|
|
|
// When
|
|
|
manager.request(urlString, withMethod: .delete)
|
|
|
.validate(contentType: ["*/*"])
|
|
|
.response { resp in
|
|
|
- response = resp
|
|
|
- expectation.fulfill()
|
|
|
+ requestResponse = resp
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ manager.download(urlString, to: { _, _ in fileURL }, withMethod: .delete)
|
|
|
+ .validate(contentType: ["*/*"])
|
|
|
+ .response { resp in
|
|
|
+ downloadResponse = resp
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(response?.response)
|
|
|
- XCTAssertNotNil(response?.data)
|
|
|
- XCTAssertNil(response?.error)
|
|
|
+ XCTAssertNotNil(requestResponse?.response)
|
|
|
+ XCTAssertNotNil(requestResponse?.data)
|
|
|
+ XCTAssertNil(requestResponse?.error)
|
|
|
+
|
|
|
+ XCTAssertEqual(requestResponse?.response?.statusCode, 204)
|
|
|
+ XCTAssertNil(requestResponse?.response?.mimeType)
|
|
|
|
|
|
- XCTAssertEqual(response?.response?.statusCode, 204)
|
|
|
- XCTAssertNil(response?.response?.mimeType)
|
|
|
+ XCTAssertNotNil(downloadResponse?.response)
|
|
|
+ XCTAssertNotNil(downloadResponse?.destinationURL)
|
|
|
+ XCTAssertNil(downloadResponse?.error)
|
|
|
+
|
|
|
+ XCTAssertEqual(downloadResponse?.response?.statusCode, 204)
|
|
|
+ XCTAssertNil(downloadResponse?.response?.mimeType)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -310,81 +465,121 @@ class MultipleValidationTestCase: BaseTestCase {
|
|
|
func testThatValidationForRequestWithAcceptableStatusCodeAndContentTypeResponseSucceeds() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/ip"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return ip")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation2 = self.expectation(description: "request should succeed and return ip")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(statusCode: 200..<300)
|
|
|
.validate(contentType: ["application/json"])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(statusCode: 200..<300)
|
|
|
+ .validate(contentType: ["application/json"])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableStatusCodeAndContentTypeResponseFailsWithStatusCodeError() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/xml"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return xml")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(statusCode: 400..<600)
|
|
|
.validate(contentType: ["application/octet-stream"])
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(statusCode: 400..<600)
|
|
|
+ .validate(contentType: ["application/octet-stream"])
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError {
|
|
|
- XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
- XCTAssertEqual(error.responseCode, 200)
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError {
|
|
|
+ XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
+ XCTAssertEqual(error.responseCode, 200)
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableStatusCodeAndContentTypeResponseFailsWithContentTypeError() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/xml"
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return xml")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate(contentType: ["application/octet-stream"])
|
|
|
.validate(statusCode: 400..<600)
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
- }
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(contentType: ["application/octet-stream"])
|
|
|
+ .validate(statusCode: 400..<600)
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError {
|
|
|
- XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
- XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
- XCTAssertEqual(error.acceptableContentTypes?.first, "application/octet-stream")
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError {
|
|
|
+ XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
+ XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
+ XCTAssertEqual(error.acceptableContentTypes?.first, "application/octet-stream")
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -398,49 +593,72 @@ class AutomaticValidationTestCase: BaseTestCase {
|
|
|
var urlRequest = URLRequest(url: url)
|
|
|
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
|
|
|
|
|
|
- let expectation = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return ip")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlRequest)
|
|
|
.validate()
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlRequest, to: { _, _ in fileURL })
|
|
|
+ .validate()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() {
|
|
|
// Given
|
|
|
let urlString = "https://httpbin.org/status/404"
|
|
|
- let expectation = self.expectation(description: "request should return 404 status code")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ let expectation1 = self.expectation(description: "request should return 404 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 404 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlString, withMethod: .get)
|
|
|
.validate()
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
- XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
- XCTAssertEqual(statusCode, 404)
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError, let statusCode = error.responseCode {
|
|
|
+ XCTAssertTrue(error.isUnacceptableStatusCode)
|
|
|
+ XCTAssertEqual(statusCode, 404)
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -450,22 +668,32 @@ class AutomaticValidationTestCase: BaseTestCase {
|
|
|
var urlRequest = URLRequest(url: url)
|
|
|
urlRequest.setValue("application/*", forHTTPHeaderField: "Accept")
|
|
|
|
|
|
- let expectation = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return ip")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return ip")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlRequest)
|
|
|
.validate()
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlRequest, to: { _, _ in fileURL })
|
|
|
+ .validate()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithAcceptableComplexContentTypeResponseSucceeds() {
|
|
|
@@ -476,22 +704,32 @@ class AutomaticValidationTestCase: BaseTestCase {
|
|
|
let headerValue = "text/xml, application/xml, application/xhtml+xml, text/html;q=0.9, text/plain;q=0.8,*/*;q=0.5"
|
|
|
urlRequest.setValue(headerValue, forHTTPHeaderField: "Accept")
|
|
|
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "request should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlRequest)
|
|
|
.validate()
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlRequest, to: { _, _ in fileURL })
|
|
|
+ .validate()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNil(error)
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
}
|
|
|
|
|
|
func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() {
|
|
|
@@ -500,29 +738,227 @@ class AutomaticValidationTestCase: BaseTestCase {
|
|
|
var urlRequest = URLRequest(url: url)
|
|
|
urlRequest.setValue("application/json", forHTTPHeaderField: "Accept")
|
|
|
|
|
|
- let expectation = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation1 = self.expectation(description: "request should succeed and return xml")
|
|
|
+ let expectation2 = self.expectation(description: "download should succeed and return xml")
|
|
|
|
|
|
- var error: Error?
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
|
|
|
// When
|
|
|
Alamofire.request(urlRequest)
|
|
|
.validate()
|
|
|
.response { resp in
|
|
|
- error = resp.error
|
|
|
- expectation.fulfill()
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlRequest, to: { _, _ in fileURL })
|
|
|
+ .validate()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ waitForExpectations(timeout: timeout, handler: nil)
|
|
|
+
|
|
|
+ // Then
|
|
|
+ XCTAssertNotNil(requestError)
|
|
|
+ XCTAssertNotNil(downloadError)
|
|
|
+
|
|
|
+ for error in [requestError, downloadError] {
|
|
|
+ if let error = error as? AFError {
|
|
|
+ XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
+ XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
+ XCTAssertEqual(error.acceptableContentTypes?.first, "application/json")
|
|
|
+ } else {
|
|
|
+ XCTFail("error should not be nil")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// MARK: -
|
|
|
+
|
|
|
+private enum ValidationError: Error {
|
|
|
+ case missingData, missingFile, fileReadFailed
|
|
|
+}
|
|
|
+
|
|
|
+extension DataRequest {
|
|
|
+ func validateDataExists() -> Self {
|
|
|
+ return validate { request, response, data in
|
|
|
+ guard data != nil else { return .failure(ValidationError.missingData) }
|
|
|
+ return .success
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func validate(with error: Error) -> Self {
|
|
|
+ return validate { _, _, _ in .failure(error) }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+extension DownloadRequest {
|
|
|
+ func validateDataExists() -> Self {
|
|
|
+ return validate { request, response, fileURL in
|
|
|
+ guard let fileURL = fileURL else { return .failure(ValidationError.missingFile) }
|
|
|
+
|
|
|
+ do {
|
|
|
+ let _ = try Data(contentsOf: fileURL)
|
|
|
+ return .success
|
|
|
+ } catch {
|
|
|
+ return .failure(ValidationError.fileReadFailed)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ func validate(with error: Error) -> Self {
|
|
|
+ return validate { _, _, _ in .failure(error) }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// MARK: -
|
|
|
+
|
|
|
+class CustomValidationTestCase: BaseTestCase {
|
|
|
+ func testThatCustomValidationClosureHasAccessToServerResponseData() {
|
|
|
+ // Given
|
|
|
+ let urlString = "https://httpbin.org/get"
|
|
|
+
|
|
|
+ let expectation1 = self.expectation(description: "request should return 200 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 200 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
+
|
|
|
+ // When
|
|
|
+ Alamofire.request(urlString, withMethod: .get)
|
|
|
+ .validate { request, response, data in
|
|
|
+ guard data != nil else { return .failure(ValidationError.missingData) }
|
|
|
+ return .success
|
|
|
+ }
|
|
|
+ .response { resp in
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate { request, response, fileURL in
|
|
|
+ guard let fileURL = fileURL else { return .failure(ValidationError.missingFile) }
|
|
|
+
|
|
|
+ do {
|
|
|
+ let _ = try Data(contentsOf: fileURL)
|
|
|
+ return .success
|
|
|
+ } catch {
|
|
|
+ return .failure(ValidationError.fileReadFailed)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ waitForExpectations(timeout: timeout, handler: nil)
|
|
|
+
|
|
|
+ // Then
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
+ }
|
|
|
+
|
|
|
+ func testThatCustomValidationCanThrowCustomError() {
|
|
|
+ // Given
|
|
|
+ let urlString = "https://httpbin.org/get"
|
|
|
+
|
|
|
+ let expectation1 = self.expectation(description: "request should return 200 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 200 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
+
|
|
|
+ // When
|
|
|
+ Alamofire.request(urlString, withMethod: .get)
|
|
|
+ .validate { _, _, _ in .failure(ValidationError.missingData) }
|
|
|
+ .validate { _, _, _ in .failure(ValidationError.missingFile) } // should be ignored
|
|
|
+ .response { resp in
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate { _, _, _ in .failure(ValidationError.missingFile) }
|
|
|
+ .validate { _, _, _ in .failure(ValidationError.fileReadFailed) } // should be ignored
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
}
|
|
|
|
|
|
waitForExpectations(timeout: timeout, handler: nil)
|
|
|
|
|
|
// Then
|
|
|
- XCTAssertNotNil(error)
|
|
|
-
|
|
|
- if let error = error as? AFError {
|
|
|
- XCTAssertTrue(error.isUnacceptableContentType)
|
|
|
- XCTAssertEqual(error.responseContentType, "application/xml")
|
|
|
- XCTAssertEqual(error.acceptableContentTypes?.first, "application/json")
|
|
|
- } else {
|
|
|
- XCTFail("error should not be nil")
|
|
|
+ XCTAssertEqual(requestError as? ValidationError, ValidationError.missingData)
|
|
|
+ XCTAssertEqual(downloadError as? ValidationError, ValidationError.missingFile)
|
|
|
+ }
|
|
|
+
|
|
|
+ func testThatValidationExtensionHasAccessToServerResponseData() {
|
|
|
+ // Given
|
|
|
+ let urlString = "https://httpbin.org/get"
|
|
|
+
|
|
|
+ let expectation1 = self.expectation(description: "request should return 200 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 200 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
+
|
|
|
+ // When
|
|
|
+ Alamofire.request(urlString, withMethod: .get)
|
|
|
+ .validateDataExists()
|
|
|
+ .response { resp in
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
}
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validateDataExists()
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ waitForExpectations(timeout: timeout, handler: nil)
|
|
|
+
|
|
|
+ // Then
|
|
|
+ XCTAssertNil(requestError)
|
|
|
+ XCTAssertNil(downloadError)
|
|
|
+ }
|
|
|
+
|
|
|
+ func testThatValidationExtensionCanThrowCustomError() {
|
|
|
+ // Given
|
|
|
+ let urlString = "https://httpbin.org/get"
|
|
|
+
|
|
|
+ let expectation1 = self.expectation(description: "request should return 200 status code")
|
|
|
+ let expectation2 = self.expectation(description: "download should return 200 status code")
|
|
|
+
|
|
|
+ var requestError: Error?
|
|
|
+ var downloadError: Error?
|
|
|
+
|
|
|
+ // When
|
|
|
+ Alamofire.request(urlString, withMethod: .get)
|
|
|
+ .validate(with: ValidationError.missingData)
|
|
|
+ .validate(with: ValidationError.missingFile) // should be ignored
|
|
|
+ .response { resp in
|
|
|
+ requestError = resp.error
|
|
|
+ expectation1.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ Alamofire.download(urlString, to: { _, _ in fileURL }, withMethod: .get)
|
|
|
+ .validate(with: ValidationError.missingFile)
|
|
|
+ .validate(with: ValidationError.fileReadFailed) // should be ignored
|
|
|
+ .response { resp in
|
|
|
+ downloadError = resp.error
|
|
|
+ expectation2.fulfill()
|
|
|
+ }
|
|
|
+
|
|
|
+ waitForExpectations(timeout: timeout, handler: nil)
|
|
|
+
|
|
|
+ // Then
|
|
|
+ XCTAssertEqual(requestError as? ValidationError, ValidationError.missingData)
|
|
|
+ XCTAssertEqual(downloadError as? ValidationError, ValidationError.missingFile)
|
|
|
}
|
|
|
}
|