mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
123 lines
3.8 KiB
Swift
123 lines
3.8 KiB
Swift
//
|
|
// DocumentCompare.swift
|
|
// JSONAPITesting
|
|
//
|
|
// Created by Mathew Polzin on 11/4/19.
|
|
//
|
|
|
|
import JSONAPI
|
|
|
|
public struct DocumentComparison: Equatable, PropertyComparable {
|
|
public let apiDescription: Comparison
|
|
public let body: BodyComparison
|
|
|
|
init(apiDescription: Comparison, body: BodyComparison) {
|
|
self.apiDescription = apiDescription
|
|
self.body = body
|
|
}
|
|
|
|
public var differences: NamedDifferences {
|
|
return Dictionary(
|
|
[
|
|
apiDescription != .same ? ("API Description", apiDescription.rawValue) : nil,
|
|
body != .same ? ("Body", body.rawValue) : nil
|
|
].compactMap { $0 },
|
|
uniquingKeysWith: { $1 }
|
|
)
|
|
}
|
|
}
|
|
|
|
public enum BodyComparison: Equatable, CustomStringConvertible {
|
|
case same
|
|
case dataErrorMismatch(errorOnLeft: Bool)
|
|
case differentErrors(ErrorComparison)
|
|
case differentData(DocumentDataComparison)
|
|
|
|
public typealias ErrorComparison = [Comparison]
|
|
|
|
static func compare<E: JSONAPIError, M: JSONAPI.Meta, L: JSONAPI.Links>(errors errors1: [E], _ meta1: M?, _ links1: L?, with errors2: [E], _ meta2: M?, _ links2: L?) -> ErrorComparison {
|
|
return errors1.compare(
|
|
to: errors2,
|
|
using: { error1, error2 in
|
|
guard error1 != error2 else {
|
|
return .same
|
|
}
|
|
|
|
return .differentValues(
|
|
String(describing: error1),
|
|
String(describing: error2)
|
|
)
|
|
}
|
|
).map(Comparison.init) + [
|
|
Comparison(meta1, meta2),
|
|
Comparison(links1, links2)
|
|
]
|
|
}
|
|
|
|
public var description: String {
|
|
switch self {
|
|
case .same:
|
|
return "same"
|
|
case .dataErrorMismatch(errorOnLeft: let errorOnLeft):
|
|
let errorString = "error response"
|
|
let dataString = "data response"
|
|
let left = errorOnLeft ? errorString : dataString
|
|
let right = errorOnLeft ? dataString : errorString
|
|
|
|
return "\(left) ≠ \(right)"
|
|
case .differentErrors(let comparisons):
|
|
return comparisons
|
|
.filter { !$0.isSame }
|
|
.map { $0.rawValue }
|
|
.sorted()
|
|
.joined(separator: ", ")
|
|
case .differentData(let comparison):
|
|
return comparison.rawValue
|
|
}
|
|
}
|
|
|
|
public var rawValue: String { description }
|
|
}
|
|
|
|
extension EncodableJSONAPIDocument where Body: Equatable, PrimaryResourceBody: _OptionalResourceBody {
|
|
public func compare(to other: Self) -> DocumentComparison {
|
|
return DocumentComparison(
|
|
apiDescription: Comparison(
|
|
String(describing: apiDescription),
|
|
String(describing: other.apiDescription)
|
|
),
|
|
body: body.compare(to: other.body)
|
|
)
|
|
}
|
|
}
|
|
|
|
extension DocumentBody where Self: Equatable, PrimaryResourceBody: _OptionalResourceBody {
|
|
public func compare(to other: Self) -> BodyComparison {
|
|
|
|
// rule out case where they are the same
|
|
guard self != other else {
|
|
return .same
|
|
}
|
|
|
|
// rule out case where they are both error bodies
|
|
if let errors1 = errors, let errors2 = other.errors {
|
|
return .differentErrors(
|
|
BodyComparison.compare(
|
|
errors: errors1, meta, links,
|
|
with: errors2, meta, links
|
|
)
|
|
)
|
|
}
|
|
|
|
// rule out the case where they are both data
|
|
if let data1 = data, let data2 = other.data {
|
|
return .differentData(data1.compare(to: data2))
|
|
}
|
|
|
|
// we are left with the case where one is data and the
|
|
// other is an error if self.isError, then "the error
|
|
// is on the left"
|
|
return .dataErrorMismatch(errorOnLeft: isError)
|
|
}
|
|
}
|