mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
going through and fleshing out tests. minor adjustments and bug fixes.
This commit is contained in:
@@ -494,6 +494,10 @@ extension Document {
|
||||
public static func ==(lhs: Document, rhs: ErrorDocument) -> Bool {
|
||||
return lhs == rhs.document
|
||||
}
|
||||
|
||||
public static func ==(lhs: ErrorDocument, rhs: Document) -> Bool {
|
||||
return lhs.document == rhs
|
||||
}
|
||||
}
|
||||
|
||||
/// A Document that only supports success bodies. This is useful if you wish to pass around a
|
||||
@@ -534,7 +538,7 @@ extension Document {
|
||||
/// `nil` if the Document is an error response. Otherwise,
|
||||
/// a structure containing the primary resource, any included
|
||||
/// resources, metadata, and links.
|
||||
var data: BodyData? {
|
||||
public var data: BodyData? {
|
||||
return document.body.data
|
||||
}
|
||||
|
||||
@@ -545,7 +549,7 @@ extension Document {
|
||||
/// resources dependening on the `PrimaryResourceBody` type.
|
||||
///
|
||||
/// See `SingleResourceBody` and `ManyResourceBody`.
|
||||
var primaryResource: PrimaryResourceBody? {
|
||||
public var primaryResource: PrimaryResourceBody? {
|
||||
return document.body.primaryResource
|
||||
}
|
||||
|
||||
@@ -553,25 +557,29 @@ extension Document {
|
||||
///
|
||||
/// `nil` if the Document is an error document. Otherwise,
|
||||
/// zero or more includes.
|
||||
var includes: Includes<IncludeType>? {
|
||||
public var includes: Includes<IncludeType>? {
|
||||
return document.body.includes
|
||||
}
|
||||
|
||||
/// The metadata for the error or data document or `nil` if
|
||||
/// no metadata is found.
|
||||
var meta: MetaType? {
|
||||
public var meta: MetaType? {
|
||||
return document.body.meta
|
||||
}
|
||||
|
||||
/// The links for the error or data document or `nil` if
|
||||
/// no links are found.
|
||||
var links: LinksType? {
|
||||
public var links: LinksType? {
|
||||
return document.body.links
|
||||
}
|
||||
|
||||
public static func ==(lhs: Document, rhs: SuccessDocument) -> Bool {
|
||||
return lhs == rhs.document
|
||||
}
|
||||
|
||||
public static func ==(lhs: SuccessDocument, rhs: Document) -> Bool {
|
||||
return lhs.document == rhs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// Created by Mathew Polzin on 11/24/18.
|
||||
//
|
||||
|
||||
/// A Links structure should contain nothing but JSONAPI.Link properties.
|
||||
/// A Links structure should contain nothing but `JSONAPI.Link` properties.
|
||||
public protocol Links: Codable, Equatable {}
|
||||
|
||||
/// Use NoLinks where no links should belong to a JSON API component
|
||||
|
||||
@@ -109,11 +109,11 @@ extension ResourceObjectDecodingError: CustomStringConvertible {
|
||||
case .keyNotFound:
|
||||
return "'\(subjectName)' \(location.singular) is required and missing."
|
||||
case .valueNotFound where location == .type:
|
||||
return "'type' (a.k.a. JSON:API type name) is not nullable but null was found."
|
||||
return "'\(location.singular)' (a.k.a. JSON:API type name) is not nullable but null was found."
|
||||
case .valueNotFound:
|
||||
return "'\(subjectName)' \(location.singular) is not nullable but null was found."
|
||||
case .typeMismatch(expectedTypeName: let expected) where location == .type:
|
||||
return "'type' (a.k.a. the JSON:API type name) is not a \(expected) as expected."
|
||||
return "'\(location.singular)' (a.k.a. the JSON:API type name) is not a \(expected) as expected."
|
||||
case .typeMismatch(expectedTypeName: let expected):
|
||||
return "'\(subjectName)' \(location.singular) is not a \(expected) as expected."
|
||||
case .jsonTypeMismatch(expectedType: let expected, foundType: let found) where location == .type:
|
||||
|
||||
@@ -14,17 +14,6 @@ public enum ArrayElementComparison: Equatable, CustomStringConvertible {
|
||||
case differentValues(String, String)
|
||||
case prebuilt(String)
|
||||
|
||||
public init(sameTypeComparison: BasicComparison) {
|
||||
switch sameTypeComparison {
|
||||
case .same:
|
||||
self = .same
|
||||
case .different(let one, let two):
|
||||
self = .differentValues(one, two)
|
||||
case .prebuilt(let str):
|
||||
self = .prebuilt(str)
|
||||
}
|
||||
}
|
||||
|
||||
public init(resourceObjectComparison: ResourceObjectComparison) {
|
||||
guard !resourceObjectComparison.isSame else {
|
||||
self = .same
|
||||
|
||||
@@ -33,10 +33,10 @@ public enum BodyComparison: Equatable, CustomStringConvertible {
|
||||
case differentErrors(ErrorComparison)
|
||||
case differentData(DocumentDataComparison)
|
||||
|
||||
public typealias ErrorComparison = [BasicComparison]
|
||||
public typealias ErrorComparison = [String: BasicComparison]
|
||||
|
||||
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(
|
||||
let errorComparisons = errors1.compare(
|
||||
to: errors2,
|
||||
using: { error1, error2 in
|
||||
guard error1 != error2 else {
|
||||
@@ -48,9 +48,19 @@ public enum BodyComparison: Equatable, CustomStringConvertible {
|
||||
String(describing: error2)
|
||||
)
|
||||
}
|
||||
).map(BasicComparison.init) + [
|
||||
BasicComparison(meta1, meta2),
|
||||
BasicComparison(links1, links2)
|
||||
).map(BasicComparison.init)
|
||||
.filter { !$0.isSame }
|
||||
.map { $0.rawValue }
|
||||
.joined(separator: ", ")
|
||||
|
||||
let errorComparisonString = errorComparisons.isEmpty
|
||||
? nil
|
||||
: errorComparisons
|
||||
|
||||
return [
|
||||
"Errors": errorComparisonString.map { BasicComparison.prebuilt("(\($0))") } ?? .same,
|
||||
"Metadata": BasicComparison(meta1, meta2),
|
||||
"Links": BasicComparison(links1, links2)
|
||||
]
|
||||
}
|
||||
|
||||
@@ -67,8 +77,8 @@ public enum BodyComparison: Equatable, CustomStringConvertible {
|
||||
return "\(left) ≠ \(right)"
|
||||
case .differentErrors(let comparisons):
|
||||
return comparisons
|
||||
.filter { !$0.isSame }
|
||||
.map { $0.rawValue }
|
||||
.filter { !$0.value.isSame }
|
||||
.map { "\($0.key): \($0.value.rawValue)" }
|
||||
.sorted()
|
||||
.joined(separator: ", ")
|
||||
case .differentData(let comparison):
|
||||
@@ -104,7 +114,7 @@ extension DocumentBody where Self: Equatable, PrimaryResourceBody: TestableResou
|
||||
return .differentErrors(
|
||||
BodyComparison.compare(
|
||||
errors: errors1, meta, links,
|
||||
with: errors2, meta, links
|
||||
with: errors2, other.meta, other.links
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// RelationshipsCompare.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/3/19.
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// ArrayCompareTests.swift
|
||||
// JSONAPITestingTests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/14/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import JSONAPITesting
|
||||
|
||||
final class ArrayCompareTests: XCTestCase {
|
||||
func test_same() {
|
||||
let arr1 = ["a", "b", "c"]
|
||||
let arr2 = ["a", "b", "c"]
|
||||
|
||||
let comparison = arr1.compare(to: arr2) { str1, str2 in
|
||||
str1 == str2 ? .same : .differentValues(str1, str2)
|
||||
}
|
||||
|
||||
XCTAssertEqual(
|
||||
comparison,
|
||||
[.same, .same, .same]
|
||||
)
|
||||
|
||||
XCTAssertEqual(comparison.map { $0.description }, ["same", "same", "same"])
|
||||
|
||||
XCTAssertEqual(comparison.map(BasicComparison.init(reducing:)), [.same, .same, .same])
|
||||
|
||||
XCTAssertEqual(comparison.map(BasicComparison.init(reducing:)).map { $0.description }, ["same", "same", "same"])
|
||||
}
|
||||
|
||||
func test_differentLengths() {
|
||||
let arr1 = ["a", "b", "c"]
|
||||
let arr2 = ["a", "b"]
|
||||
|
||||
let comparison1 = arr1.compare(to: arr2) { str1, str2 in
|
||||
str1 == str2 ? .same : .differentValues(str1, str2)
|
||||
}
|
||||
|
||||
XCTAssertEqual(
|
||||
comparison1,
|
||||
[.same, .same, .missing]
|
||||
)
|
||||
|
||||
XCTAssertEqual(comparison1.map { $0.description }, ["same", "same", "missing"])
|
||||
|
||||
XCTAssertEqual(comparison1.map(BasicComparison.init(reducing:)), [.same, .same, .different("array length 1", "array length 2")])
|
||||
|
||||
let comparison2 = arr2.compare(to: arr1) { str1, str2 in
|
||||
str1 == str2 ? .same : .differentValues(str1, str2)
|
||||
}
|
||||
|
||||
XCTAssertEqual(
|
||||
comparison2,
|
||||
[.same, .same, .missing]
|
||||
)
|
||||
|
||||
XCTAssertEqual(comparison2.map { $0.description }, ["same", "same", "missing"])
|
||||
|
||||
XCTAssertEqual(comparison2.map(BasicComparison.init(reducing:)), [.same, .same, .different("array length 1", "array length 2")])
|
||||
}
|
||||
|
||||
func test_differentValues() {
|
||||
let arr1 = ["c", "b", "a"]
|
||||
let arr2 = ["a", "b", "c"]
|
||||
|
||||
let comparison = arr1.compare(to: arr2) { str1, str2 in
|
||||
str1 == str2 ? .same : .differentValues(str1, str2)
|
||||
}
|
||||
|
||||
XCTAssertEqual(
|
||||
comparison,
|
||||
[.differentValues("c", "a"), .same, .differentValues("a", "c")]
|
||||
)
|
||||
|
||||
XCTAssertEqual(comparison.map { $0.description }, ["c ≠ a", "same", "a ≠ c"])
|
||||
}
|
||||
|
||||
func test_reducePrebuilt() {
|
||||
let prebuilt = ArrayElementComparison.prebuilt("hello world")
|
||||
|
||||
XCTAssertEqual(BasicComparison(reducing: prebuilt), .prebuilt("hello world"))
|
||||
|
||||
XCTAssertEqual(BasicComparison(reducing: prebuilt).description, "hello world")
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,14 @@ import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class AttributesCompareTests: XCTestCase {
|
||||
func test_sameAttributes() {
|
||||
func test_sameAttributes() throws {
|
||||
let attr1 = TestAttributes(
|
||||
string: "hello world",
|
||||
int: 10,
|
||||
bool: true,
|
||||
double: 105.4,
|
||||
struct: .init(value: .init())
|
||||
struct: .init(value: .init()),
|
||||
transformed: try .init(rawValue: 10)
|
||||
)
|
||||
let attr2 = attr1
|
||||
|
||||
@@ -25,24 +26,27 @@ final class AttributesCompareTests: XCTestCase {
|
||||
"int": .same,
|
||||
"bool": .same,
|
||||
"double": .same,
|
||||
"struct": .same
|
||||
"struct": .same,
|
||||
"transformed": .same
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentAttributes() {
|
||||
func test_differentAttributes() throws {
|
||||
let attr1 = TestAttributes(
|
||||
string: "hello world",
|
||||
int: 10,
|
||||
bool: true,
|
||||
double: 105.4,
|
||||
struct: .init(value: .init())
|
||||
struct: .init(value: .init()),
|
||||
transformed: try .init(rawValue: 10)
|
||||
)
|
||||
let attr2 = TestAttributes(
|
||||
string: "hello",
|
||||
int: 11,
|
||||
bool: false,
|
||||
double: 1.4,
|
||||
struct: .init(value: .init(val: "there"))
|
||||
struct: .init(value: .init(val: "there")),
|
||||
transformed: try .init(rawValue: 11)
|
||||
)
|
||||
|
||||
XCTAssertEqual(attr1.compare(to: attr2), [
|
||||
@@ -50,7 +54,8 @@ final class AttributesCompareTests: XCTestCase {
|
||||
"int": .different("10", "11"),
|
||||
"bool": .different("true", "false"),
|
||||
"double": .different("105.4", "1.4"),
|
||||
"struct": .different("string: hello", "string: there")
|
||||
"struct": .different("string: hello", "string: there"),
|
||||
"transformed": .different("10", "11")
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -61,6 +66,7 @@ private struct TestAttributes: JSONAPI.Attributes {
|
||||
let bool: Attribute<Bool>
|
||||
let double: Attribute<Double>
|
||||
let `struct`: Attribute<Struct>
|
||||
let transformed: TransformedAttribute<Int, TestTransformer>
|
||||
|
||||
struct Struct: Equatable, Codable, CustomStringConvertible {
|
||||
let string: String
|
||||
@@ -72,3 +78,9 @@ private struct TestAttributes: JSONAPI.Attributes {
|
||||
var description: String { return "string: \(string)" }
|
||||
}
|
||||
}
|
||||
|
||||
private enum TestTransformer: Transformer {
|
||||
static func transform(_ value: Int) throws -> String {
|
||||
return "\(value)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,33 @@ final class DocumentCompareTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_differentErrors() {
|
||||
XCTAssertEqual(d2.compare(to: d4).differences, [
|
||||
"Body": "status: 500, title: Internal Error ≠ status: 404, title: Not Found"
|
||||
let comparison = d2.compare(to: d4)
|
||||
XCTAssertEqual(comparison.differences, [
|
||||
"Body": "Errors: (status: 500, title: Internal Error ≠ status: 404, title: Not Found)"
|
||||
])
|
||||
|
||||
XCTAssertEqual(String(describing: comparison), "(Body: Errors: (status: 500, title: Internal Error ≠ status: 404, title: Not Found))")
|
||||
}
|
||||
|
||||
func test_sameErrorsDifferentMetadata() {
|
||||
let errors = [
|
||||
BasicJSONAPIError<String>.error(.init(id: nil, status: "500", title: "Internal Error"))
|
||||
]
|
||||
let doc1 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "1", meta: .none),
|
||||
errors: errors,
|
||||
meta: nil,
|
||||
links: nil
|
||||
)
|
||||
let doc2 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "1", meta: .none),
|
||||
errors: errors,
|
||||
meta: .init(total: 11),
|
||||
links: nil
|
||||
)
|
||||
|
||||
XCTAssertEqual(doc1.compare(to: doc2).differences, [
|
||||
"Body": "Metadata: nil ≠ Optional(total: 11)"
|
||||
])
|
||||
}
|
||||
|
||||
@@ -60,6 +85,24 @@ final class DocumentCompareTests: XCTestCase {
|
||||
"Body": ##"(Primary Resource: (resource 1: 'age' attribute: 10 ≠ 12, 'bestFriend' relationship: Optional(Id(2)) ≠ nil, 'favoriteColor' attribute: nil ≠ Optional("blue"), 'name' attribute: name ≠ Fig, id: 1 ≠ 5))"##
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentMetadata() {
|
||||
XCTAssertEqual(d11.compare(to: d12).differences, [
|
||||
"Body": "(Meta: total: 10 ≠ total: 10000)"
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentLinks() {
|
||||
XCTAssertEqual(d11.compare(to: d13).differences, [
|
||||
"Body": ##"(Links: TestLinks(link: JSONAPI.Link<Swift.String, JSONAPI.NoMetadata>(url: "http://google.com", meta: No Metadata)) ≠ TestLinks(link: JSONAPI.Link<Swift.String, JSONAPI.NoMetadata>(url: "http://yahoo.com", meta: No Metadata)))"##
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentAPIDescription() {
|
||||
XCTAssertEqual(d11.compare(to: d14).differences, [
|
||||
"API Description": ##"APIDescription<NoMetadata>(version: "10", meta: No Metadata) ≠ APIDescription<NoMetadata>(version: "1", meta: No Metadata)"##
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate enum TestDescription: JSONAPI.ResourceObjectDescription {
|
||||
@@ -98,6 +141,22 @@ fileprivate typealias TestType2 = ResourceObject<TestDescription2, NoMetadata, N
|
||||
|
||||
fileprivate typealias SingleDocument = JSONAPI.Document<SingleResourceBody<TestType>, NoMetadata, NoLinks, Include2<TestType, TestType2>, NoAPIDescription, BasicJSONAPIError<String>>
|
||||
|
||||
fileprivate struct TestMetadata: JSONAPI.Meta, CustomStringConvertible {
|
||||
let total: Int
|
||||
|
||||
var description: String {
|
||||
"total: \(total)"
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate struct TestLinks: JSONAPI.Links {
|
||||
let link: Link<String, NoMetadata>
|
||||
}
|
||||
|
||||
typealias TestAPIDescription = APIDescription<NoMetadata>
|
||||
|
||||
fileprivate typealias SingleDocumentWithMetaAndLinks = JSONAPI.Document<SingleResourceBody<TestType>, TestMetadata, TestLinks, Include2<TestType, TestType2>, TestAPIDescription, BasicJSONAPIError<String>>
|
||||
|
||||
fileprivate typealias OptionalSingleDocument = JSONAPI.Document<SingleResourceBody<TestType?>, NoMetadata, NoLinks, Include2<TestType, TestType2>, NoAPIDescription, BasicJSONAPIError<String>>
|
||||
|
||||
fileprivate typealias ManyDocument = JSONAPI.Document<ManyResourceBody<TestType>, NoMetadata, NoLinks, Include2<TestType, TestType2>, NoAPIDescription, BasicJSONAPIError<String>>
|
||||
@@ -220,3 +279,35 @@ fileprivate let d10 = SingleDocument(
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let d11 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "10", meta: .none),
|
||||
body: .init(resourceObject: r2),
|
||||
includes: .none,
|
||||
meta: TestMetadata(total: 10),
|
||||
links: TestLinks(link: .init(url: "http://google.com"))
|
||||
)
|
||||
|
||||
fileprivate let d12 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "10", meta: .none),
|
||||
body: .init(resourceObject: r2),
|
||||
includes: .none,
|
||||
meta: TestMetadata(total: 10000),
|
||||
links: TestLinks(link: .init(url: "http://google.com"))
|
||||
)
|
||||
|
||||
fileprivate let d13 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "10", meta: .none),
|
||||
body: .init(resourceObject: r2),
|
||||
includes: .none,
|
||||
meta: TestMetadata(total: 10),
|
||||
links: TestLinks(link: .init(url: "http://yahoo.com"))
|
||||
)
|
||||
|
||||
fileprivate let d14 = SingleDocumentWithMetaAndLinks(
|
||||
apiDescription: TestAPIDescription(version: "1", meta: .none),
|
||||
body: .init(resourceObject: r2),
|
||||
includes: .none,
|
||||
meta: TestMetadata(total: 10),
|
||||
links: TestLinks(link: .init(url: "http://google.com"))
|
||||
)
|
||||
|
||||
@@ -10,5 +10,23 @@ import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class RelationshipsCompareTests: XCTestCase {
|
||||
// TODO: write tests
|
||||
func test_same() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentIds() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentTypes() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentMetadata() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentLinks() {
|
||||
// TODO: write tests
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// File.swift
|
||||
// ResourceObjectCompareTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/3/19.
|
||||
@@ -15,11 +15,31 @@ final class ResourceObjectCompareTests: XCTestCase {
|
||||
XCTAssertTrue(test2.compare(to: test2).differences.isEmpty)
|
||||
}
|
||||
|
||||
func test_different() {
|
||||
func test_differentAttributes() {
|
||||
// TODO: write actual test
|
||||
print(test1.compare(to: test2).differences.map { "\($0): \($1)" }.joined(separator: ", "))
|
||||
}
|
||||
|
||||
func test_differentRelationships() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentTypes() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentIds() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentMetadata() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
func test_differentLinks() {
|
||||
// TODO: write test
|
||||
}
|
||||
|
||||
fileprivate let test1 = TestType(
|
||||
id: "2",
|
||||
attributes: .init(
|
||||
|
||||
@@ -12,3 +12,5 @@ public typealias Entity<Description: JSONAPI.ResourceObjectDescription, Meta: JS
|
||||
public typealias BasicEntity<Description: JSONAPI.ResourceObjectDescription> = Entity<Description, NoMetadata, NoLinks>
|
||||
|
||||
public typealias NewEntity<Description: JSONAPI.ResourceObjectDescription, Meta: JSONAPI.Meta, Links: JSONAPI.Links> = JSONAPI.ResourceObject<Description, Meta, Links, Unidentified>
|
||||
|
||||
extension String: JSONAPI.JSONAPIURL {}
|
||||
|
||||
@@ -14,6 +14,10 @@ class AttributeTests: XCTestCase {
|
||||
XCTAssertEqual(Attribute<String>(value: "hello").value, "hello")
|
||||
}
|
||||
|
||||
func test_AttributeRawType() {
|
||||
XCTAssert(Attribute<String>(value: "hello").rawValueType == String.self)
|
||||
}
|
||||
|
||||
func test_TransformedAttributeNoThrow() {
|
||||
XCTAssertNoThrow(try TransformedAttribute<String, TestTransformer>(rawValue: "10"))
|
||||
}
|
||||
@@ -26,6 +30,10 @@ class AttributeTests: XCTestCase {
|
||||
XCTAssertNoThrow(try TransformedAttribute<String, TestTransformer>(transformedValue: 10))
|
||||
}
|
||||
|
||||
func test_TransformedAttributeRawType() throws {
|
||||
try XCTAssert(TransformedAttribute<String, TestTransformer>(rawValue: "10").rawValueType == String.self)
|
||||
}
|
||||
|
||||
func test_EncodedPrimitives() {
|
||||
testEncodedPrimitive(attribute: Attribute<Int>(value: 10))
|
||||
testEncodedPrimitive(attribute: Attribute<Bool>(value: false))
|
||||
|
||||
@@ -120,6 +120,28 @@ found JSON:API type "not_an_author" but expected "authors"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func test_wantSuccess_foundError() {
|
||||
XCTAssertThrowsError(
|
||||
try testDecoder.decode(
|
||||
Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.SuccessDocument.self,
|
||||
from: error_document_no_metadata
|
||||
)
|
||||
) { error in
|
||||
XCTAssertEqual(String(describing: error), #"Expected a success document with a 'data' property but found an error document."#)
|
||||
}
|
||||
}
|
||||
|
||||
func test_wantError_foundSuccess() {
|
||||
XCTAssertThrowsError(
|
||||
try testDecoder.decode(
|
||||
Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.ErrorDocument.self,
|
||||
from: single_document_some_includes_with_metadata_with_api_description
|
||||
)
|
||||
) { error in
|
||||
XCTAssertEqual(String(describing: error), #"Expected an error document but found a success document with a 'data' property."#)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test Types
|
||||
|
||||
@@ -1554,5 +1554,3 @@ extension DocumentTests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension String: JSONAPI.JSONAPIURL {}
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
//
|
||||
// SuccessAndErrorDocumentTests.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/12/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
|
||||
final class SuccessAndErrorDocumentTests: XCTestCase {
|
||||
func test_errorAccessors() {
|
||||
let apiDescription = TestErrorDocument.APIDescription(
|
||||
version: "1.0",
|
||||
meta: .none
|
||||
)
|
||||
let errors = [
|
||||
BasicJSONAPIError<String>.error(.init(status: "500"))
|
||||
]
|
||||
let meta = TestMeta(hello: "world")
|
||||
let links = TestLinks(testLink: .init(url: "http://google.com"))
|
||||
let errorDoc = TestErrorDocument(
|
||||
apiDescription: apiDescription,
|
||||
errors: errors,
|
||||
meta: meta,
|
||||
links: links
|
||||
)
|
||||
|
||||
guard case let .errors(testErrors, meta: testMeta, links: testLinks) = errorDoc.body else {
|
||||
XCTFail("Expected an error body")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(testErrors, errors)
|
||||
XCTAssertEqual(testMeta, meta)
|
||||
XCTAssertEqual(testLinks, links)
|
||||
|
||||
XCTAssertEqual(errorDoc.apiDescription, apiDescription)
|
||||
XCTAssertEqual(errorDoc.errors, errors)
|
||||
XCTAssertEqual(errorDoc.meta, meta)
|
||||
XCTAssertEqual(errorDoc.links, links)
|
||||
|
||||
let equivalentDocument = TestDocument(
|
||||
apiDescription: apiDescription,
|
||||
errors: errors,
|
||||
meta: meta,
|
||||
links: links
|
||||
)
|
||||
|
||||
XCTAssert(equivalentDocument == errorDoc)
|
||||
XCTAssert(errorDoc == equivalentDocument)
|
||||
}
|
||||
|
||||
func test_successAccessors() {
|
||||
let apiDescription = TestErrorDocument.APIDescription(
|
||||
version: "1.0",
|
||||
meta: .none
|
||||
)
|
||||
let primaryResource = TestType(
|
||||
id: "123",
|
||||
attributes: .none,
|
||||
relationships: .none,
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
let resourceBody = SingleResourceBody(resourceObject: primaryResource)
|
||||
let includedResource = TestType(
|
||||
id: "456",
|
||||
attributes: .none,
|
||||
relationships: .none,
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
let includes = Includes<TestDocument.Include>(values: [.init(includedResource)])
|
||||
let meta = TestMeta(hello: "world")
|
||||
let links = TestLinks(testLink: .init(url: "http://google.com"))
|
||||
let successDoc = TestSuccessDocument(
|
||||
apiDescription: apiDescription,
|
||||
body: resourceBody,
|
||||
includes: includes,
|
||||
meta: meta,
|
||||
links: links
|
||||
)
|
||||
|
||||
guard case let .data(data) = successDoc.body else {
|
||||
XCTFail("Expected an data body")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(data.primary, resourceBody)
|
||||
XCTAssertEqual(data.includes, includes)
|
||||
XCTAssertEqual(data.meta, meta)
|
||||
XCTAssertEqual(data.links, links)
|
||||
|
||||
XCTAssertEqual(successDoc.data, data)
|
||||
XCTAssertEqual(successDoc.apiDescription, apiDescription)
|
||||
XCTAssertEqual(successDoc.primaryResource, resourceBody)
|
||||
XCTAssertEqual(successDoc.includes, includes)
|
||||
XCTAssertEqual(successDoc.meta, meta)
|
||||
XCTAssertEqual(successDoc.links, links)
|
||||
|
||||
let equivalentDocument = TestDocument(
|
||||
apiDescription: apiDescription,
|
||||
body: resourceBody,
|
||||
includes: includes,
|
||||
meta: meta,
|
||||
links: links
|
||||
)
|
||||
|
||||
XCTAssert(equivalentDocument == successDoc)
|
||||
XCTAssert(successDoc == equivalentDocument)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test Type
|
||||
extension SuccessAndErrorDocumentTests {
|
||||
enum TestTypeDescription: ResourceObjectDescription {
|
||||
static let jsonType: String = "tests"
|
||||
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
struct TestMeta: JSONAPI.Meta {
|
||||
let hello: String
|
||||
}
|
||||
|
||||
struct TestLinks: JSONAPI.Links {
|
||||
let testLink: Link<String, NoMetadata>
|
||||
}
|
||||
|
||||
typealias TestType = ResourceObject<TestTypeDescription, NoMetadata, NoLinks, String>
|
||||
|
||||
typealias TestDocument = Document<SingleResourceBody<TestType>, TestMeta, TestLinks, Include1<TestType>, APIDescription<NoMetadata>, BasicJSONAPIError<String>>
|
||||
|
||||
typealias TestSuccessDocument = TestDocument.SuccessDocument
|
||||
typealias TestErrorDocument = TestDocument.ErrorDocument
|
||||
}
|
||||
@@ -64,6 +64,7 @@ final class GenericJSONAPIErrorTests: XCTestCase {
|
||||
let error = decoded(type: TestGenericJSONAPIError.self, data: data)
|
||||
|
||||
XCTAssertEqual(error, .unknown)
|
||||
XCTAssertEqual(String(describing: error), "unknown error")
|
||||
}
|
||||
|
||||
func test_encode() {
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// IncludesDecodingErrorTests.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/14/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
|
||||
final class IncludesDecodingErrorTests: XCTestCase {
|
||||
func test_unexpectedIncludeType() {
|
||||
var error1: Error!
|
||||
XCTAssertThrowsError(try testDecoder.decode(Includes<Include2<TestEntity, TestEntity2>>.self, from: three_different_type_includes)) { (error: Error) -> Void in
|
||||
XCTAssertEqual(
|
||||
(error as? IncludesDecodingError)?.idx,
|
||||
2
|
||||
)
|
||||
|
||||
XCTAssertEqual(
|
||||
(error as? IncludesDecodingError).map(String.init(describing:)),
|
||||
"""
|
||||
Include 3 failed to parse: \nCould not have been Include Type 1 because:
|
||||
found JSON:API type "test_entity4" but expected "test_entity1"
|
||||
|
||||
Could not have been Include Type 2 because:
|
||||
found JSON:API type "test_entity4" but expected "test_entity2"
|
||||
"""
|
||||
)
|
||||
|
||||
error1 = error
|
||||
}
|
||||
|
||||
// now test that we get the same error from a different test stub
|
||||
XCTAssertThrowsError(try testDecoder.decode(Includes<Include2<TestEntity, TestEntity2>>.self, from: four_different_type_includes)) { (error2: Error) -> Void in
|
||||
XCTAssertEqual(
|
||||
error1 as? IncludesDecodingError,
|
||||
error2 as? IncludesDecodingError
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test Types
|
||||
extension IncludesDecodingErrorTests {
|
||||
enum TestEntityType: ResourceObjectDescription {
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
|
||||
public static var jsonType: String { return "test_entity1" }
|
||||
|
||||
public struct Attributes: JSONAPI.SparsableAttributes {
|
||||
let foo: Attribute<String>
|
||||
let bar: Attribute<Int>
|
||||
|
||||
public enum CodingKeys: String, Equatable, CodingKey {
|
||||
case foo
|
||||
case bar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias TestEntity = BasicEntity<TestEntityType>
|
||||
|
||||
enum TestEntityType2: ResourceObjectDescription {
|
||||
|
||||
public static var jsonType: String { return "test_entity2" }
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let entity1: ToOneRelationship<TestEntity, NoMetadata, NoLinks>
|
||||
}
|
||||
|
||||
public struct Attributes: JSONAPI.SparsableAttributes {
|
||||
let foo: Attribute<String>
|
||||
let bar: Attribute<Int>
|
||||
|
||||
public enum CodingKeys: String, Equatable, CodingKey {
|
||||
case foo
|
||||
case bar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias TestEntity2 = BasicEntity<TestEntityType2>
|
||||
|
||||
enum TestEntityType4: ResourceObjectDescription {
|
||||
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
|
||||
public static var jsonType: String { return "test_entity4" }
|
||||
}
|
||||
|
||||
typealias TestEntity4 = BasicEntity<TestEntityType4>
|
||||
|
||||
enum TestEntityType6: ResourceObjectDescription {
|
||||
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
public static var jsonType: String { return "test_entity6" }
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let entity4: ToOneRelationship<TestEntity4, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
typealias TestEntity6 = BasicEntity<TestEntityType6>
|
||||
}
|
||||
@@ -129,6 +129,10 @@ let four_different_type_includes = """
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity4",
|
||||
"id": "364B3B69-4DF1-467F-B52E-B0C9E44F666E"
|
||||
},
|
||||
{
|
||||
"type": "test_entity6",
|
||||
"id": "11113B69-4DF1-467F-B52E-B0C9E44FC444",
|
||||
@@ -140,10 +144,6 @@ let four_different_type_includes = """
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity4",
|
||||
"id": "364B3B69-4DF1-467F-B52E-B0C9E44F666E"
|
||||
}
|
||||
]
|
||||
""".data(using: .utf8)!
|
||||
|
||||
@@ -15,6 +15,12 @@ public class PolyProxyTests: XCTestCase {
|
||||
XCTAssertEqual(User.jsonType, "users")
|
||||
}
|
||||
|
||||
func test_CannotEncodeOrDecodePoly0() {
|
||||
XCTAssertThrowsError(try testDecoder.decode(Poly0.self, from: poly_user_stub_1))
|
||||
|
||||
XCTAssertThrowsError(try testEncoder.encode(Poly0()))
|
||||
}
|
||||
|
||||
func test_UserADecode() {
|
||||
let polyUserA = decoded(type: User.self, data: poly_user_stub_1)
|
||||
let userA = decoded(type: UserA.self, data: poly_user_stub_1)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user