mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
lots of comparison code, a few small breaking changes
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/3/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class AttributesCompareTests: XCTestCase {
|
||||
func test_sameAttributes() {
|
||||
let attr1 = TestAttributes(
|
||||
string: "hello world",
|
||||
int: 10,
|
||||
bool: true,
|
||||
double: 105.4,
|
||||
struct: .init(value: .init())
|
||||
)
|
||||
let attr2 = attr1
|
||||
|
||||
XCTAssertEqual(attr1.compare(to: attr2), [
|
||||
"string": .same,
|
||||
"int": .same,
|
||||
"bool": .same,
|
||||
"double": .same,
|
||||
"struct": .same
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentAttributes() {
|
||||
let attr1 = TestAttributes(
|
||||
string: "hello world",
|
||||
int: 10,
|
||||
bool: true,
|
||||
double: 105.4,
|
||||
struct: .init(value: .init())
|
||||
)
|
||||
let attr2 = TestAttributes(
|
||||
string: "hello",
|
||||
int: 11,
|
||||
bool: false,
|
||||
double: 1.4,
|
||||
struct: .init(value: .init(val: "there"))
|
||||
)
|
||||
|
||||
XCTAssertEqual(attr1.compare(to: attr2), [
|
||||
"string": .different("hello world", "hello"),
|
||||
"int": .different("10", "11"),
|
||||
"bool": .different("true", "false"),
|
||||
"double": .different("105.4", "1.4"),
|
||||
"struct": .different("string: hello", "string: there")
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
private struct TestAttributes: JSONAPI.Attributes {
|
||||
let string: Attribute<String>
|
||||
let int: Attribute<Int>
|
||||
let bool: Attribute<Bool>
|
||||
let double: Attribute<Double>
|
||||
let `struct`: Attribute<Struct>
|
||||
|
||||
struct Struct: Equatable, Codable, CustomStringConvertible {
|
||||
let string: String
|
||||
|
||||
init(val: String = "hello") {
|
||||
self.string = val
|
||||
}
|
||||
|
||||
var description: String { return "string: \(string)" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// DocumentCompareTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/4/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class DocumentCompareTests: XCTestCase {
|
||||
func test_same() {
|
||||
XCTAssertTrue(d1.compare(to: d1).differences.isEmpty)
|
||||
XCTAssertTrue(d2.compare(to: d2).differences.isEmpty)
|
||||
XCTAssertTrue(d3.compare(to: d3).differences.isEmpty)
|
||||
XCTAssertTrue(d4.compare(to: d4).differences.isEmpty)
|
||||
}
|
||||
|
||||
func test_errorAndData() {
|
||||
XCTAssertEqual(d1.compare(to: d2).differences, [
|
||||
"Body": "data response ≠ error response"
|
||||
])
|
||||
|
||||
XCTAssertEqual(d2.compare(to: d1).differences, [
|
||||
"Body": "error response ≠ data response"
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentErrors() {
|
||||
XCTAssertEqual(d2.compare(to: d4).differences, [
|
||||
"Body": "status: 500, title: Internal Error ≠ status: 404, title: Not Found"
|
||||
])
|
||||
}
|
||||
|
||||
func test_differentData() {
|
||||
XCTAssertEqual(d3.compare(to: d5).differences, [
|
||||
"Body": "(Includes: (include 2: missing)), (Primary Resource: (resource 2: missing))"
|
||||
])
|
||||
|
||||
XCTAssertEqual(d3.compare(to: d6).differences, [
|
||||
"Body": ##"(Includes: (include 2: missing)), (Primary Resource: (resource 2: 'age' attribute: 10 ≠ 12, 'bestFriend' relationship: Optional(Id(2)) ≠ nil, 'favoriteColor' attribute: nil ≠ Optional("blue"), 'name' attribute: name ≠ Fig, id: 1 ≠ 5), (resource 3: missing))"##
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate enum TestDescription: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "test_type"
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
let age: Attribute<Int>
|
||||
let favoriteColor: Attribute<String?>
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let bestFriend: ToOneRelationship<TestType2?, NoMetadata, NoLinks>
|
||||
let parents: ToManyRelationship<TestType, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate typealias TestType = ResourceObject<TestDescription, NoMetadata, NoLinks, String>
|
||||
|
||||
fileprivate enum TestDescription2: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "test_type2"
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
let age: Attribute<Int>
|
||||
let favoriteColor: Attribute<String?>
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let bestFriend: ToOneRelationship<TestType2?, NoMetadata, NoLinks>
|
||||
let parents: ToManyRelationship<TestType2, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate typealias TestType2 = ResourceObject<TestDescription2, NoMetadata, NoLinks, String>
|
||||
|
||||
fileprivate typealias SingleDocument = 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>>
|
||||
|
||||
fileprivate let r1 = TestType(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "name",
|
||||
age: 10,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: "2",
|
||||
parents: ["3", "4"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let r2 = TestType(
|
||||
id: "5",
|
||||
attributes: .init(
|
||||
name: "Fig",
|
||||
age: 12,
|
||||
favoriteColor: "blue"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: ["3", "4"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let r3 = TestType2(
|
||||
id: "2",
|
||||
attributes: .init(
|
||||
name: "Tully",
|
||||
age: 100,
|
||||
favoriteColor: "red"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: []
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let d1 = SingleDocument(
|
||||
apiDescription: .none,
|
||||
body: .init(resourceObject: r1),
|
||||
includes: .none,
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let d2 = SingleDocument(
|
||||
apiDescription: .none,
|
||||
errors: [.error(.init(id: nil, status: "500", title: "Internal Error"))]
|
||||
)
|
||||
|
||||
fileprivate let d3 = ManyDocument(
|
||||
apiDescription: .none,
|
||||
body: .init(resourceObjects: [r1, r2]),
|
||||
includes: .init(values: [.init(r3)]),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let d4 = SingleDocument(
|
||||
apiDescription: .none,
|
||||
errors: [.error(.init(id: nil, status: "404", title: "Not Found"))]
|
||||
)
|
||||
|
||||
fileprivate let d5 = ManyDocument(
|
||||
apiDescription: .none,
|
||||
body: .init(resourceObjects: [r1]),
|
||||
includes: .init(values: [.init(r3), .init(r2)]),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let d6 = ManyDocument(
|
||||
apiDescription: .none,
|
||||
body: .init(resourceObjects: [r1, r1, r2]),
|
||||
includes: .init(values: [.init(r3), .init(r2)]),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// IncludeCompareTests.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/4/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITesting
|
||||
import Poly
|
||||
|
||||
final class IncludesCompareTests: XCTestCase {
|
||||
func test_same() {
|
||||
let includes1 = Includes(values: justTypeOnes)
|
||||
let includes2 = Includes(values: justTypeOnes)
|
||||
XCTAssertTrue(includes1.compare(to: includes2).differences.isEmpty)
|
||||
|
||||
let includes3 = Includes(values: longerTypeOnes)
|
||||
let includes4 = Includes(values: longerTypeOnes)
|
||||
XCTAssertTrue(includes3.compare(to: includes4).differences.isEmpty)
|
||||
|
||||
let includes5 = Includes(values: onesAndTwos)
|
||||
let includes6 = Includes(values: onesAndTwos)
|
||||
XCTAssertTrue(includes5.compare(to: includes6).differences.isEmpty)
|
||||
}
|
||||
|
||||
func test_missing() {
|
||||
let includes1 = Includes(values: justTypeOnes)
|
||||
let includes2 = Includes(values: longerTypeOnes)
|
||||
XCTAssertEqual(includes1.compare(to: includes2).differences, ["include 3": "missing"])
|
||||
XCTAssertEqual(includes2.compare(to: includes1).differences, ["include 3": "missing"])
|
||||
}
|
||||
|
||||
func test_typeMismatch() {
|
||||
let includes1 = Includes(values: onesAndTwos)
|
||||
let includes2 = Includes(values: justTypeOnes)
|
||||
XCTAssertEqual(includes1.compare(to: includes2).differences, ["include 2": "ResourceObject<TestDescription2, NoMetadata, NoLinks, String> ≠ ResourceObject<TestDescription1, NoMetadata, NoLinks, String>"])
|
||||
XCTAssertEqual(includes2.compare(to: includes1).differences, ["include 2": "ResourceObject<TestDescription1, NoMetadata, NoLinks, String> ≠ ResourceObject<TestDescription2, NoMetadata, NoLinks, String>"])
|
||||
}
|
||||
|
||||
func test_valueMismatch() {
|
||||
let includes1 = Includes(values: onesAndTwos)
|
||||
let includes2 = Includes(values: differentOnesAndTwos)
|
||||
XCTAssertEqual(includes1.compare(to: includes2).differences, [
|
||||
"include 1": #"'favoriteColor' attribute: Optional("red") ≠ nil, 'name' attribute: Matt ≠ Todd, 'parents' relationship: 4, 5 ≠ 7, 8, id: 1 ≠ 2"#
|
||||
])
|
||||
}
|
||||
|
||||
fileprivate let justTypeOnes: [Poly2<TestType1, TestType2>] = [
|
||||
.a(
|
||||
TestType1(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "Matt",
|
||||
age: 23,
|
||||
favoriteColor: "red"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: "3",
|
||||
parents: ["4", "5"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
),
|
||||
.a(
|
||||
TestType1(
|
||||
id: "3",
|
||||
attributes: .init(
|
||||
name: "Helen",
|
||||
age: 24,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: ["2"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
fileprivate let longerTypeOnes: [Poly2<TestType1, TestType2>] = [
|
||||
.a(
|
||||
TestType1(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "Matt",
|
||||
age: 23,
|
||||
favoriteColor: "red"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: "3",
|
||||
parents: ["4", "5"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
),
|
||||
.a(
|
||||
TestType1(
|
||||
id: "3",
|
||||
attributes: .init(
|
||||
name: "Helen",
|
||||
age: 24,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: ["2"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
),
|
||||
.a(
|
||||
TestType1(
|
||||
id: "2",
|
||||
attributes: .init(
|
||||
name: "Troy",
|
||||
age: 45,
|
||||
favoriteColor: "blue"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: []
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
fileprivate let onesAndTwos: [Poly2<TestType1, TestType2>] = [
|
||||
.a(
|
||||
TestType1(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "Matt",
|
||||
age: 23,
|
||||
favoriteColor: "red"
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: "3",
|
||||
parents: ["4", "5"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
),
|
||||
.b(
|
||||
TestType2(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "Lucy",
|
||||
age: 33,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: []
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
fileprivate let differentOnesAndTwos: [Poly2<TestType1, TestType2>] = [
|
||||
.a(
|
||||
TestType1(
|
||||
id: "2",
|
||||
attributes: .init(
|
||||
name: "Todd",
|
||||
age: 23,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: "3",
|
||||
parents: ["7", "8"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
),
|
||||
.b(
|
||||
TestType2(
|
||||
id: "1",
|
||||
attributes: .init(
|
||||
name: "Lucy",
|
||||
age: 33,
|
||||
favoriteColor: nil
|
||||
),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: []
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
private enum TestDescription1: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "test_type1"
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
let age: Attribute<Int>
|
||||
let favoriteColor: Attribute<String?>
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let bestFriend: ToOneRelationship<TestType1?, NoMetadata, NoLinks>
|
||||
let parents: ToManyRelationship<TestType1, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
private typealias TestType1 = ResourceObject<TestDescription1, NoMetadata, NoLinks, String>
|
||||
|
||||
private enum TestDescription2: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "test_type2"
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
let age: Attribute<Int>
|
||||
let favoriteColor: Attribute<String?>
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let bestFriend: ToOneRelationship<TestType2?, NoMetadata, NoLinks>
|
||||
let parents: ToManyRelationship<TestType2, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
private typealias TestType2 = ResourceObject<TestDescription2, NoMetadata, NoLinks, String>
|
||||
@@ -0,0 +1,14 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/5/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class RelationshipsCompareTests: XCTestCase {
|
||||
// TODO: write tests
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
//
|
||||
// File.swift
|
||||
//
|
||||
//
|
||||
// Created by Mathew Polzin on 11/3/19.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITesting
|
||||
|
||||
final class ResourceObjectCompareTests: XCTestCase {
|
||||
func test_same() {
|
||||
print(test1.compare(to: test1).differences)
|
||||
XCTAssertTrue(test1.compare(to: test1).differences.isEmpty)
|
||||
XCTAssertTrue(test2.compare(to: test2).differences.isEmpty)
|
||||
}
|
||||
|
||||
func test_different() {
|
||||
// TODO: write actual test
|
||||
print(test1.compare(to: test2).differences.map { "\($0): \($1)" }.joined(separator: ", "))
|
||||
}
|
||||
|
||||
fileprivate let test1 = TestType(
|
||||
id: "2",
|
||||
attributes: .init(
|
||||
name: "James",
|
||||
age: 12,
|
||||
favoriteColor: "red"),
|
||||
relationships: .init(
|
||||
bestFriend: "3",
|
||||
parents: ["4", "5"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
|
||||
fileprivate let test2 = TestType(
|
||||
id: "3",
|
||||
attributes: .init(
|
||||
name: "Fred",
|
||||
age: 10,
|
||||
favoriteColor: .init(value: nil)),
|
||||
relationships: .init(
|
||||
bestFriend: nil,
|
||||
parents: ["1"]
|
||||
),
|
||||
meta: .none,
|
||||
links: .none
|
||||
)
|
||||
}
|
||||
|
||||
private enum TestDescription: JSONAPI.ResourceObjectDescription {
|
||||
static let jsonType: String = "test_type"
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
let age: Attribute<Int>
|
||||
let favoriteColor: Attribute<String?>
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let bestFriend: ToOneRelationship<TestType?, NoMetadata, NoLinks>
|
||||
let parents: ToManyRelationship<TestType, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
private typealias TestType = ResourceObject<TestDescription, NoMetadata, NoLinks, String>
|
||||
Reference in New Issue
Block a user