From 163ac94c519127c78ee6ff204d624d56e305d2e9 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Wed, 28 Nov 2018 21:13:07 -0800 Subject: [PATCH] I did some more type wrangling to finally get the Id type to specialize on Entity rather than EntityDescription. The compiler gets into trouble depending on which of a few semantically identical routes are taken, but I finally stumbled upon the correct combination of protocols and extensions to get the job done. this was always the ideal outcome, but I was not sure the Swift compiler would allow it. --- .../Usage.xcplaygroundpage/Contents.swift | 5 ++- JSONAPI.playground/Sources/Entities.swift | 12 ++--- README.md | 4 +- Sources/JSONAPI/Document/Document.swift | 19 +++++++- Sources/JSONAPI/Meta/Links.swift | 4 +- Sources/JSONAPI/Meta/Meta.swift | 4 +- Sources/JSONAPI/Resource/Entity.swift | 44 ++++++++++++------- Sources/JSONAPI/Resource/Id.swift | 37 ++++++++++------ Sources/JSONAPI/Resource/Poly.swift | 12 ++--- Sources/JSONAPI/Resource/Relationship.swift | 14 +++--- Sources/JSONAPITestLib/EntityCheck.swift | 2 +- Tests/JSONAPITests/Entity/EntityTests.swift | 8 ++-- .../JSONAPITestLib/EntityCheckTests.swift | 9 +--- .../JSONAPITestLib/Id+LiteralTests.swift | 4 +- .../ResourceBody/ResourceBodyTests.swift | 2 +- .../JSONAPITests/Test Helpers/Entity+Id.swift | 4 +- Tests/JSONAPITests/XCTestManifests.swift | 1 - 17 files changed, 110 insertions(+), 75 deletions(-) diff --git a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift index ac259aa..6b89adf 100644 --- a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift +++ b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift @@ -40,10 +40,13 @@ let peopleFromData = peopleResponse.body.primaryData?.values let dogsFromData = peopleResponse.body.includes?[Dog.self] let housesFromData = peopleResponse.body.includes?[House.self] +print("-----") +print(peopleResponse) +print("-----") + // MARK: - Pass successfully parsed body to other parts of the code if case let .data(bodyData) = peopleResponse.body { - print(bodyData) print("first person's name: \(bodyData.primary.values[0][\.fullName])") } else { print("no body data") diff --git a/JSONAPI.playground/Sources/Entities.swift b/JSONAPI.playground/Sources/Entities.swift index 025abaa..484073b 100644 --- a/JSONAPI.playground/Sources/Entities.swift +++ b/JSONAPI.playground/Sources/Entities.swift @@ -24,7 +24,7 @@ extension String: CreatableRawIdType { } // MARK: - Entity typealias for convenience -public typealias ExampleEntity = Entity> +public typealias ExampleEntity = Entity // MARK: - A few resource objects (entities) public enum PersonDescription: EntityDescription { @@ -60,9 +60,9 @@ public enum PersonDescription: EntityDescription { public typealias Person = ExampleEntity -public extension Entity where Description == PersonDescription, Identifier == Id { - public init(id: Person.Identifier? = nil,name: [String], favoriteColor: String, friends: [Person], dogs: [Dog], home: House) throws { - self = try Person(id: id ?? Person.Identifier(), attributes: .init(name: .init(rawValue: name), favoriteColor: .init(rawValue: favoriteColor)), relationships: .init(friends: .init(entities: friends), dogs: .init(entities: dogs), home: .init(entity: home))) +public extension Entity where Description == PersonDescription, EntityRawIdType == String { + public init(id: Person.Id? = nil,name: [String], favoriteColor: String, friends: [Person], dogs: [Dog], home: House) throws { + self = try Person(id: id ?? Person.Id(), attributes: .init(name: .init(rawValue: name), favoriteColor: .init(rawValue: favoriteColor)), relationships: .init(friends: .init(entities: friends), dogs: .init(entities: dogs), home: .init(entity: home))) } } @@ -89,12 +89,12 @@ public enum DogDescription: EntityDescription { public typealias Dog = ExampleEntity -public extension Entity where Description == DogDescription, Identifier == Id { +public extension Entity where Description == DogDescription, EntityRawIdType == String { public init(name: String, owner: Person?) throws { self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: DogDescription.Relationships(owner: .init(entity: owner))) } - public init(name: String, owner: Person.Identifier) throws { + public init(name: String, owner: Person.Id) throws { self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: .init(owner: .init(id: owner))) } } diff --git a/README.md b/README.md index c2a9013..3f3ce3a 100644 --- a/README.md +++ b/README.md @@ -170,13 +170,13 @@ An `Entity` needs to be specialized on two generic types. The first is the `Enti #### `IdType` -An `IdType` packages up two pieces of information: A unique identifier of a given `RawIdType` and the `EntityDescription` of the type of entity the Id identifies. Having the `EntityDescription` type associated with the Id makes it easy to store all of your entities in a local hash broken out by `EntityDescription`; You can pass Ids around and always know where to look for the `Entity` to which the Id refers. `RawIdType`s are documented below. +An `IdType` packages up two pieces of information: A unique identifier of a given `RawIdType` and the `Entity` type that the Id identifies. Having the `Entity` type associated with the Id makes it easy to store all of your entities in a local hash broken out by `Entity` type; You can pass Ids around and always know where to look for the `Entity` to which the Id refers. `RawIdType`s are documented below. #### Convenient `typealiases` Often you can use one `RawIdType` for many if not all of your `Entities`. That means you can save yourself some boilerplate by using `typealias`es like the following: ``` -public typealias Entity = JSONAPI.Entity> +public typealias Entity = JSONAPI.Entity public typealias NewEntity = JSONAPI.Entity ``` diff --git a/Sources/JSONAPI/Document/Document.swift b/Sources/JSONAPI/Document/Document.swift index 93aefb0..5fb7810 100644 --- a/Sources/JSONAPI/Document/Document.swift +++ b/Sources/JSONAPI/Document/Document.swift @@ -243,6 +243,23 @@ extension Document { extension Document: CustomStringConvertible { public var description: String { - return "Document(body: \(String(describing: body))" + return "Document(\(String(describing: body)))" + } +} + +extension Document.Body: CustomStringConvertible { + public var description: String { + switch self { + case .errors(let errors, meta: let meta, links: let links): + return "errors: \(String(describing: errors)), meta: \(String(describing: meta)), links: \(String(describing: links))" + case .data(let data): + return String(describing: data) + } + } +} + +extension Document.Body.Data: CustomStringConvertible { + public var description: String { + return "primary: \(String(describing: primary)), includes: \(String(describing: includes)), meta: \(String(describing: meta)), links: \(String(describing: links))" } } diff --git a/Sources/JSONAPI/Meta/Links.swift b/Sources/JSONAPI/Meta/Links.swift index e01d0ee..fb18008 100644 --- a/Sources/JSONAPI/Meta/Links.swift +++ b/Sources/JSONAPI/Meta/Links.swift @@ -9,9 +9,11 @@ public protocol Links: Codable, Equatable {} /// Use NoLinks where no links should belong to a JSON API component -public struct NoLinks: Links { +public struct NoLinks: Links, CustomStringConvertible { public static var none: NoLinks { return NoLinks() } public init() {} + + public var description: String { return "No Links" } } public protocol JSONAPIURL: Codable, Equatable {} diff --git a/Sources/JSONAPI/Meta/Meta.swift b/Sources/JSONAPI/Meta/Meta.swift index 318c438..587dc9c 100644 --- a/Sources/JSONAPI/Meta/Meta.swift +++ b/Sources/JSONAPI/Meta/Meta.swift @@ -19,8 +19,10 @@ public protocol Meta: Codable, Equatable { // nullable. extension Optional: Meta where Wrapped: Meta {} -public struct NoMetadata: Meta { +public struct NoMetadata: Meta, CustomStringConvertible { public static var none: NoMetadata { return NoMetadata() } public init() { } + + public var description: String { return "No Metadata" } } diff --git a/Sources/JSONAPI/Resource/Entity.swift b/Sources/JSONAPI/Resource/Entity.swift index b7a3031..b405162 100644 --- a/Sources/JSONAPI/Resource/Entity.swift +++ b/Sources/JSONAPI/Resource/Entity.swift @@ -39,7 +39,9 @@ public protocol EntityDescription { /// specialization. public protocol EntityType: PrimaryResource { associatedtype Description: EntityDescription - associatedtype Identifier: Equatable & Codable + associatedtype EntityRawIdType: JSONAPI.MaybeRawId + + typealias Id = JSONAPI.Id typealias Attributes = Description.Attributes typealias Relationships = Description.Relationships @@ -48,7 +50,7 @@ public protocol EntityType: PrimaryResource { /// the entity is being created clientside and the /// server is being asked to create a unique Id. Otherwise, /// this should be of a type conforming to `IdType`. - var id: Identifier { get } + var id: Id { get } /// The JSON API compliant attributes of this `Entity`. var attributes: Attributes { get } @@ -57,11 +59,13 @@ public protocol EntityType: PrimaryResource { var relationships: Relationships { get } } +public protocol IdentifiableEntityType: EntityType, Relatable where EntityRawIdType: JSONAPI.RawIdType {} + /// An `Entity` is a single model type that can be /// encoded to or decoded from a JSON API /// "Resource Object." /// See https://jsonapi.org/format/#document-resource-objects -public struct Entity: EntityType { +public struct Entity: EntityType { /// The JSON API compliant "type" of this `Entity`. public static var type: String { return Description.type } @@ -70,7 +74,7 @@ public struct Entity(id: \(String(describing: id)), attributes: \(String(describing: attributes)), relationships: \(String(describing: relationships)))" @@ -92,52 +101,52 @@ extension Entity: CustomStringConvertible { } // MARK: Convenience initializers -extension Entity where Identifier: CreatableIdType { +extension Entity where EntityRawIdType: CreatableRawIdType { public init(attributes: Description.Attributes, relationships: Description.Relationships) { - self.id = Identifier() + self.id = Entity.Id() self.attributes = attributes self.relationships = relationships } } extension Entity where Description.Attributes == NoAttributes { - public init(id: Identifier, relationships: Description.Relationships) { + public init(id: Entity.Id, relationships: Description.Relationships) { self.init(id: id, attributes: NoAttributes(), relationships: relationships) } } -extension Entity where Description.Attributes == NoAttributes, Identifier: CreatableIdType { +extension Entity where Description.Attributes == NoAttributes, EntityRawIdType: CreatableRawIdType { public init(relationships: Description.Relationships) { self.init(attributes: NoAttributes(), relationships: relationships) } } extension Entity where Description.Relationships == NoRelationships { - public init(id: Identifier, attributes: Description.Attributes) { + public init(id: Entity.Id, attributes: Description.Attributes) { self.init(id: id, attributes: attributes, relationships: NoRelationships()) } } -extension Entity where Description.Relationships == NoRelationships, Identifier: CreatableIdType { +extension Entity where Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { public init(attributes: Description.Attributes) { self.init(attributes: attributes, relationships: NoRelationships()) } } extension Entity where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships { - public init(id: Identifier) { + public init(id: Entity.Id) { self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships()) } } -extension Entity where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, Identifier: CreatableIdType { +extension Entity where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { public init() { self.init(attributes: NoAttributes(), relationships: NoRelationships()) } } // MARK: Pointer for Relationships use. -public extension Entity where Identifier: IdType { +public extension Entity where EntityRawIdType: JSONAPI.RawIdType { /// Get a pointer to this entity that can be used as a /// relationship to another entity. public var pointer: ToOneRelationship { @@ -202,7 +211,7 @@ public extension Entity { try container.encode(Entity.type, forKey: .type) - if Identifier.self != Unidentified.self { + if EntityRawIdType.self != Unidentified.self { try container.encode(id, forKey: .id) } @@ -224,8 +233,9 @@ public extension Entity { guard Entity.type == type else { throw JSONAPIEncodingError.typeMismatch(expected: Description.type, found: type) } - - id = try (Unidentified() as? Identifier) ?? container.decode(Identifier.self, forKey: .id) + + let maybeUnidentified = Unidentified() as? EntityRawIdType + id = try maybeUnidentified.map { Entity.Id(rawValue: $0) } ?? container.decode(Entity.Id.self, forKey: .id) attributes = try (NoAttributes() as? Description.Attributes) ?? container.decode(Description.Attributes.self, forKey: .attributes) diff --git a/Sources/JSONAPI/Resource/Id.swift b/Sources/JSONAPI/Resource/Id.swift index 2627617..c388239 100644 --- a/Sources/JSONAPI/Resource/Id.swift +++ b/Sources/JSONAPI/Resource/Id.swift @@ -5,10 +5,16 @@ // Created by Mathew Polzin on 7/24/18. // +/// All types that are RawIdType and additionally +/// Unidentified conform to this protocol. You +/// should not add conformance to this protocol +/// directly. +public protocol MaybeRawId: Codable, Equatable {} + /// Any type that you would like to be encoded to and /// decoded from JSON API ids should conform to this /// protocol. Conformance for `String` is given. -public protocol RawIdType: Codable, Hashable {} +public protocol RawIdType: MaybeRawId, Hashable {} /// If you would like to be able to create new /// Entities with Ids backed by a RawIdType then @@ -22,19 +28,18 @@ public protocol CreatableRawIdType: RawIdType { extension String: RawIdType {} -public protocol Identifier: Codable, Equatable { - associatedtype EntityDescription: JSONAPI.EntityDescription -} - -public struct Unidentified: Identifier, CustomStringConvertible { +public struct Unidentified: MaybeRawId, CustomStringConvertible { public init() {} - public var description: String { return "Id(Unidentified)" } + public var description: String { return "Unidentified" } } -public protocol IdType: Identifier, Hashable, CustomStringConvertible { - associatedtype RawType: RawIdType - +public protocol MaybeId: Codable { + associatedtype EntityType: JSONAPI.EntityType + associatedtype RawType: MaybeRawId +} + +public protocol IdType: MaybeId, CustomStringConvertible, Hashable where RawType: RawIdType { var rawValue: RawType { get } } @@ -48,27 +53,33 @@ public protocol CreatableIdType: IdType { /// An Entity ID. These IDs can be encoded to or decoded from /// JSON API IDs. -public struct Id: IdType { +public struct Id: Codable, Equatable, MaybeId { public let rawValue: RawType public init(rawValue: RawType) { self.rawValue = rawValue } - + public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() rawValue = try container.decode(RawType.self) } - + public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() try container.encode(rawValue) } } +extension Id: Hashable, CustomStringConvertible, IdType where RawType: RawIdType {} + extension Id: CreatableIdType where RawType: CreatableRawIdType { public init() { rawValue = .unique() } } + +extension Id where RawType == Unidentified { + public static var unidentified: Id { return .init(rawValue: Unidentified()) } +} diff --git a/Sources/JSONAPI/Resource/Poly.swift b/Sources/JSONAPI/Resource/Poly.swift index bc3f4ba..51e5226 100644 --- a/Sources/JSONAPI/Resource/Poly.swift +++ b/Sources/JSONAPI/Resource/Poly.swift @@ -98,7 +98,7 @@ extension Poly1: CustomStringConvertible { case .a(let a): str = String(describing: a) } - return "Include(\(str))" + return "Poly(\(str))" } } @@ -177,7 +177,7 @@ extension Poly2: CustomStringConvertible { case .b(let b): str = String(describing: b) } - return "Include(\(str))" + return "Poly(\(str))" } } @@ -271,7 +271,7 @@ extension Poly3: CustomStringConvertible { case .c(let c): str = String(describing: c) } - return "Include(\(str))" + return "Poly(\(str))" } } @@ -380,7 +380,7 @@ extension Poly4: CustomStringConvertible { case .d(let d): str = String(describing: d) } - return "Include(\(str))" + return "Poly(\(str))" } } @@ -504,7 +504,7 @@ extension Poly5: CustomStringConvertible { case .e(let e): str = String(describing: e) } - return "Include(\(str))" + return "Poly(\(str))" } } @@ -643,6 +643,6 @@ extension Poly6: CustomStringConvertible { case .f(let f): str = String(describing: f) } - return "Include(\(str))" + return "Poly(\(str))" } } diff --git a/Sources/JSONAPI/Resource/Relationship.swift b/Sources/JSONAPI/Resource/Relationship.swift index 4c97019..2a5069e 100644 --- a/Sources/JSONAPI/Resource/Relationship.swift +++ b/Sources/JSONAPI/Resource/Relationship.swift @@ -21,13 +21,13 @@ public struct ToOneRelationship: Relations } extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier { - public init(entity: Entity) { + public init(entity: E) where E.Description == Relatable.Description, E.Id == Relatable.Identifier { id = entity.id } } -extension ToOneRelationship where Relatable.WrappedIdentifier == Optional { - public init(entity: Entity?) { +extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier? { + public init(entity: E?) where E.Description == Relatable.Description, E.Id == Relatable.Identifier { id = entity?.id } } @@ -58,7 +58,7 @@ public struct ToManyRelationship: RelationshipType } extension ToManyRelationship { - public init(entities: [Entity]) { + public init(entities: [E]) where E.Description == Relatable.Description, E.Id == Relatable.Identifier { ids = entities.map { $0.id } } } @@ -76,10 +76,6 @@ public typealias OptionalRelatable = WrappedRelatable /// has an IdType Identifier public protocol Relatable: WrappedRelatable {} -extension Entity: Relatable, WrappedRelatable where Identifier: JSONAPI.IdType { - public typealias WrappedIdentifier = Identifier -} - extension Optional: OptionalRelatable where Wrapped: Relatable { public typealias Description = Wrapped.Description public typealias Identifier = Wrapped.Identifier @@ -184,5 +180,5 @@ extension ToOneRelationship: CustomStringConvertible { } extension ToManyRelationship: CustomStringConvertible { - public var description: String { return "Relationship(\(String(describing: ids)))" } + public var description: String { return "Relationship([\(ids.map(String.init(describing:)).joined(separator: ", "))])" } } diff --git a/Sources/JSONAPITestLib/EntityCheck.swift b/Sources/JSONAPITestLib/EntityCheck.swift index c628867..5310531 100644 --- a/Sources/JSONAPITestLib/EntityCheck.swift +++ b/Sources/JSONAPITestLib/EntityCheck.swift @@ -36,7 +36,7 @@ public extension Entity { public static func check(_ entity: Entity) throws { var problems = [EntityCheckError]() - if Swift.type(of: entity.id).EntityDescription.self != Description.self { + if Swift.type(of: entity.id).EntityType.Description.self != Description.self { problems.append(.badId) } diff --git a/Tests/JSONAPITests/Entity/EntityTests.swift b/Tests/JSONAPITests/Entity/EntityTests.swift index 006cfe3..6cc32ad 100644 --- a/Tests/JSONAPITests/Entity/EntityTests.swift +++ b/Tests/JSONAPITests/Entity/EntityTests.swift @@ -294,7 +294,7 @@ extension EntityTests { data: entity_unidentified) XCTAssertNil(entity[\.me]) - XCTAssertEqual(entity.id, Unidentified()) + XCTAssertEqual(entity.id, .unidentified) XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity)) } @@ -308,7 +308,7 @@ extension EntityTests { data: entity_unidentified_with_attributes) XCTAssertEqual(entity[\.me], "unknown") - XCTAssertEqual(entity.id, Unidentified()) + XCTAssertEqual(entity.id, .unidentified) XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity)) } @@ -524,13 +524,13 @@ extension EntityTests { } } -extension Entity where Description == EntityTests.TestEntityType2, Identifier: CreatableIdType { +extension Entity where Description == EntityTests.TestEntityType2, EntityRawIdType: CreatableRawIdType { init(other: ToOneRelationship) { self.init(relationships: .init(other: other)) } } -extension Entity where Description == EntityTests.TestEntityType3, Identifier: CreatableIdType { +extension Entity where Description == EntityTests.TestEntityType3, EntityRawIdType: CreatableRawIdType { init(others: ToManyRelationship) { self.init(relationships: .init(others: others)) } diff --git a/Tests/JSONAPITests/JSONAPITestLib/EntityCheckTests.swift b/Tests/JSONAPITests/JSONAPITestLib/EntityCheckTests.swift index f92d69f..192db8f 100644 --- a/Tests/JSONAPITests/JSONAPITestLib/EntityCheckTests.swift +++ b/Tests/JSONAPITests/JSONAPITestLib/EntityCheckTests.swift @@ -12,11 +12,6 @@ import JSONAPITestLib // Successes are fairly well-checked by the EntityTests. We will confirm failure cases are working // in this file. class EntityCheckTests: XCTestCase { - func test_FailsWithBadId() { - let entity = BadIdEntity() - XCTAssertThrowsError(try BadIdEntity.check(entity)) - } - func test_failsWithEnumAttributes() { let entity = EnumAttributesEntity(attributes: .hello) XCTAssertThrowsError(try EnumAttributesEntity.check(entity)) @@ -61,7 +56,7 @@ extension EntityCheckTests { public typealias Relationships = NoRelationships } - public typealias BadIdEntity = JSONAPI.Entity> + public typealias OtherOkEntity = Entity enum EnumAttributesDescription: EntityDescription { public static var type: String { return "hello" } @@ -121,7 +116,7 @@ extension EntityCheckTests { public struct Relationships: JSONAPI.Relationships { let x: ToOneRelationship - let y: Id + let y: Id } } diff --git a/Tests/JSONAPITests/JSONAPITestLib/Id+LiteralTests.swift b/Tests/JSONAPITests/JSONAPITestLib/Id+LiteralTests.swift index 70fac44..0cefdae 100644 --- a/Tests/JSONAPITests/JSONAPITestLib/Id+LiteralTests.swift +++ b/Tests/JSONAPITests/JSONAPITestLib/Id+LiteralTests.swift @@ -14,11 +14,11 @@ extension Int: RawIdType {} class Id_LiteralTests: XCTestCase { func test_StringLiteral() { - XCTAssertEqual(Id(rawValue: "hello"), "hello") + XCTAssertEqual(Id(rawValue: "hello"), "hello") } func test_IntegerLiteral() { - XCTAssertEqual(Id(rawValue: 121), 121) + XCTAssertEqual(Id(rawValue: 121), 121) } } diff --git a/Tests/JSONAPITests/ResourceBody/ResourceBodyTests.swift b/Tests/JSONAPITests/ResourceBody/ResourceBodyTests.swift index 3360877..124c5d4 100644 --- a/Tests/JSONAPITests/ResourceBody/ResourceBodyTests.swift +++ b/Tests/JSONAPITests/ResourceBody/ResourceBodyTests.swift @@ -14,7 +14,7 @@ class ResourceBodyTests: XCTestCase { let body = decoded(type: SingleResourceBody
.self, data: single_resource_body) - XCTAssertEqual(body.value, Article(id: Id(rawValue: "1"), + XCTAssertEqual(body.value, Article(id: Id(rawValue: "1"), attributes: ArticleType.Attributes(title: try! .init(rawValue: "JSON:API paints my bikeshed!")))) } diff --git a/Tests/JSONAPITests/Test Helpers/Entity+Id.swift b/Tests/JSONAPITests/Test Helpers/Entity+Id.swift index dfd4279..edf5794 100644 --- a/Tests/JSONAPITests/Test Helpers/Entity+Id.swift +++ b/Tests/JSONAPITests/Test Helpers/Entity+Id.swift @@ -7,6 +7,6 @@ import JSONAPI -public typealias Entity = JSONAPI.Entity> +public typealias Entity = JSONAPI.Entity -public typealias NewEntity = JSONAPI.Entity> +public typealias NewEntity = JSONAPI.Entity diff --git a/Tests/JSONAPITests/XCTestManifests.swift b/Tests/JSONAPITests/XCTestManifests.swift index 2abf868..cb17f39 100644 --- a/Tests/JSONAPITests/XCTestManifests.swift +++ b/Tests/JSONAPITests/XCTestManifests.swift @@ -70,7 +70,6 @@ extension DocumentTests { extension EntityCheckTests { static let __allTests = [ ("test_failsWithBadAttribute", test_failsWithBadAttribute), - ("test_FailsWithBadId", test_FailsWithBadId), ("test_failsWithBadRelationship", test_failsWithBadRelationship), ("test_failsWithEnumAttributes", test_failsWithEnumAttributes), ("test_failsWithEnumRelationships", test_failsWithEnumRelationships),