diff --git a/Source/Error.swift b/Source/Error.swift index e02ec4f1b671d0cf1f4e807fb7602472d53a4b84..6d1995ca81308cd820dd18523e2e2e4f30dab696 100644 --- a/Source/Error.swift +++ b/Source/Error.swift @@ -39,6 +39,15 @@ public struct Error { case PropertyListSerializationFailed = -6007 } + /// Custom keys contained within certain NSError `userInfo` dictionaries generated by Alamofire. + public struct UserInfoKeys { + /// The content type user info key for a `.ContentTypeValidationFailed` error stored as a `String` value. + public static let ContentType = "ContentType" + + /// The status code user info key for a `.StatusCodeValidationFailed` error stored as an `Int` value. + public static let StatusCode = "StatusCode" + } + /** Creates an `NSError` with the given error code and failure reason. diff --git a/Source/Validation.swift b/Source/Validation.swift index 63656065600c401e52156f2a35bec518b7806d76..a2ee1ab10c4a6ead1ffd5db9e0588a8598332d3e 100644 --- a/Source/Validation.swift +++ b/Source/Validation.swift @@ -80,7 +80,17 @@ extension Request { return .Success } else { let failureReason = "Response status code was unacceptable: \(response.statusCode)" - return .Failure(Error.error(code: .StatusCodeValidationFailed, failureReason: failureReason)) + + let error = NSError( + domain: Error.Domain, + code: Error.Code.StatusCodeValidationFailed.rawValue, + userInfo: [ + NSLocalizedFailureReasonErrorKey: failureReason, + Error.UserInfoKeys.StatusCode: response.statusCode + ] + ) + + return .Failure(error) } } } @@ -149,18 +159,31 @@ extension Request { } } + let contentType: String let failureReason: String if let responseContentType = response.MIMEType { + contentType = responseContentType + failureReason = ( "Response content type \"\(responseContentType)\" does not match any acceptable " + "content types: \(acceptableContentTypes)" ) } else { + contentType = "" failureReason = "Response content type was missing and acceptable content type does not match \"*/*\"" } - return .Failure(Error.error(code: .ContentTypeValidationFailed, failureReason: failureReason)) + let error = NSError( + domain: Error.Domain, + code: Error.Code.ContentTypeValidationFailed.rawValue, + userInfo: [ + NSLocalizedFailureReasonErrorKey: failureReason, + Error.UserInfoKeys.ContentType: contentType + ] + ) + + return .Failure(error) } } diff --git a/Tests/ValidationTests.swift b/Tests/ValidationTests.swift index 7bdc9555aa801744966565ac56bbbe295abb4a79..1f0acf28a7cb4afbbba11d590479f92e2b8bd43d 100644 --- a/Tests/ValidationTests.swift +++ b/Tests/ValidationTests.swift @@ -43,7 +43,7 @@ class StatusCodeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() { @@ -64,13 +64,14 @@ class StatusCodeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 404) } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } @@ -92,13 +93,14 @@ class StatusCodeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 201) } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } } @@ -126,7 +128,7 @@ class ContentTypeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceeds() { @@ -149,7 +151,7 @@ class ContentTypeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() { @@ -170,13 +172,14 @@ class ContentTypeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml") } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } @@ -201,10 +204,11 @@ class ContentTypeValidationTestCase: BaseTestCase { XCTAssertNotNil(error, "error should not be nil") if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml") } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } @@ -226,7 +230,7 @@ class ContentTypeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithAcceptableWildcardContentTypeResponseSucceedsWhenResponseIsNil() { @@ -297,13 +301,13 @@ class ContentTypeValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(response, "response should not be nil") - XCTAssertNotNil(data, "data should not be nil") - XCTAssertNil(error, "error should be nil") + XCTAssertNotNil(response) + XCTAssertNotNil(data) + XCTAssertNil(error) if let response = response { - XCTAssertEqual(response.statusCode, 204, "response status code should be 204") - XCTAssertNil(response.MIMEType, "response mime type should be nil") + XCTAssertEqual(response.statusCode, 204) + XCTAssertNil(response.MIMEType) } } } @@ -330,7 +334,7 @@ class MultipleValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithUnacceptableStatusCodeAndContentTypeResponseFailsWithStatusCodeError() { @@ -352,13 +356,14 @@ class MultipleValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 200) } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } @@ -381,13 +386,14 @@ class MultipleValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml") } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } } @@ -416,7 +422,7 @@ class AutomaticValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithUnacceptableStatusCodeResponseFails() { @@ -437,13 +443,14 @@ class AutomaticValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue, "code should be status code validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.StatusCodeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.StatusCode] as? Int, 404) } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } @@ -468,7 +475,7 @@ class AutomaticValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithAcceptableComplexContentTypeResponseSucceeds() { @@ -494,7 +501,7 @@ class AutomaticValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNil(error, "error should be nil") + XCTAssertNil(error) } func testThatValidationForRequestWithUnacceptableContentTypeResponseFails() { @@ -518,13 +525,14 @@ class AutomaticValidationTestCase: BaseTestCase { waitForExpectationsWithTimeout(timeout, handler: nil) // Then - XCTAssertNotNil(error, "error should not be nil") + XCTAssertNotNil(error) if let error = error { - XCTAssertEqual(error.domain, Error.Domain, "domain should be Alamofire error domain") - XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue, "code should be content type validation failure") + XCTAssertEqual(error.domain, Error.Domain) + XCTAssertEqual(error.code, Error.Code.ContentTypeValidationFailed.rawValue) + XCTAssertEqual(error.userInfo[Error.UserInfoKeys.ContentType] as? String, "application/xml") } else { - XCTFail("error should be an NSError") + XCTFail("error should not be nil") } } }