64 lines
1.9 KiB
Swift
64 lines
1.9 KiB
Swift
import Decoded
|
|
import XCTest
|
|
import Validations
|
|
|
|
final class KeyedFailuresTests: ValidationsTestCase {
|
|
func test_annotatingFailuresWithErrorCodes() throws {
|
|
do {
|
|
let decoded: Decoded<Post> = try decode("""
|
|
{
|
|
"title": "My title",
|
|
"body": "invalid"
|
|
}
|
|
""")
|
|
|
|
// fail the validation on purpose
|
|
_ = try decoded.validated {
|
|
Validator(nestedAt: \.title, failure: Failure1())
|
|
Validator(nestedAt: \.body, failure: Failure2())
|
|
}
|
|
} catch let failures as KeyedFailures {
|
|
let errorOutput = failures.mapFailures(FailureWithCode.init)
|
|
|
|
// encode mapped failures and decode as a dictionary so we can compare with the expected outcome
|
|
let data = try JSONEncoder().encode(errorOutput)
|
|
let dict = try JSONDecoder().decode([String: [FailureWithCode]].self, from: data)
|
|
|
|
XCTAssertEqual(dict, [
|
|
"title": [FailureWithCode(description: "failure1", code: 1)],
|
|
"body": [FailureWithCode(description: "failure2", code: nil)]
|
|
])
|
|
}
|
|
}
|
|
}
|
|
|
|
fileprivate protocol CodedError {
|
|
var errorCode: Int { get }
|
|
}
|
|
|
|
fileprivate struct FailureWithCode: Codable, Equatable {
|
|
let description: String
|
|
let code: Int?
|
|
}
|
|
|
|
extension FailureWithCode {
|
|
init(failure: ValidationFailure) {
|
|
self.code = (failure as? CodedError)?.errorCode
|
|
self.description = String(describing: failure)
|
|
}
|
|
}
|
|
|
|
fileprivate struct Failure1: ValidationFailure, CodedError, CustomStringConvertible {
|
|
let description = "failure1"
|
|
let errorCode = 1
|
|
}
|
|
|
|
fileprivate struct Failure2: ValidationFailure, CustomStringConvertible {
|
|
let description = "failure2"
|
|
}
|
|
|
|
fileprivate struct Post: Decodable {
|
|
let title: Decoded<String>
|
|
let body: Decoded<String>
|
|
}
|