From dd5f3b1737ed9df17dbe3d51470632040f4bcd6f Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Tue, 27 Nov 2018 13:57:55 -0800 Subject: [PATCH] Added check for nullable array attributes --- README.md | 2 +- Sources/JSONAPITestLib/EntityCheck.swift | 24 ++++++++++++++----- .../TestLib/EntityCheckTests.swift | 18 ++++++++++++++ Tests/JSONAPITests/XCTestManifests.swift | 1 + 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5e5b207..e0784d8 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ To create an Xcode project for JSONAPI, run - [x] `meta` ### Entity Validator (using reflection) -- [ ] Disallow optional array in `Attribute` and `Relationship` (should be empty array, not `null`). +- [x] Disallow optional array in `Attribute` (should be empty array, not `null`). - [x] Only allow `TransformedAttribute` and its derivatives within `Attributes` struct. - [x] Only allow `ToManyRelationship` and `ToOneRelationship` within `Relationships` struct. diff --git a/Sources/JSONAPITestLib/EntityCheck.swift b/Sources/JSONAPITestLib/EntityCheck.swift index 8517236..c628867 100644 --- a/Sources/JSONAPITestLib/EntityCheck.swift +++ b/Sources/JSONAPITestLib/EntityCheck.swift @@ -10,8 +10,9 @@ import JSONAPI public enum EntityCheckError: Swift.Error { case attributesNotStruct case relationshipsNotStruct - case badAttribute(named: String) - case badRelationship(named: String) + case nonAttribute(named: String) + case nonRelationship(named: String) + case nullArray(named: String) case badId } @@ -19,10 +20,18 @@ public struct EntityCheckErrors: Swift.Error { let problems: [EntityCheckError] } -public protocol OptionalAttributeType {} - +private protocol OptionalAttributeType {} extension Optional: OptionalAttributeType where Wrapped: AttributeType {} +private protocol OptionalArray {} +extension Optional: OptionalArray where Wrapped: ArrayType {} + +private protocol AttributeTypeWithOptionalArray {} +extension TransformedAttribute: AttributeTypeWithOptionalArray where RawValue: OptionalArray {} + +private protocol OptionalRelationshipType {} +extension Optional: OptionalRelationshipType where Wrapped: RelationshipType {} + public extension Entity { public static func check(_ entity: Entity) throws { var problems = [EntityCheckError]() @@ -40,7 +49,10 @@ public extension Entity { for attribute in attributesMirror.children { if attribute.value as? AttributeType == nil, attribute.value as? OptionalAttributeType == nil { - problems.append(.badAttribute(named: attribute.label ?? "unnamed")) + problems.append(.nonAttribute(named: attribute.label ?? "unnamed")) + } + if attribute.value as? AttributeTypeWithOptionalArray != nil { + problems.append(.nullArray(named: attribute.label ?? "unnamed")) } } @@ -52,7 +64,7 @@ public extension Entity { for relationship in relationshipsMirror.children { if relationship.value as? RelationshipType == nil { - problems.append(.badRelationship(named: relationship.label ?? "unnamed")) + problems.append(.nonRelationship(named: relationship.label ?? "unnamed")) } } diff --git a/Tests/JSONAPITests/TestLib/EntityCheckTests.swift b/Tests/JSONAPITests/TestLib/EntityCheckTests.swift index 72fd08b..f92d69f 100644 --- a/Tests/JSONAPITests/TestLib/EntityCheckTests.swift +++ b/Tests/JSONAPITests/TestLib/EntityCheckTests.swift @@ -36,6 +36,11 @@ class EntityCheckTests: XCTestCase { let entity = BadRelationshipEntity(relationships: .init(x: OkEntity().pointer, y: OkEntity().id)) XCTAssertThrowsError(try BadRelationshipEntity.check(entity)) } + + func test_failsWithOptionalArrayAttribute() { + let entity = OptionalArrayAttributeEntity(attributes: .init(x: ["hello"], y: nil)) + XCTAssertThrowsError(try OptionalArrayAttributeEntity.check(entity)) + } } // MARK: - Test types @@ -121,4 +126,17 @@ extension EntityCheckTests { } public typealias BadRelationshipEntity = Entity + + enum OptionalArrayAttributeDescription: EntityDescription { + public static var type: String { return "hello" } + + public struct Attributes: JSONAPI.Attributes { + let x: Attribute<[String]> + let y: Attribute<[String]?> + } + + public typealias Relationships = NoRelationships + } + + public typealias OptionalArrayAttributeEntity = Entity } diff --git a/Tests/JSONAPITests/XCTestManifests.swift b/Tests/JSONAPITests/XCTestManifests.swift index 06ddbfa..2abf868 100644 --- a/Tests/JSONAPITests/XCTestManifests.swift +++ b/Tests/JSONAPITests/XCTestManifests.swift @@ -74,6 +74,7 @@ extension EntityCheckTests { ("test_failsWithBadRelationship", test_failsWithBadRelationship), ("test_failsWithEnumAttributes", test_failsWithEnumAttributes), ("test_failsWithEnumRelationships", test_failsWithEnumRelationships), + ("test_failsWithOptionalArrayAttribute", test_failsWithOptionalArrayAttribute), ] }