mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Add encoding to ResourceBody and test it
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
// Created by Mathew Polzin on 11/10/18.
|
||||
//
|
||||
|
||||
public protocol ResourceBody: Decodable {
|
||||
public protocol ResourceBody: Codable, Equatable {
|
||||
}
|
||||
|
||||
public struct SingleResourceBody<Entity: JSONAPI.EntityType>: ResourceBody {
|
||||
@@ -20,8 +20,25 @@ public struct ManyResourceBody<Entity: JSONAPI.EntityType>: ResourceBody {
|
||||
extension SingleResourceBody {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
if container.decodeNil() {
|
||||
value = nil
|
||||
return
|
||||
}
|
||||
|
||||
value = try container.decode(Entity.self)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
if value == nil {
|
||||
try container.encodeNil()
|
||||
return
|
||||
}
|
||||
|
||||
try container.encode(value)
|
||||
}
|
||||
}
|
||||
|
||||
extension ManyResourceBody {
|
||||
@@ -33,4 +50,12 @@ extension ManyResourceBody {
|
||||
}
|
||||
values = valueAggregator
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.unkeyedContainer()
|
||||
|
||||
for value in values {
|
||||
try container.encode(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class EntityTests: XCTestCase {
|
||||
extension EntityTests {
|
||||
|
||||
func test_EntityNoRelationshipsNoAttributes() {
|
||||
let entity = decodedTestType(type: TestEntity1.self,
|
||||
let entity = decoded(type: TestEntity1.self,
|
||||
data: entity_no_relationships_no_attributes)
|
||||
|
||||
XCTAssert(type(of: entity.relationships) == NoRelatives.self)
|
||||
@@ -58,7 +58,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_EntityNoRelationshipsSomeAttributes() {
|
||||
let entity = decodedTestType(type: TestEntity5.self,
|
||||
let entity = decoded(type: TestEntity5.self,
|
||||
data: entity_no_relationships_some_attributes)
|
||||
|
||||
XCTAssert(type(of: entity.relationships) == NoRelatives.self)
|
||||
@@ -72,7 +72,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsNoAttributes() {
|
||||
let entity = decodedTestType(type: TestEntity3.self,
|
||||
let entity = decoded(type: TestEntity3.self,
|
||||
data: entity_some_relationships_no_attributes)
|
||||
|
||||
XCTAssert(type(of: entity.attributes) == NoAttributes.self)
|
||||
@@ -86,7 +86,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsSomeAttributes() {
|
||||
let entity = decodedTestType(type: TestEntity4.self,
|
||||
let entity = decoded(type: TestEntity4.self,
|
||||
data: entity_some_relationships_some_attributes)
|
||||
|
||||
XCTAssertEqual(entity[\.word], "coolio")
|
||||
@@ -104,7 +104,7 @@ extension EntityTests {
|
||||
extension EntityTests {
|
||||
|
||||
func test_entityOneOmittedAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity6.self,
|
||||
let entity = decoded(type: TestEntity6.self,
|
||||
data: entity_one_omitted_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -118,7 +118,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_entityOneNullAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity6.self,
|
||||
let entity = decoded(type: TestEntity6.self,
|
||||
data: entity_one_null_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -132,7 +132,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_entityAllAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity6.self,
|
||||
let entity = decoded(type: TestEntity6.self,
|
||||
data: entity_all_attributes)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -146,7 +146,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_entityOneNullAndOneOmittedAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity6.self,
|
||||
let entity = decoded(type: TestEntity6.self,
|
||||
data: entity_one_null_and_one_missing_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -165,7 +165,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_NullOptionalNullableAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity7.self,
|
||||
let entity = decoded(type: TestEntity7.self,
|
||||
data: entity_null_optional_nullable_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -178,7 +178,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_NonNullOptionalNullableAttribute() {
|
||||
let entity = decodedTestType(type: TestEntity7.self,
|
||||
let entity = decoded(type: TestEntity7.self,
|
||||
data: entity_non_null_optional_nullable_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
@@ -194,7 +194,7 @@ extension EntityTests {
|
||||
// MARK: Attribute Transformation
|
||||
extension EntityTests {
|
||||
func test_IntToString() {
|
||||
let entity = decodedTestType(type: TestEntity8.self,
|
||||
let entity = decoded(type: TestEntity8.self,
|
||||
data: entity_int_to_string_attribute)
|
||||
|
||||
XCTAssertEqual(entity[\.string], "22")
|
||||
@@ -214,7 +214,7 @@ extension EntityTests {
|
||||
// MARK: Relationship omission and nullification
|
||||
extension EntityTests {
|
||||
func test_nullableRelationshipNotNull() {
|
||||
let entity = decodedTestType(type: TestEntity9.self,
|
||||
let entity = decoded(type: TestEntity9.self,
|
||||
data: entity_omitted_relationship)
|
||||
|
||||
XCTAssertEqual((entity ~> \.nullableOne)?.rawValue, "3323")
|
||||
@@ -227,7 +227,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_nullableRelationshipIsNull() {
|
||||
let entity = decodedTestType(type: TestEntity9.self,
|
||||
let entity = decoded(type: TestEntity9.self,
|
||||
data: entity_nulled_relationship)
|
||||
|
||||
XCTAssertNil(entity ~> \.nullableOne)
|
||||
@@ -244,7 +244,7 @@ extension EntityTests {
|
||||
|
||||
extension EntityTests {
|
||||
func test_RleationshipsOfSameType() {
|
||||
let entity = decodedTestType(type: TestEntity10.self,
|
||||
let entity = decoded(type: TestEntity10.self,
|
||||
data: entity_self_ref_relationship)
|
||||
|
||||
XCTAssertEqual((entity ~> \.selfRef).rawValue, "1")
|
||||
@@ -260,7 +260,7 @@ extension EntityTests {
|
||||
|
||||
extension EntityTests {
|
||||
func test_UnidentifiedEntity() {
|
||||
let entity = decodedTestType(type: UnidentifiedTestEntity.self,
|
||||
let entity = decoded(type: UnidentifiedTestEntity.self,
|
||||
data: entity_unidentified)
|
||||
|
||||
XCTAssertNil(entity[\.me])
|
||||
@@ -273,7 +273,7 @@ extension EntityTests {
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntityWithAttributes() {
|
||||
let entity = decodedTestType(type: UnidentifiedTestEntity.self,
|
||||
let entity = decoded(type: UnidentifiedTestEntity.self,
|
||||
data: entity_unidentified_with_attributes)
|
||||
|
||||
XCTAssertEqual(entity[\.me], "unknown")
|
||||
|
||||
@@ -7,62 +7,37 @@ class IncludedTests: XCTestCase {
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
func test_zeroIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<NoIncludes>.self, from: two_same_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
let includes = decoded(type: Includes<NoIncludes>.self,
|
||||
data: two_same_type_includes)
|
||||
|
||||
XCTAssertEqual(includes.count, 0)
|
||||
}
|
||||
|
||||
func test_OneInclude() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include1<TestEntity>>.self, from: one_include)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
let includes = decoded(type: Includes<Include1<TestEntity>>.self,
|
||||
data: one_include)
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
}
|
||||
|
||||
func test_TwoSameIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include1<TestEntity>>.self, from: two_same_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
let includes = decoded(type: Includes<Include1<TestEntity>>.self,
|
||||
data: two_same_type_includes)
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 2)
|
||||
}
|
||||
|
||||
func test_TwoDifferentIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include2<TestEntity, TestEntity2>>.self, from: two_different_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
let includes = decoded(type: Includes<Include2<TestEntity, TestEntity2>>.self,
|
||||
data: two_different_type_includes)
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
}
|
||||
|
||||
func test_ThreeDifferentIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include3<TestEntity, TestEntity2, TestEntity4>>.self, from: three_different_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
let includes = decoded(type: Includes<Include3<TestEntity, TestEntity2, TestEntity4>>.self,
|
||||
data: three_different_type_includes)
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
@@ -70,13 +45,8 @@ class IncludedTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_FourDifferentIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include4<TestEntity, TestEntity2, TestEntity4, TestEntity6>>.self, from: four_different_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
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)
|
||||
@@ -85,13 +55,8 @@ class IncludedTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_FiveDifferentIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include5<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6>>.self, from: five_different_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
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)
|
||||
@@ -101,13 +66,8 @@ class IncludedTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_SixDifferentIncludes() {
|
||||
let maybeIncludes = try? decoder.decode(Includes<Include6<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6>>.self, from: six_different_type_includes)
|
||||
|
||||
XCTAssertNotNil(maybeIncludes)
|
||||
|
||||
guard let includes = maybeIncludes else {
|
||||
return
|
||||
}
|
||||
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)
|
||||
|
||||
@@ -31,24 +31,38 @@ class RelationshipTests: XCTestCase {
|
||||
XCTAssertEqual(relationship.ids.count, 4)
|
||||
XCTAssertEqual(relationship.ids, [entity1, entity2, entity3, entity4].map { $0.id })
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Encode/Decode
|
||||
extension RelationshipTests {
|
||||
func test_ToOneRelationship() {
|
||||
let relationship = try? JSONDecoder().decode(ToOneRelationship<TestEntity1>.self, from: to_one_relationship)
|
||||
let relationship = decoded(type: ToOneRelationship<TestEntity1>.self,
|
||||
data: to_one_relationship)
|
||||
|
||||
XCTAssertNotNil(relationship)
|
||||
XCTAssertEqual(relationship.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(relationship.ids.count, 1)
|
||||
}
|
||||
|
||||
XCTAssertEqual(relationship?.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(relationship?.ids.count, 1)
|
||||
func test_ToOneRelationship_encode() {
|
||||
test_DecodeEncodeEquality(type: ToOneRelationship<TestEntity1>.self,
|
||||
data: to_one_relationship)
|
||||
}
|
||||
|
||||
func test_ToManyRelationship() {
|
||||
let relationship = try? JSONDecoder().decode(ToManyRelationship<TestEntity1>.self, from: to_many_relationship)
|
||||
let relationship = decoded(type: ToManyRelationship<TestEntity1>.self,
|
||||
data: to_many_relationship)
|
||||
|
||||
XCTAssertNotNil(relationship)
|
||||
|
||||
XCTAssertEqual(relationship?.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
XCTAssertEqual(relationship.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
}
|
||||
|
||||
func test_ToManyRelationship_encode() {
|
||||
test_DecodeEncodeEquality(type: ToManyRelationship<TestEntity1>.self,
|
||||
data: to_many_relationship)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test types
|
||||
extension RelationshipTests {
|
||||
enum TestEntityType1: EntityDescription {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
|
||||
@@ -11,30 +11,46 @@ import JSONAPI
|
||||
class ResourceBodyTests: XCTestCase {
|
||||
|
||||
func test_singleResourceBody() {
|
||||
let body = try? JSONDecoder().decode(SingleResourceBody<Article>.self, from: single_resource_body)
|
||||
let body = decoded(type: SingleResourceBody<Article>.self,
|
||||
data: single_resource_body)
|
||||
|
||||
XCTAssertNotNil(body)
|
||||
|
||||
guard let b = body else { return }
|
||||
|
||||
XCTAssertEqual(b.value, Article(id: Id<String, ArticleType>(rawValue: "1"),
|
||||
XCTAssertEqual(body.value, Article(id: Id<String, ArticleType>(rawValue: "1"),
|
||||
attributes: ArticleType.Attributes(title: try! .init(rawValue: "JSON:API paints my bikeshed!"))))
|
||||
}
|
||||
|
||||
func test_singleResourceBody_encode() {
|
||||
test_DecodeEncodeEquality(type: SingleResourceBody<Article>.self,
|
||||
data: single_resource_body)
|
||||
}
|
||||
|
||||
func test_manyResourceBody() {
|
||||
let body = try? JSONDecoder().decode(ManyResourceBody<Article>.self, from: many_resource_body)
|
||||
let body = decoded(type: ManyResourceBody<Article>.self,
|
||||
data: many_resource_body)
|
||||
|
||||
XCTAssertNotNil(body)
|
||||
|
||||
guard let b = body else { return }
|
||||
|
||||
XCTAssertEqual(b.values, [
|
||||
XCTAssertEqual(body.values, [
|
||||
Article(id: .init(rawValue: "1"), attributes: try! .init(title: .init(rawValue: "JSON:API paints my bikeshed!"))),
|
||||
Article(id: .init(rawValue: "2"), attributes: try! .init(title: .init(rawValue: "Sick"))),
|
||||
Article(id: .init(rawValue: "3"), attributes: try! .init(title: .init(rawValue: "Hello World")))
|
||||
])
|
||||
}
|
||||
|
||||
func test_manyResourceBody_encode() {
|
||||
test_DecodeEncodeEquality(type: ManyResourceBody<Article>.self,
|
||||
data: many_resource_body)
|
||||
}
|
||||
|
||||
func test_manyResourceBodyEmpty() {
|
||||
let body = decoded(type: ManyResourceBody<Article>.self,
|
||||
data: many_resource_body_empty)
|
||||
|
||||
XCTAssertEqual(body.values.count, 0)
|
||||
}
|
||||
|
||||
func test_manyResourceBodyEmpty_encode() {
|
||||
test_DecodeEncodeEquality(type: ManyResourceBody<Article>.self,
|
||||
data: many_resource_body_empty)
|
||||
}
|
||||
|
||||
enum ArticleType: EntityDescription {
|
||||
public static var type: String { return "articles" }
|
||||
|
||||
|
||||
@@ -40,3 +40,8 @@ let many_resource_body = """
|
||||
}
|
||||
]
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let many_resource_body_empty = """
|
||||
[
|
||||
]
|
||||
""".data(using: .utf8)!
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
import XCTest
|
||||
|
||||
func decodedTestType<T: Codable & Equatable>(type: T.Type, data: Data) -> T {
|
||||
func decoded<T: Decodable>(type: T.Type, data: Data) -> T {
|
||||
return try! JSONDecoder().decode(T.self, from: data)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user