import XCTest @testable import JSONAPI class IncludedTests: XCTestCase { func test_zeroIncludes_init() { let includes = Includes() XCTAssertEqual(includes.count, 0) } func test_zeroIncludes() { let includes = decoded(type: Includes.self, data: two_same_type_includes) XCTAssertEqual(includes.count, 0) } func test_zeroIncludes_encode() { XCTAssertThrowsError(try JSONEncoder().encode(decoded(type: Includes.self, data: two_same_type_includes))) } func test_OneInclude() { let includes = decoded(type: Includes>.self, data: one_include) XCTAssertEqual(includes[TestEntity.self].count, 1) } func test_OneInclude_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: one_include) } func test_TwoSameIncludes() { let includes = decoded(type: Includes>.self, data: two_same_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 2) } func test_TwoSameIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: two_same_type_includes) } func test_TwoDifferentIncludes() { let includes = decoded(type: Includes>.self, data: two_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) } func test_TwoDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: two_different_type_includes) } func test_ThreeDifferentIncludes() { let includes = decoded(type: Includes>.self, data: three_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) } func test_ThreeDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: three_different_type_includes) } func test_FourDifferentIncludes() { let includes = decoded(type: Includes>.self, data: four_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) } func test_FourDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: four_different_type_includes) } func test_FiveDifferentIncludes() { let includes = decoded(type: Includes>.self, data: five_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) } func test_FiveDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: five_different_type_includes) } func test_SixDifferentIncludes() { let includes = decoded(type: Includes>.self, data: six_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) } func test_SixDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: six_different_type_includes) } func test_SevenDifferentIncludes() { let includes = decoded(type: Includes>.self, data: seven_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) XCTAssertEqual(includes[TestEntity7.self].count, 1) } func test_SevenDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: seven_different_type_includes) } func test_EightDifferentIncludes() { let includes = decoded(type: Includes>.self, data: eight_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) XCTAssertEqual(includes[TestEntity7.self].count, 1) XCTAssertEqual(includes[TestEntity8.self].count, 1) } func test_EightDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: eight_different_type_includes) } func test_NineDifferentIncludes() { let includes = decoded(type: Includes>.self, data: nine_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) XCTAssertEqual(includes[TestEntity7.self].count, 1) XCTAssertEqual(includes[TestEntity8.self].count, 1) XCTAssertEqual(includes[TestEntity9.self].count, 1) } func test_NineDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: nine_different_type_includes) } func test_TenDifferentIncludes() { let includes = decoded(type: Includes>.self, data: ten_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) XCTAssertEqual(includes[TestEntity7.self].count, 1) XCTAssertEqual(includes[TestEntity8.self].count, 1) XCTAssertEqual(includes[TestEntity9.self].count, 1) XCTAssertEqual(includes[TestEntity10.self].count, 1) } func test_TenDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: ten_different_type_includes) } func test_ElevenDifferentIncludes() { let includes = decoded(type: Includes>.self, data: eleven_different_type_includes) XCTAssertEqual(includes[TestEntity.self].count, 1) XCTAssertEqual(includes[TestEntity2.self].count, 1) XCTAssertEqual(includes[TestEntity3.self].count, 1) XCTAssertEqual(includes[TestEntity4.self].count, 1) XCTAssertEqual(includes[TestEntity5.self].count, 1) XCTAssertEqual(includes[TestEntity6.self].count, 1) XCTAssertEqual(includes[TestEntity7.self].count, 1) XCTAssertEqual(includes[TestEntity8.self].count, 1) XCTAssertEqual(includes[TestEntity9.self].count, 1) XCTAssertEqual(includes[TestEntity10.self].count, 1) XCTAssertEqual(includes[TestEntity11.self].count, 1) } func test_ElevenDifferentIncludes_encode() { test_DecodeEncodeEquality(type: Includes>.self, data: eleven_different_type_includes) } } // MARK: - Appending extension IncludedTests { func test_appending() { let include1 = Includes>(values: [.init(TestEntity8(attributes: .none, relationships: .none, meta: .none, links: .none)), .init(TestEntity9(attributes: .none, relationships: .none, meta: .none, links: .none)), .init(TestEntity8(attributes: .none, relationships: .none, meta: .none, links: .none))]) let include2 = Includes>(values: [.init(TestEntity8(attributes: .none, relationships: .none, meta: .none, links: .none)), .init(TestEntity9(attributes: .none, relationships: .none, meta: .none, links: .none)), .init(TestEntity8(attributes: .none, relationships: .none, meta: .none, links: .none))]) let combined = include1 + include2 XCTAssertEqual(combined.values, include1.values + include2.values) } } // MARK: - Sparse Fieldsets extension IncludedTests { func test_OneSparseIncludeType() { let include1 = TestEntity(attributes: .init(foo: "hello", bar: 10), relationships: .none, meta: .none, links: .none) .sparse(with: [.foo]) let includes: Includes> = .init(values: [.init(include1)]) let encoded = try! JSONEncoder().encode(includes) let deserialized = try! JSONSerialization.jsonObject(with: encoded, options: []) let deserializedObj = deserialized as? [Any] XCTAssertEqual(deserializedObj?.count, 1) guard let deserializedObj1 = deserializedObj?.first as? [String: Any] else { XCTFail("Expected to deserialize one object from array") return } XCTAssertNotNil(deserializedObj1["id"]) XCTAssertEqual(deserializedObj1["id"] as? String, include1.resourceObject.id.rawValue) XCTAssertNotNil(deserializedObj1["type"]) XCTAssertEqual(deserializedObj1["type"] as? String, TestEntity.jsonType) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 1) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?["foo"] as? String, "hello") XCTAssertNil(deserializedObj1["relationships"]) } func test_TwoSparseIncludeTypes() { let include1 = TestEntity(attributes: .init(foo: "hello", bar: 10), relationships: .none, meta: .none, links: .none) .sparse(with: [.foo]) let include2 = TestEntity2(attributes: .init(foo: "world", bar: 2), relationships: .init(entity1: "1234"), meta: .none, links: .none) .sparse(with: [.bar]) let includes: Includes> = .init(values: [.init(include1), .init(include2)]) let encoded = try! JSONEncoder().encode(includes) let deserialized = try! JSONSerialization.jsonObject(with: encoded, options: []) let deserializedObj = deserialized as? [Any] XCTAssertEqual(deserializedObj?.count, 2) guard let deserializedObj1 = deserializedObj?.first as? [String: Any], let deserializedObj2 = deserializedObj?.last as? [String: Any] else { XCTFail("Expected to deserialize two objects from array") return } // first include XCTAssertNotNil(deserializedObj1["id"]) XCTAssertEqual(deserializedObj1["id"] as? String, include1.resourceObject.id.rawValue) XCTAssertNotNil(deserializedObj1["type"]) XCTAssertEqual(deserializedObj1["type"] as? String, TestEntity.jsonType) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 1) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?["foo"] as? String, "hello") XCTAssertNil(deserializedObj1["relationships"]) // second include XCTAssertNotNil(deserializedObj2["id"]) XCTAssertEqual(deserializedObj2["id"] as? String, include2.resourceObject.id.rawValue) XCTAssertNotNil(deserializedObj2["type"]) XCTAssertEqual(deserializedObj2["type"] as? String, TestEntity2.jsonType) XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?.count, 1) XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?["bar"] as? Int, 2) XCTAssertNotNil(deserializedObj2["relationships"]) XCTAssertNotNil((deserializedObj2["relationships"] as? [String: Any])?["entity1"]) } func test_ComboSparseAndFullIncludeTypes() { let include1 = TestEntity(attributes: .init(foo: "hello", bar: 10), relationships: .none, meta: .none, links: .none) .sparse(with: [.foo]) let include2 = TestEntity2(attributes: .init(foo: "world", bar: 2), relationships: .init(entity1: "1234"), meta: .none, links: .none) let includes: Includes> = .init(values: [.init(include1), .init(include2)]) let encoded = try! JSONEncoder().encode(includes) let deserialized = try! JSONSerialization.jsonObject(with: encoded, options: []) let deserializedObj = deserialized as? [Any] XCTAssertEqual(deserializedObj?.count, 2) guard let deserializedObj1 = deserializedObj?.first as? [String: Any], let deserializedObj2 = deserializedObj?.last as? [String: Any] else { XCTFail("Expected to deserialize two objects from array") return } // first include XCTAssertNotNil(deserializedObj1["id"]) XCTAssertEqual(deserializedObj1["id"] as? String, include1.resourceObject.id.rawValue) XCTAssertNotNil(deserializedObj1["type"]) XCTAssertEqual(deserializedObj1["type"] as? String, TestEntity.jsonType) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?.count, 1) XCTAssertEqual((deserializedObj1["attributes"] as? [String: Any])?["foo"] as? String, "hello") XCTAssertNil(deserializedObj1["relationships"]) // second include XCTAssertNotNil(deserializedObj2["id"]) XCTAssertEqual(deserializedObj2["id"] as? String, include2.id.rawValue) XCTAssertNotNil(deserializedObj2["type"]) XCTAssertEqual(deserializedObj2["type"] as? String, TestEntity2.jsonType) XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?.count, 2) XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?["foo"] as? String, "world") XCTAssertEqual((deserializedObj2["attributes"] as? [String: Any])?["bar"] as? Int, 2) XCTAssertNotNil(deserializedObj2["relationships"]) XCTAssertNotNil((deserializedObj2["relationships"] as? [String: Any])?["entity1"]) } } // MARK: - Test types extension IncludedTests { enum TestEntityType: ResourceObjectDescription { typealias Relationships = NoRelationships public static var jsonType: String { return "test_entity1" } public struct Attributes: JSONAPI.SparsableAttributes { let foo: Attribute let bar: Attribute public enum CodingKeys: String, Equatable, CodingKey { case foo case bar } } } typealias TestEntity = BasicEntity enum TestEntityType2: ResourceObjectDescription { public static var jsonType: String { return "test_entity2" } public struct Relationships: JSONAPI.Relationships { let entity1: ToOneRelationship } public struct Attributes: JSONAPI.SparsableAttributes { let foo: Attribute let bar: Attribute public enum CodingKeys: String, Equatable, CodingKey { case foo case bar } } } typealias TestEntity2 = BasicEntity enum TestEntityType3: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity3" } public struct Relationships: JSONAPI.Relationships { let entity1: ToOneRelationship let entity2: ToManyRelationship } } typealias TestEntity3 = BasicEntity enum TestEntityType4: ResourceObjectDescription { typealias Attributes = NoAttributes typealias Relationships = NoRelationships public static var jsonType: String { return "test_entity4" } } typealias TestEntity4 = BasicEntity enum TestEntityType5: ResourceObjectDescription { typealias Attributes = NoAttributes typealias Relationships = NoRelationships public static var jsonType: String { return "test_entity5" } } typealias TestEntity5 = BasicEntity enum TestEntityType6: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity6" } struct Relationships: JSONAPI.Relationships { let entity4: ToOneRelationship } } typealias TestEntity6 = BasicEntity enum TestEntityType7: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity7" } typealias Relationships = NoRelationships } typealias TestEntity7 = BasicEntity enum TestEntityType8: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity8" } typealias Relationships = NoRelationships } typealias TestEntity8 = BasicEntity enum TestEntityType9: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity9" } typealias Relationships = NoRelationships } typealias TestEntity9 = BasicEntity enum TestEntityType10: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity10" } typealias Relationships = NoRelationships } typealias TestEntity10 = BasicEntity enum TestEntityType11: ResourceObjectDescription { typealias Attributes = NoAttributes public static var jsonType: String { return "test_entity11" } typealias Relationships = NoRelationships } typealias TestEntity11 = BasicEntity }