mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Add sparse document tests
This commit is contained in:
@@ -15,10 +15,12 @@ public protocol Relationships: Codable & Equatable {}
|
||||
/// properties of any types that are JSON encodable.
|
||||
public protocol Attributes: Codable & Equatable {}
|
||||
|
||||
public typealias SparsableCodingKey = CodingKey & Equatable
|
||||
|
||||
/// Attributes containing publicly accessible and `Equatable`
|
||||
/// CodingKeys are required to support Sparse Fieldsets.
|
||||
public protocol SparsableAttributes: Attributes {
|
||||
associatedtype CodingKeys: CodingKey & Equatable
|
||||
associatedtype CodingKeys: SparsableCodingKey
|
||||
}
|
||||
|
||||
/// Can be used as `Relationships` Type for Entities that do not
|
||||
|
||||
@@ -926,6 +926,217 @@ extension DocumentTests {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Sparse Fieldset Documents
|
||||
|
||||
extension DocumentTests {
|
||||
func test_sparsePrimaryResource() {
|
||||
let primaryResource = Book(attributes: .init(pageCount: 100),
|
||||
relationships: .init(author: "1234",
|
||||
series: []),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
.sparse(with: [.pageCount])
|
||||
|
||||
let document = Document<
|
||||
SingleResourceBody<Book.SparseType>,
|
||||
NoMetadata,
|
||||
NoLinks,
|
||||
NoIncludes,
|
||||
NoAPIDescription,
|
||||
UnknownJSONAPIError
|
||||
>(apiDescription: .none,
|
||||
body: .init(resourceObject: primaryResource),
|
||||
includes: .none,
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let encoded = try! JSONEncoder().encode(document)
|
||||
|
||||
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
|
||||
options: [])
|
||||
|
||||
let deserializedObj = deserialized as? [String: Any]
|
||||
|
||||
guard let deserializedObj1 = deserializedObj?["data"] as? [String: Any] else {
|
||||
XCTFail("Expected to deserialize one object from document data")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["id"])
|
||||
XCTAssertEqual(deserializedObj1["id"] as? String, primaryResource.resourceObject.id.rawValue)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["type"])
|
||||
XCTAssertEqual(deserializedObj1["type"] as? String, Book.jsonType)
|
||||
|
||||
XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 1)
|
||||
XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?["pageCount"] as? Int, 100)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["relationships"])
|
||||
}
|
||||
|
||||
func test_sparsePrimaryResourceOptionalAndNil() {
|
||||
let document = Document<
|
||||
SingleResourceBody<Book.SparseType?>,
|
||||
NoMetadata,
|
||||
NoLinks,
|
||||
NoIncludes,
|
||||
NoAPIDescription,
|
||||
UnknownJSONAPIError
|
||||
>(apiDescription: .none,
|
||||
body: .init(resourceObject: nil),
|
||||
includes: .none,
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let encoded = try! JSONEncoder().encode(document)
|
||||
|
||||
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
|
||||
options: [])
|
||||
|
||||
let deserializedObj = deserialized as? [String: Any]
|
||||
|
||||
XCTAssertNotNil(deserializedObj?["data"] as? NSNull)
|
||||
}
|
||||
|
||||
func test_sparseIncludeFullPrimaryResource() {
|
||||
let bookInclude = Book(id: "444",
|
||||
attributes: .init(pageCount: 113),
|
||||
relationships: .init(author: "1234",
|
||||
series: ["443"]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
.sparse(with: [])
|
||||
|
||||
let primaryResource = Book(id: "443",
|
||||
attributes: .init(pageCount: 100),
|
||||
relationships: .init(author: "1234",
|
||||
series: ["444"]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let document = Document<
|
||||
SingleResourceBody<Book>,
|
||||
NoMetadata,
|
||||
NoLinks,
|
||||
Include1<Book.SparseType>,
|
||||
NoAPIDescription,
|
||||
UnknownJSONAPIError
|
||||
>(apiDescription: .none,
|
||||
body: .init(resourceObject: primaryResource),
|
||||
includes: .init(values: [.init(bookInclude)]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let encoded = try! JSONEncoder().encode(document)
|
||||
|
||||
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
|
||||
options: [])
|
||||
|
||||
let deserializedObj = deserialized as? [String: Any]
|
||||
|
||||
guard let deserializedObj1 = deserializedObj?["data"] as? [String: Any] else {
|
||||
XCTFail("Expected to deserialize one object from document data")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["id"])
|
||||
XCTAssertEqual(deserializedObj1["id"] as? String, primaryResource.id.rawValue)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["type"])
|
||||
XCTAssertEqual(deserializedObj1["type"] as? String, Book.jsonType)
|
||||
|
||||
XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 1)
|
||||
XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?["pageCount"] as? Int, 100)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["relationships"])
|
||||
|
||||
guard let deserializedIncludes = deserializedObj?["included"] as? [Any],
|
||||
let deserializedObj2 = deserializedIncludes.first as? [String: Any] else {
|
||||
XCTFail("Expected to deserialize one incude object")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["id"])
|
||||
XCTAssertEqual(deserializedObj2["id"] as? String, bookInclude.resourceObject.id.rawValue)
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["type"])
|
||||
XCTAssertEqual(deserializedObj2["type"] as? String, Book.jsonType)
|
||||
|
||||
XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?.count, 0)
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["relationships"])
|
||||
}
|
||||
|
||||
func test_sparseIncludeSparsePrimaryResource() {
|
||||
let bookInclude = Book(id: "444",
|
||||
attributes: .init(pageCount: 113),
|
||||
relationships: .init(author: "1234",
|
||||
series: ["443"]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
.sparse(with: [])
|
||||
|
||||
let primaryResource = Book(id: "443",
|
||||
attributes: .init(pageCount: 100),
|
||||
relationships: .init(author: "1234",
|
||||
series: ["444"]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
.sparse(with: [])
|
||||
|
||||
let document = Document<
|
||||
SingleResourceBody<Book.SparseType>,
|
||||
NoMetadata,
|
||||
NoLinks,
|
||||
Include1<Book.SparseType>,
|
||||
NoAPIDescription,
|
||||
UnknownJSONAPIError
|
||||
>(apiDescription: .none,
|
||||
body: .init(resourceObject: primaryResource),
|
||||
includes: .init(values: [.init(bookInclude)]),
|
||||
meta: .none,
|
||||
links: .none)
|
||||
|
||||
let encoded = try! JSONEncoder().encode(document)
|
||||
|
||||
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
|
||||
options: [])
|
||||
|
||||
let deserializedObj = deserialized as? [String: Any]
|
||||
|
||||
guard let deserializedObj1 = deserializedObj?["data"] as? [String: Any] else {
|
||||
XCTFail("Expected to deserialize one object from document data")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["id"])
|
||||
XCTAssertEqual(deserializedObj1["id"] as? String, primaryResource.resourceObject.id.rawValue)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["type"])
|
||||
XCTAssertEqual(deserializedObj1["type"] as? String, Book.jsonType)
|
||||
|
||||
XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 0)
|
||||
|
||||
XCTAssertNotNil(deserializedObj1["relationships"])
|
||||
|
||||
guard let deserializedIncludes = deserializedObj?["included"] as? [Any],
|
||||
let deserializedObj2 = deserializedIncludes.first as? [String: Any] else {
|
||||
XCTFail("Expected to deserialize one incude object")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["id"])
|
||||
XCTAssertEqual(deserializedObj2["id"] as? String, bookInclude.resourceObject.id.rawValue)
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["type"])
|
||||
XCTAssertEqual(deserializedObj2["type"] as? String, Book.jsonType)
|
||||
|
||||
XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?.count, 0)
|
||||
|
||||
XCTAssertNotNil(deserializedObj2["relationships"])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Poly PrimaryResource Tests
|
||||
extension DocumentTests {
|
||||
func test_singleDocument_PolyPrimaryResource() {
|
||||
@@ -1115,6 +1326,25 @@ extension DocumentTests {
|
||||
|
||||
typealias Article = BasicEntity<ArticleType>
|
||||
|
||||
enum BookType: ResourceObjectDescription {
|
||||
static var jsonType: String { return "books" }
|
||||
|
||||
struct Attributes: JSONAPI.SparsableAttributes {
|
||||
let pageCount: Attribute<Int>
|
||||
|
||||
enum CodingKeys: String, SparsableCodingKey {
|
||||
case pageCount
|
||||
}
|
||||
}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let author: ToOneRelationship<Author, NoMetadata, NoLinks>
|
||||
let series: ToManyRelationship<Book, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
typealias Book = BasicEntity<BookType>
|
||||
|
||||
struct TestPageMetadata: JSONAPI.Meta {
|
||||
let total: Int
|
||||
let limit: Int
|
||||
|
||||
@@ -12,15 +12,15 @@ class IncludedTests: XCTestCase {
|
||||
func test_zeroIncludes() {
|
||||
let includes = decoded(type: Includes<NoIncludes>.self,
|
||||
data: two_same_type_includes)
|
||||
|
||||
|
||||
XCTAssertEqual(includes.count, 0)
|
||||
}
|
||||
|
||||
func test_zeroIncludes_encode() {
|
||||
XCTAssertThrowsError(try JSONEncoder().encode(decoded(type: Includes<NoIncludes>.self,
|
||||
data: two_same_type_includes)))
|
||||
}
|
||||
|
||||
XCTAssertThrowsError(try JSONEncoder().encode(decoded(type: Includes<NoIncludes>.self,
|
||||
data: two_same_type_includes)))
|
||||
}
|
||||
|
||||
func test_OneInclude() {
|
||||
let includes = decoded(type: Includes<Include1<TestEntity>>.self,
|
||||
data: one_include)
|
||||
@@ -32,7 +32,7 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include1<TestEntity>>.self,
|
||||
data: one_include)
|
||||
}
|
||||
|
||||
|
||||
func test_TwoSameIncludes() {
|
||||
let includes = decoded(type: Includes<Include1<TestEntity>>.self,
|
||||
data: two_same_type_includes)
|
||||
@@ -57,7 +57,7 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include2<TestEntity, TestEntity2>>.self,
|
||||
data: two_different_type_includes)
|
||||
}
|
||||
|
||||
|
||||
func test_ThreeDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include3<TestEntity, TestEntity2, TestEntity4>>.self,
|
||||
data: three_different_type_includes)
|
||||
@@ -71,11 +71,11 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include3<TestEntity, TestEntity2, TestEntity4>>.self,
|
||||
data: three_different_type_includes)
|
||||
}
|
||||
|
||||
|
||||
func test_FourDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include4<TestEntity, TestEntity2, TestEntity4, TestEntity6>>.self,
|
||||
data: four_different_type_includes)
|
||||
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity4.self].count, 1)
|
||||
@@ -86,11 +86,11 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include4<TestEntity, TestEntity2, TestEntity4, TestEntity6>>.self,
|
||||
data: four_different_type_includes)
|
||||
}
|
||||
|
||||
|
||||
func test_FiveDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include5<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6>>.self,
|
||||
data: five_different_type_includes)
|
||||
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity3.self].count, 1)
|
||||
@@ -102,11 +102,11 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include5<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6>>.self,
|
||||
data: five_different_type_includes)
|
||||
}
|
||||
|
||||
|
||||
func test_SixDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include6<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6>>.self,
|
||||
data: six_different_type_includes)
|
||||
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity3.self].count, 1)
|
||||
|
||||
Reference in New Issue
Block a user