Add encoding to ResourceBody and test it

This commit is contained in:
Mathew Polzin
2018-11-16 18:21:37 -08:00
parent 696e434caa
commit 9802efd917
7 changed files with 114 additions and 94 deletions
+26 -1
View File
@@ -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)
}
}
}
+16 -16
View File
@@ -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")
+16 -56
View File
@@ -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)
}