mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Added encoding support to Includes and tests
This commit is contained in:
@@ -40,22 +40,22 @@ The primary goals of this framework are:
|
||||
### Encoding
|
||||
#### Document
|
||||
- [ ] `data`
|
||||
- [ ] `included`
|
||||
- [x] `included`
|
||||
- [ ] `errors`
|
||||
- [ ] `meta`
|
||||
- [ ] `jsonapi`
|
||||
- [ ] `links`
|
||||
|
||||
#### Resource Object
|
||||
- [x] `id` (untested)
|
||||
- [x] `type` (untested)
|
||||
- [x] `attributes` (untested)
|
||||
- [x] `relationships` (untested)
|
||||
- [x] `id`
|
||||
- [x] `type`
|
||||
- [x] `attributes`
|
||||
- [x] `relationships`
|
||||
- [ ] `links`
|
||||
- [ ] `meta`
|
||||
|
||||
#### Relationship Object
|
||||
- [x] `data` (untested)
|
||||
- [x] `data`
|
||||
- [ ] `links`
|
||||
- [ ] `meta`
|
||||
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
import Result
|
||||
|
||||
public protocol IncludeDecoder: Decodable {}
|
||||
public protocol IncludeDecoder: Codable, Equatable {}
|
||||
|
||||
public struct Includes<I: IncludeDecoder>: Decodable {
|
||||
public struct Includes<I: IncludeDecoder>: Codable, Equatable {
|
||||
public static var none: Includes { return .init(values: []) }
|
||||
|
||||
let values: [I]
|
||||
@@ -34,6 +34,18 @@ public struct Includes<I: IncludeDecoder>: Decodable {
|
||||
|
||||
values = valueAggregator
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.unkeyedContainer()
|
||||
|
||||
guard I.self != NoIncludes.self else {
|
||||
throw JSONAPIEncodingError.illegalEncoding("Attempting to encode Include0, which should be represented by the absense of an 'included' entry altogether.")
|
||||
}
|
||||
|
||||
for value in values {
|
||||
try container.encode(value)
|
||||
}
|
||||
}
|
||||
|
||||
public var count: Int {
|
||||
return values.count
|
||||
@@ -64,6 +76,10 @@ public struct Include0: _Include0 {
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
throw JSONAPIEncodingError.illegalEncoding("Attempted to encode Include0, which should be represented by the absence of an 'included' entry altogether.")
|
||||
}
|
||||
}
|
||||
public typealias NoIncludes = Include0
|
||||
|
||||
@@ -85,6 +101,15 @@ public enum Include1<A: EntityType>: _Include1 {
|
||||
|
||||
self = .a(try container.decode(A.self))
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include1 {
|
||||
@@ -129,6 +154,17 @@ public enum Include2<A: EntityType, B: EntityType>: _Include2 {
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include2 {
|
||||
@@ -180,6 +216,19 @@ public enum Include3<A: EntityType, B: EntityType, C: EntityType>: _Include3 {
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
case .c(let c):
|
||||
try container.encode(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include3 {
|
||||
@@ -238,6 +287,21 @@ public enum Include4<A: EntityType, B: EntityType, C: EntityType, D: EntityType>
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
case .c(let c):
|
||||
try container.encode(c)
|
||||
case .d(let d):
|
||||
try container.encode(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include4 {
|
||||
@@ -303,6 +367,23 @@ public enum Include5<A: EntityType, B: EntityType, C: EntityType, D: EntityType,
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
case .c(let c):
|
||||
try container.encode(c)
|
||||
case .d(let d):
|
||||
try container.encode(d)
|
||||
case .e(let e):
|
||||
try container.encode(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include5 {
|
||||
@@ -375,6 +456,25 @@ public enum Include6<A: EntityType, B: EntityType, C: EntityType, D: EntityType,
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
case .c(let c):
|
||||
try container.encode(c)
|
||||
case .d(let d):
|
||||
try container.encode(d)
|
||||
case .e(let e):
|
||||
try container.encode(e)
|
||||
case .f(let f):
|
||||
try container.encode(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Includes where I: _Include6 {
|
||||
|
||||
@@ -91,6 +91,7 @@ private enum ResourceIdentifierCodingKeys: String, CodingKey {
|
||||
|
||||
public enum JSONAPIEncodingError: Swift.Error {
|
||||
case typeMismatch(expected: String, found: String)
|
||||
case illegalEncoding(String)
|
||||
}
|
||||
|
||||
extension ToOneRelationship {
|
||||
|
||||
@@ -12,6 +12,11 @@ class IncludedTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(includes.count, 0)
|
||||
}
|
||||
|
||||
func test_zeroIncludes_encode() {
|
||||
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,
|
||||
@@ -19,6 +24,11 @@ class IncludedTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
}
|
||||
|
||||
func test_OneInclude_encode() {
|
||||
test_DecodeEncodeEquality(type: Includes<Include1<TestEntity>>.self,
|
||||
data: one_include)
|
||||
}
|
||||
|
||||
func test_TwoSameIncludes() {
|
||||
let includes = decoded(type: Includes<Include1<TestEntity>>.self,
|
||||
@@ -26,6 +36,11 @@ class IncludedTests: XCTestCase {
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 2)
|
||||
}
|
||||
|
||||
func test_TwoSameIncludes_encode() {
|
||||
test_DecodeEncodeEquality(type: Includes<Include1<TestEntity>>.self,
|
||||
data: two_same_type_includes)
|
||||
}
|
||||
|
||||
func test_TwoDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include2<TestEntity, TestEntity2>>.self,
|
||||
@@ -34,6 +49,11 @@ class IncludedTests: XCTestCase {
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
}
|
||||
|
||||
func test_TwoDifferentIncludes_encode() {
|
||||
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,
|
||||
@@ -43,6 +63,11 @@ class IncludedTests: XCTestCase {
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity4.self].count, 1)
|
||||
}
|
||||
|
||||
func test_ThreeDifferentIncludes_encode() {
|
||||
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,
|
||||
@@ -53,6 +78,11 @@ class IncludedTests: XCTestCase {
|
||||
XCTAssertEqual(includes[TestEntity4.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity6.self].count, 1)
|
||||
}
|
||||
|
||||
func test_FourDifferentIncludes_encode() {
|
||||
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,
|
||||
@@ -64,6 +94,11 @@ class IncludedTests: XCTestCase {
|
||||
XCTAssertEqual(includes[TestEntity4.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity6.self].count, 1)
|
||||
}
|
||||
|
||||
func test_FiveDifferentIncludes_encode() {
|
||||
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,
|
||||
@@ -76,6 +111,11 @@ class IncludedTests: XCTestCase {
|
||||
XCTAssertEqual(includes[TestEntity5.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity6.self].count, 1)
|
||||
}
|
||||
|
||||
func test_SixDifferentIncludes_encode() {
|
||||
test_DecodeEncodeEquality(type: Includes<Include6<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6>>.self,
|
||||
data: six_different_type_includes)
|
||||
}
|
||||
}
|
||||
|
||||
extension IncludedTests {
|
||||
|
||||
@@ -12,33 +12,63 @@ extension DocumentTests {
|
||||
extension EntityTests {
|
||||
static let __allTests = [
|
||||
("test_entityAllAttribute", test_entityAllAttribute),
|
||||
("test_entityAllAttribute_encode", test_entityAllAttribute_encode),
|
||||
("test_entityBrokenNullableOmittedAttribute", test_entityBrokenNullableOmittedAttribute),
|
||||
("test_EntityNoRelationshipsNoAttributes", test_EntityNoRelationshipsNoAttributes),
|
||||
("test_EntityNoRelationshipsNoAttributes_encode", test_EntityNoRelationshipsNoAttributes_encode),
|
||||
("test_EntityNoRelationshipsSomeAttributes", test_EntityNoRelationshipsSomeAttributes),
|
||||
("test_EntityNoRelationshipsSomeAttributes_encode", test_EntityNoRelationshipsSomeAttributes_encode),
|
||||
("test_entityOneNullAndOneOmittedAttribute", test_entityOneNullAndOneOmittedAttribute),
|
||||
("test_entityOneNullAndOneOmittedAttribute_encode", test_entityOneNullAndOneOmittedAttribute_encode),
|
||||
("test_entityOneNullAttribute", test_entityOneNullAttribute),
|
||||
("test_entityOneNullAttribute_encode", test_entityOneNullAttribute_encode),
|
||||
("test_entityOneOmittedAttribute", test_entityOneOmittedAttribute),
|
||||
("test_entityOneOmittedAttribute_encode", test_entityOneOmittedAttribute_encode),
|
||||
("test_EntitySomeRelationshipsNoAttributes", test_EntitySomeRelationshipsNoAttributes),
|
||||
("test_EntitySomeRelationshipsNoAttributes_encode", test_EntitySomeRelationshipsNoAttributes_encode),
|
||||
("test_EntitySomeRelationshipsSomeAttributes", test_EntitySomeRelationshipsSomeAttributes),
|
||||
("test_EntitySomeRelationshipsSomeAttributes_encode", test_EntitySomeRelationshipsSomeAttributes_encode),
|
||||
("test_IntToString", test_IntToString),
|
||||
("test_IntToString_encode", test_IntToString_encode),
|
||||
("test_NonNullOptionalNullableAttribute", test_NonNullOptionalNullableAttribute),
|
||||
("test_NonNullOptionalNullableAttribute_encode", test_NonNullOptionalNullableAttribute_encode),
|
||||
("test_nullableRelationshipIsNull", test_nullableRelationshipIsNull),
|
||||
("test_nullableRelationshipIsNull_encode", test_nullableRelationshipIsNull_encode),
|
||||
("test_nullableRelationshipNotNull", test_nullableRelationshipNotNull),
|
||||
("test_nullableRelationshipNotNull_encode", test_nullableRelationshipNotNull_encode),
|
||||
("test_NullOptionalNullableAttribute", test_NullOptionalNullableAttribute),
|
||||
("test_NullOptionalNullableAttribute_encode", test_NullOptionalNullableAttribute_encode),
|
||||
("test_relationship_access", test_relationship_access),
|
||||
("test_relationship_operator_access", test_relationship_operator_access),
|
||||
("test_relationshipIds", test_relationshipIds),
|
||||
("test_RleationshipsOfSameType", test_RleationshipsOfSameType),
|
||||
("test_RleationshipsOfSameType_encode", test_RleationshipsOfSameType_encode),
|
||||
("test_toMany_relationship_operator_access", test_toMany_relationship_operator_access),
|
||||
("test_UnidentifiedEntity", test_UnidentifiedEntity),
|
||||
("test_UnidentifiedEntity_encode", test_UnidentifiedEntity_encode),
|
||||
("test_UnidentifiedEntityWithAttributes", test_UnidentifiedEntityWithAttributes),
|
||||
("test_UnidentifiedEntityWithAttributes_encode", test_UnidentifiedEntityWithAttributes_encode),
|
||||
]
|
||||
}
|
||||
|
||||
extension IncludedTests {
|
||||
static let __allTests = [
|
||||
("test_FiveDifferentIncludes", test_FiveDifferentIncludes),
|
||||
("test_FiveDifferentIncludes_encode", test_FiveDifferentIncludes_encode),
|
||||
("test_FourDifferentIncludes", test_FourDifferentIncludes),
|
||||
("test_FourDifferentIncludes_encode", test_FourDifferentIncludes_encode),
|
||||
("test_OneInclude", test_OneInclude),
|
||||
("test_OneInclude_encode", test_OneInclude_encode),
|
||||
("test_SixDifferentIncludes", test_SixDifferentIncludes),
|
||||
("test_SixDifferentIncludes_encode", test_SixDifferentIncludes_encode),
|
||||
("test_ThreeDifferentIncludes", test_ThreeDifferentIncludes),
|
||||
("test_ThreeDifferentIncludes_encode", test_ThreeDifferentIncludes_encode),
|
||||
("test_TwoDifferentIncludes", test_TwoDifferentIncludes),
|
||||
("test_TwoDifferentIncludes_encode", test_TwoDifferentIncludes_encode),
|
||||
("test_TwoSameIncludes", test_TwoSameIncludes),
|
||||
("test_TwoSameIncludes_encode", test_TwoSameIncludes_encode),
|
||||
("test_zeroIncludes", test_zeroIncludes),
|
||||
("test_zeroIncludes_encode", test_zeroIncludes_encode),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -47,14 +77,20 @@ extension RelationshipTests {
|
||||
("test_initToManyWithEntities", test_initToManyWithEntities),
|
||||
("test_initToManyWithRelationships", test_initToManyWithRelationships),
|
||||
("test_ToManyRelationship", test_ToManyRelationship),
|
||||
("test_ToManyRelationship_encode", test_ToManyRelationship_encode),
|
||||
("test_ToOneRelationship", test_ToOneRelationship),
|
||||
("test_ToOneRelationship_encode", test_ToOneRelationship_encode),
|
||||
]
|
||||
}
|
||||
|
||||
extension ResourceBodyTests {
|
||||
static let __allTests = [
|
||||
("test_manyResourceBody", test_manyResourceBody),
|
||||
("test_manyResourceBody_encode", test_manyResourceBody_encode),
|
||||
("test_manyResourceBodyEmpty", test_manyResourceBodyEmpty),
|
||||
("test_manyResourceBodyEmpty_encode", test_manyResourceBodyEmpty_encode),
|
||||
("test_singleResourceBody", test_singleResourceBody),
|
||||
("test_singleResourceBody_encode", test_singleResourceBody_encode),
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user