deprecate subscript attribute accessor in favor of key path dynamic member lookup

This commit is contained in:
Mathew Polzin
2019-11-05 20:48:04 -08:00
parent 706346e3a6
commit 87271b93f9
11 changed files with 377 additions and 324 deletions
+4 -4
View File
@@ -96,7 +96,7 @@ public protocol EncodableJSONAPIDocument: Equatable, Encodable, DocumentBodyCont
/// A `CodableJSONAPIDocument` supports encoding and decoding of a JSON:API
/// compliant Document.
public protocol CodableJSONAPIDocument: EncodableJSONAPIDocument, Decodable where PrimaryResourceBody: JSONAPI.ResourceBody, IncludeType: Decodable {}
public protocol CodableJSONAPIDocument: EncodableJSONAPIDocument, Decodable where PrimaryResourceBody: JSONAPI.CodableResourceBody, IncludeType: Decodable {}
/// A JSON API Document represents the entire body
/// of a JSON API request or the entire body of
@@ -340,7 +340,7 @@ extension Document {
}
}
extension Document: Decodable, CodableJSONAPIDocument where PrimaryResourceBody: ResourceBody, IncludeType: Decodable {
extension Document: Decodable, CodableJSONAPIDocument where PrimaryResourceBody: CodableResourceBody, IncludeType: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: RootCodingKeys.self)
@@ -557,7 +557,7 @@ extension Document {
}
extension Document.ErrorDocument: Decodable, CodableJSONAPIDocument
where PrimaryResourceBody: ResourceBody, IncludeType: Decodable {
where PrimaryResourceBody: CodableResourceBody, IncludeType: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
@@ -570,7 +570,7 @@ extension Document.ErrorDocument: Decodable, CodableJSONAPIDocument
}
extension Document.SuccessDocument: Decodable, CodableJSONAPIDocument
where PrimaryResourceBody: ResourceBody, IncludeType: Decodable {
where PrimaryResourceBody: CodableResourceBody, IncludeType: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
+10 -12
View File
@@ -10,33 +10,31 @@
/// array should be used for no results).
public protocol OptionalEncodablePrimaryResource: Equatable, Encodable {}
/// An `EncodablePrimaryResource` is a `PrimaryResource` that only supports encoding.
/// This is actually more restrictave than `PrimaryResource`, which supports both encoding and
/// decoding.
/// An `EncodablePrimaryResource` is a `CodablePrimaryResource` that only supports encoding.
public protocol EncodablePrimaryResource: OptionalEncodablePrimaryResource {}
/// This protocol allows for `SingleResourceBody` to contain a `null`
/// data object where `ManyResourceBody` cannot (because an empty
/// array should be used for no results).
public protocol OptionalPrimaryResource: OptionalEncodablePrimaryResource, Decodable {}
public protocol OptionalCodablePrimaryResource: OptionalEncodablePrimaryResource, Decodable {}
/// A `PrimaryResource` is a type that can be used in the body of a JSON API
/// A `CodablePrimaryResource` is a type that can be used in the body of a JSON API
/// document as the primary resource.
public protocol PrimaryResource: EncodablePrimaryResource, OptionalPrimaryResource {}
public protocol CodablePrimaryResource: EncodablePrimaryResource, OptionalCodablePrimaryResource {}
extension Optional: OptionalEncodablePrimaryResource where Wrapped: EncodablePrimaryResource {}
extension Optional: OptionalPrimaryResource where Wrapped: PrimaryResource {}
extension Optional: OptionalCodablePrimaryResource where Wrapped: CodablePrimaryResource {}
/// An `EncodableResourceBody` is a `ResourceBody` that only supports being
/// encoded. It is actually weaker than `ResourceBody`, which supports both encoding
/// and decoding.
public protocol EncodableResourceBody: Equatable, Encodable {}
/// A ResourceBody is a representation of the body of the JSON API Document.
/// A `CodableResourceBody` is a representation of the body of the JSON:API Document.
/// It can either be one resource (which can be specified as optional or not)
/// or it can contain many resources (and array with zero or more entries).
public protocol ResourceBody: Decodable, EncodableResourceBody {}
public protocol CodableResourceBody: Decodable, EncodableResourceBody {}
/// A `ResourceBody` that has the ability to take on more primary
/// resources by appending another similarly typed `ResourceBody`.
@@ -74,7 +72,7 @@ public struct ManyResourceBody<Entity: JSONAPI.EncodablePrimaryResource>: Encoda
/// Use NoResourceBody to indicate you expect a JSON API document to not
/// contain a "data" top-level key.
public struct NoResourceBody: ResourceBody {
public struct NoResourceBody: CodableResourceBody {
public static var none: NoResourceBody { return NoResourceBody() }
}
@@ -94,7 +92,7 @@ extension SingleResourceBody {
}
}
extension SingleResourceBody: Decodable, ResourceBody where Entity: OptionalPrimaryResource {
extension SingleResourceBody: Decodable, CodableResourceBody where Entity: OptionalCodablePrimaryResource {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
@@ -119,7 +117,7 @@ extension ManyResourceBody {
}
}
extension ManyResourceBody: Decodable, ResourceBody where Entity: PrimaryResource {
extension ManyResourceBody: Decodable, CodableResourceBody where Entity: CodablePrimaryResource {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var valueAggregator = [Entity]()
+4 -4
View File
@@ -6,17 +6,17 @@
//
/// Conform a type to this protocol to indicate it can be encoded to or decoded from
/// the meta data attached to a component of a JSON API document. Different meta data
/// the meta data attached to a component of a JSON:API document. Different meta data
/// can be stored all over the place: On the root document, on a resource object, on
/// link objects, etc.
///
/// JSON API Metadata is totally open ended. It can take whatever JSON-compliant structure
/// JSON:API Metadata is totally open ended. It can take whatever JSON-compliant structure
/// the server and client agree upon.
public protocol Meta: Codable, Equatable {
}
// We make Optional a Meta if it wraps a Meta so that Metadata can be specified as
// nullable.
// We make Optional a Meta if it wraps a Meta so that
// Metadata can be specified as nullable.
extension Optional: Meta where Wrapped: Meta {}
/// Use this type when you want to specify not to encode or decode any metadata
@@ -20,7 +20,7 @@ public typealias EncodableJSONPoly = Poly & EncodablePrimaryResource
public typealias EncodablePolyWrapped = Encodable & Equatable
public typealias PolyWrapped = EncodablePolyWrapped & Decodable
extension Poly0: PrimaryResource {
extension Poly0: CodablePrimaryResource {
public init(from decoder: Decoder) throws {
throw JSONAPIEncodingError.illegalDecoding("Attempted to decode Poly0, which should represent a thing that is not expected to be found in a document.")
}
@@ -33,54 +33,54 @@ extension Poly0: PrimaryResource {
// MARK: - 1 type
extension Poly1: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped {}
extension Poly1: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped {}
extension Poly1: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped {}
// MARK: - 2 types
extension Poly2: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped {}
extension Poly2: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped {}
extension Poly2: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped {}
// MARK: - 3 types
extension Poly3: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped {}
extension Poly3: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {}
extension Poly3: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {}
// MARK: - 4 types
extension Poly4: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped {}
extension Poly4: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {}
extension Poly4: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {}
// MARK: - 5 types
extension Poly5: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped {}
extension Poly5: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {}
extension Poly5: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {}
// MARK: - 6 types
extension Poly6: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped {}
extension Poly6: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {}
extension Poly6: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {}
// MARK: - 7 types
extension Poly7: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped {}
extension Poly7: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {}
extension Poly7: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {}
// MARK: - 8 types
extension Poly8: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped {}
extension Poly8: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {}
extension Poly8: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {}
// MARK: - 9 types
extension Poly9: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped {}
extension Poly9: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {}
extension Poly9: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {}
// MARK: - 10 types
extension Poly10: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped, J: EncodablePolyWrapped {}
extension Poly10: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped {}
extension Poly10: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped {}
// MARK: - 11 types
extension Poly11: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped, J: EncodablePolyWrapped, K: EncodablePolyWrapped {}
extension Poly11: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped, K: PolyWrapped {}
extension Poly11: CodablePrimaryResource, OptionalCodablePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped, K: PolyWrapped {}
@@ -99,7 +99,7 @@ extension ResourceObjectProxy {
/// ResourceObjectType is the protocol that ResourceObject conforms to. This
/// protocol lets other types accept any ResourceObject as a generic
/// specialization.
public protocol ResourceObjectType: ResourceObjectProxy, PrimaryResource where Description: ResourceObjectDescription {
public protocol ResourceObjectType: ResourceObjectProxy, CodablePrimaryResource where Description: ResourceObjectDescription {
associatedtype Meta: JSONAPI.Meta
associatedtype Links: JSONAPI.Links
}
@@ -173,236 +173,6 @@ extension ResourceObject where EntityRawIdType == Unidentified {
}
}
/*
extension ResourceObject where Description.Attributes == NoAttributes {
public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType, links: LinksType) {
self.init(id: id, attributes: NoAttributes(), relationships: relationships, meta: meta, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata {
public init(id: ResourceObject.Id, relationships: Description.Relationships, links: LinksType) {
self.init(id: id, relationships: relationships, meta: .none, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks {
public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType) {
self.init(id: id, relationships: relationships, meta: meta, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks {
public init(id: ResourceObject.Id, relationships: Description.Relationships) {
self.init(id: id, relationships: relationships, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType: CreatableRawIdType {
public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) {
self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType {
public init(relationships: Description.Relationships, links: LinksType) {
self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(relationships: Description.Relationships, meta: MetaType) {
self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(relationships: Description.Relationships) {
self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType == Unidentified {
public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) {
self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships {
public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType, links: LinksType) {
self.init(id: id, attributes: attributes, relationships: NoRelationships(), meta: meta, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata {
public init(id: ResourceObject.Id, attributes: Description.Attributes, links: LinksType) {
self.init(id: id, attributes: attributes, meta: .none, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks {
public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType) {
self.init(id: id, attributes: attributes, meta: meta, links: .none)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks {
public init(id: ResourceObject.Id, attributes: Description.Attributes) {
self.init(id: id, attributes: attributes, meta: .none, links: .none)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, links: LinksType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, meta: MetaType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, links: LinksType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, meta: MetaType) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none)
}
}
extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes) {
self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships {
public init(id: ResourceObject.Id, meta: MetaType, links: LinksType) {
self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata {
public init(id: ResourceObject.Id, links: LinksType) {
self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks {
public init(id: ResourceObject.Id, meta: MetaType) {
self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks {
public init(id: ResourceObject.Id) {
self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType {
public init(meta: MetaType, links: LinksType) {
self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType {
public init(links: LinksType) {
self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(meta: MetaType) {
self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none)
}
}
extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init() {
self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none)
}
}
extension ResourceObject where MetaType == NoMetadata {
public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) {
self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: links)
}
}
extension ResourceObject where MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) {
self.init(attributes: attributes, relationships: relationships, meta: .none, links: links)
}
}
extension ResourceObject where MetaType == NoMetadata, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) {
self.init(attributes: attributes, relationships: relationships, meta: .none, links: links)
}
}
extension ResourceObject where LinksType == NoLinks {
public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) {
self.init(id: id, attributes: attributes, relationships: relationships, meta: meta, links: .none)
}
}
extension ResourceObject where LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) {
self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none)
}
}
extension ResourceObject where LinksType == NoLinks, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) {
self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none)
}
}
extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks {
public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships) {
self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: .none)
}
}
extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType {
public init(attributes: Description.Attributes, relationships: Description.Relationships) {
self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none)
}
}
extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified {
public init(attributes: Description.Attributes, relationships: Description.Relationships) {
self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none)
}
}
*/
// MARK: - Pointer for Relationships use
public extension ResourceObject where EntityRawIdType: JSONAPI.RawIdType {
@@ -456,6 +226,7 @@ public extension ResourceObjectProxy {
/// Access the attribute at the given keypath. This just
/// allows you to write `resourceObject[\.propertyName]` instead
/// of `resourceObject.attributes.propertyName.value`.
@available(*, deprecated, message: "This will be removed in a future version in favor of `resource.<attribute_name>` (dynamic member lookup)")
subscript<T: AttributeType>(_ path: KeyPath<Description.Attributes, T>) -> T.ValueType {
return attributes[keyPath: path].value
}
@@ -463,6 +234,7 @@ public extension ResourceObjectProxy {
/// Access the attribute at the given keypath. This just
/// allows you to write `resourceObject[\.propertyName]` instead
/// of `resourceObject.attributes.propertyName.value`.
@available(*, deprecated, message: "This will be removed in a future version in favor of `resource.<attribute_name>` (dynamic member lookup)")
subscript<T: AttributeType>(_ path: KeyPath<Description.Attributes, T?>) -> T.ValueType? {
return attributes[keyPath: path]?.value
}
@@ -470,6 +242,7 @@ public extension ResourceObjectProxy {
/// Access the attribute at the given keypath. This just
/// allows you to write `resourceObject[\.propertyName]` instead
/// of `resourceObject.attributes.propertyName.value`.
@available(*, deprecated, message: "This will be removed in a future version in favor of `resource.<attribute_name>` (dynamic member lookup)")
subscript<T: AttributeType, U>(_ path: KeyPath<Description.Attributes, T?>) -> U? where T.ValueType == U? {
// Implementation Note: Handles Transform that returns optional
// type.
@@ -517,6 +290,7 @@ public extension ResourceObjectProxy {
// MARK: Keypath Subscript Lookup
/// Access an attribute requiring a transformation on the RawValue _and_
/// a secondary transformation on this entity (self).
@available(*, deprecated, message: "This will be removed in a future version in favor of `resource.<attribute_name>` (dynamic member lookup)")
subscript<T>(_ path: KeyPath<Description.Attributes, (Self) -> T>) -> T {
return attributes[keyPath: path](self)
}
@@ -15,27 +15,46 @@ class Attribute_FunctorTests: XCTestCase {
XCTAssertNotNil(entity)
XCTAssertEqual(entity?[\.computedString], "Frankie2")
XCTAssertEqual(entity?.computedString, "Frankie2")
}
@available(*, deprecated, message: "remove next major version")
func test_mapGuaranteed_deprecated() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)), relationships: .none, meta: .none, links: .none)
XCTAssertEqual(entity?[\.computedString], "Frankie2")
}
func test_mapOptionalSuccess() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)), relationships: .none, meta: .none, links: .none)
XCTAssertNotNil(entity)
XCTAssertEqual(entity?[\.computedNumber], 22)
XCTAssertEqual(entity?.computedNumber, 22)
}
@available(*, deprecated, message: "remove next major version")
func test_mapOptionalSuccess_deprecated() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)), relationships: .none, meta: .none, links: .none)
XCTAssertEqual(entity?[\.computedNumber], 22)
}
func test_mapOptionalFailure() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.5)), relationships: .none, meta: .none, links: .none)
XCTAssertNotNil(entity)
XCTAssertNil(entity?[\.computedNumber])
XCTAssertNil(entity?.computedNumber)
}
@available(*, deprecated, message: "remove next major version")
func test_mapOptionalFailure_deprecated() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.5)), relationships: .none, meta: .none, links: .none)
XCTAssertNil(entity?[\.computedNumber])
}
}
// MARK: Test types
@@ -14,12 +14,18 @@ class ComputedPropertiesTests: XCTestCase {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity.id, "1234")
XCTAssertEqual(entity[\.name], "Sarah")
XCTAssertEqual(entity.name, "Sarah")
XCTAssertEqual(entity ~> \.other, "5678")
XCTAssertNoThrow(try TestType.check(entity))
}
@available(*, deprecated, message: "remove next major version")
func test_DecodeIgnoresComputed_deprecated() {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity[\.name], "Sarah")
}
func test_EncodeIgnoresComputed() {
test_DecodeEncodeEquality(type: TestType.self, data: computed_property_attribute)
}
@@ -27,11 +33,17 @@ class ComputedPropertiesTests: XCTestCase {
func test_ComputedAttributeAccess() {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity[\.computed], "Sarah2")
XCTAssertEqual(entity.computed, "Sarah2")
XCTAssertEqual(entity[direct: \.directSecretsOut], "shhhh")
}
@available(*, deprecated, message: "remove next major version")
func test_ComputedAttributeAccess_deprecated() {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
XCTAssertEqual(entity[\.computed], "Sarah2")
}
func test_ComputedNonAttributeAccess() {
let entity = decoded(type: TestType.self, data: computed_property_attribute)
@@ -13,13 +13,19 @@ class CustomAttributesTests: XCTestCase {
func test_customDecode() {
let entity = decoded(type: CustomAttributeEntity.self, data: customAttributeEntityData)
XCTAssertEqual(entity[\.firstName], "Cool")
XCTAssertEqual(entity.firstName, "Cool")
XCTAssertEqual(entity[\.name], "Cool Name")
XCTAssertEqual(entity.name, "Cool Name")
XCTAssertNoThrow(try CustomAttributeEntity.check(entity))
}
@available(*, deprecated, message: "remove next major version")
func test_customDecode_deprecated() {
let entity = decoded(type: CustomAttributeEntity.self, data: customAttributeEntityData)
XCTAssertEqual(entity[\.firstName], "Cool")
XCTAssertEqual(entity[\.name], "Cool Name")
}
func test_customEncode() {
test_DecodeEncodeEquality(type: CustomAttributeEntity.self,
data: customAttributeEntityData)
@@ -28,13 +34,19 @@ class CustomAttributesTests: XCTestCase {
func test_customKeysDecode() {
let entity = decoded(type: CustomKeysEntity.self, data: customAttributeEntityData)
XCTAssertEqual(entity[\.firstNameSilly], "Cool")
XCTAssertEqual(entity.firstNameSilly, "Cool")
XCTAssertEqual(entity[\.lastNameSilly], "Name")
XCTAssertEqual(entity.lastNameSilly, "Name")
XCTAssertNoThrow(try CustomKeysEntity.check(entity))
}
@available(*, deprecated, message: "remove next major version")
func test_customKeysDecode_deprecated() {
let entity = decoded(type: CustomKeysEntity.self, data: customAttributeEntityData)
XCTAssertEqual(entity[\.firstNameSilly], "Cool")
XCTAssertEqual(entity[\.lastNameSilly], "Name")
}
func test_customKeysEncode() {
test_DecodeEncodeEquality(type: CustomKeysEntity.self,
data: customAttributeEntityData)
+18 -4
View File
@@ -21,12 +21,19 @@ public class PolyProxyTests: XCTestCase {
XCTAssertEqual(polyUserA.userA, userA)
XCTAssertNil(polyUserA.userB)
XCTAssertEqual(polyUserA[\.name], "Ken Moore")
XCTAssertEqual(polyUserA.name, "Ken Moore")
XCTAssertEqual(polyUserA.id, "1")
XCTAssertEqual(polyUserA.relationships, .none)
XCTAssertEqual(polyUserA[direct: \.x], .init(x: "y"))
}
@available(*, deprecated, message: "remove next major version")
func test_UserADecode_deprecated() {
let polyUserA = decoded(type: User.self, data: poly_user_stub_1)
XCTAssertEqual(polyUserA[\.name], "Ken Moore")
}
func test_UserAAndBEncodeEquality() {
test_DecodeEncodeEquality(type: User.self, data: poly_user_stub_1)
test_DecodeEncodeEquality(type: User.self, data: poly_user_stub_2)
@@ -56,11 +63,18 @@ public class PolyProxyTests: XCTestCase {
XCTAssertEqual(polyUserB.userB, userB)
XCTAssertNil(polyUserB.userA)
XCTAssertEqual(polyUserB[\.name], "Ken Less")
XCTAssertEqual(polyUserB.name, "Ken Less")
XCTAssertEqual(polyUserB.id, "2")
XCTAssertEqual(polyUserB.relationships, .none)
XCTAssertEqual(polyUserB[direct: \.x], .init(x: "y"))
}
@available(*, deprecated, message: "remove next major version")
func test_UserBDecode_deprecated() {
let polyUserB = decoded(type: User.self, data: poly_user_stub_2)
XCTAssertEqual(polyUserB[\.name], "Ken Less")
}
}
// MARK: - Test types
@@ -114,9 +128,9 @@ extension Poly2: ResourceObjectProxy, JSONTyped where A == PolyProxyTests.UserA,
public var attributes: SharedUserDescription.Attributes {
switch self {
case .a(let a):
return .init(name: .init(value: "\(a[\.firstName]) \(a[\.lastName])"), x: .init(x: "y"))
return .init(name: .init(value: "\(a.firstName) \(a.lastName)"), x: .init(x: "y"))
case .b(let b):
return .init(name: .init(value: b[\.name].joined(separator: " ")), x: .init(x: "y"))
return .init(name: .init(value: b.name.joined(separator: " ")), x: .init(x: "y"))
}
}
@@ -69,10 +69,16 @@ class ResourceObjectTests: XCTestCase {
func test_unidentifiedEntityAttributeAccess() {
let entity = UnidentifiedTestEntity(attributes: .init(me: "hello"), relationships: .none, meta: .none, links: .none)
XCTAssertEqual(entity[\.me], "hello")
XCTAssertEqual(entity.me, "hello")
}
@available(*, deprecated, message: "remove next major version")
func test_unidentifiedEntityAttributeAccess_deprecated() {
let entity = UnidentifiedTestEntity(attributes: .init(me: "hello"), relationships: .none, meta: .none, links: .none)
XCTAssertEqual(entity[\.me], "hello")
}
func test_initialization() {
let entity1 = TestEntity1(id: .init(rawValue: "wow"), attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity2(id: .init(rawValue: "cool"), attributes: .none, relationships: .init(other: .init(resourceObject: entity1)), meta: .none, links: .none)
@@ -158,13 +164,19 @@ extension ResourceObjectTests {
XCTAssert(type(of: entity.relationships) == NoRelationships.self)
XCTAssertEqual(entity[\.floater], 123.321)
XCTAssertEqual(entity.floater, 123.321)
XCTAssertNoThrow(try TestEntity5.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_EntityNoRelationshipsSomeAttributes_deprecated() {
let entity = decoded(type: TestEntity5.self,
data: entity_no_relationships_some_attributes)
XCTAssertEqual(entity[\.floater], 123.321)
}
func test_EntityNoRelationshipsSomeAttributes_encode() {
test_DecodeEncodeEquality(type: TestEntity5.self,
data: entity_no_relationships_some_attributes)
@@ -191,9 +203,7 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity4.self,
data: entity_some_relationships_some_attributes)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity.word, "coolio")
XCTAssertEqual(entity[\.number], 992299)
XCTAssertEqual(entity.number, 992299)
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
XCTAssertNoThrow(try TestEntity4.check(entity))
@@ -201,6 +211,15 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_EntitySomeRelationshipsSomeAttributes_deprecated() {
let entity = decoded(type: TestEntity4.self,
data: entity_some_relationships_some_attributes)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity[\.number], 992299)
}
func test_EntitySomeRelationshipsSomeAttributes_encode() {
test_DecodeEncodeEquality(type: TestEntity4.self,
data: entity_some_relationships_some_attributes)
@@ -214,17 +233,24 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity6.self,
data: entity_one_omitted_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertNil(entity[\.maybeHere])
XCTAssertNil(entity.maybeHere)
XCTAssertEqual(entity[\.maybeNull], "World")
XCTAssertEqual(entity.maybeNull, "World")
XCTAssertNoThrow(try TestEntity6.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_entityOneOmittedAttribute_deprecated() {
let entity = decoded(type: TestEntity6.self,
data: entity_one_omitted_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertNil(entity[\.maybeHere])
XCTAssertEqual(entity[\.maybeNull], "World")
}
func test_entityOneOmittedAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity6.self,
data: entity_one_omitted_attribute)
@@ -234,17 +260,24 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity6.self,
data: entity_one_null_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertEqual(entity[\.maybeHere], "World")
XCTAssertEqual(entity.maybeHere, "World")
XCTAssertNil(entity[\.maybeNull])
XCTAssertNil(entity.maybeNull)
XCTAssertNoThrow(try TestEntity6.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_entityOneNullAttribute_deprecated() {
let entity = decoded(type: TestEntity6.self,
data: entity_one_null_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity[\.maybeHere], "World")
XCTAssertNil(entity[\.maybeNull])
}
func test_entityOneNullAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity6.self,
data: entity_one_null_attribute)
@@ -254,17 +287,24 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity6.self,
data: entity_all_attributes)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertEqual(entity[\.maybeHere], "World")
XCTAssertEqual(entity.maybeHere, "World")
XCTAssertEqual(entity[\.maybeNull], "!")
XCTAssertEqual(entity.maybeNull, "!")
XCTAssertNoThrow(try TestEntity6.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_entityAllAttribute_deprecated() {
let entity = decoded(type: TestEntity6.self,
data: entity_all_attributes)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity[\.maybeHere], "World")
XCTAssertEqual(entity[\.maybeNull], "!")
}
func test_entityAllAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity6.self,
data: entity_all_attributes)
@@ -274,17 +314,24 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity6.self,
data: entity_one_null_and_one_missing_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertNil(entity[\.maybeHere])
XCTAssertNil(entity.maybeHere)
XCTAssertNil(entity[\.maybeNull])
XCTAssertNil(entity.maybeNull)
XCTAssertNoThrow(try TestEntity6.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_entityOneNullAndOneOmittedAttribute_deprecated() {
let entity = decoded(type: TestEntity6.self,
data: entity_one_null_and_one_missing_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertNil(entity[\.maybeHere])
XCTAssertNil(entity[\.maybeNull])
}
func test_entityOneNullAndOneOmittedAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity6.self,
data: entity_one_null_and_one_missing_attribute)
@@ -299,15 +346,22 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity7.self,
data: entity_null_optional_nullable_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertNil(entity[\.maybeHereMaybeNull])
XCTAssertNil(entity.maybeHereMaybeNull)
XCTAssertNoThrow(try TestEntity7.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_NullOptionalNullableAttribute_deprecated() {
let entity = decoded(type: TestEntity7.self,
data: entity_null_optional_nullable_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertNil(entity[\.maybeHereMaybeNull])
}
func test_NullOptionalNullableAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity7.self,
data: entity_null_optional_nullable_attribute)
@@ -317,15 +371,22 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity7.self,
data: entity_non_null_optional_nullable_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity.here, "Hello")
XCTAssertEqual(entity[\.maybeHereMaybeNull], "World")
XCTAssertEqual(entity.maybeHereMaybeNull, "World")
XCTAssertNoThrow(try TestEntity7.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_NonNullOptionalNullableAttribute_deprecated() {
let entity = decoded(type: TestEntity7.self,
data: entity_non_null_optional_nullable_attribute)
XCTAssertEqual(entity[\.here], "Hello")
XCTAssertEqual(entity[\.maybeHereMaybeNull], "World")
}
func test_NonNullOptionalNullableAttribute_encode() {
test_DecodeEncodeEquality(type: TestEntity7.self,
data: entity_non_null_optional_nullable_attribute)
@@ -338,23 +399,30 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity8.self,
data: entity_int_to_string_attribute)
XCTAssertEqual(entity[\.string], "22")
XCTAssertEqual(entity.string, "22")
XCTAssertEqual(entity[\.int], 22)
XCTAssertEqual(entity.int, 22)
XCTAssertEqual(entity[\.stringFromInt], "22")
XCTAssertEqual(entity.stringFromInt, "22")
XCTAssertEqual(entity[\.plus], 122)
XCTAssertEqual(entity.plus, 122)
XCTAssertEqual(entity[\.doubleFromInt], 22.0)
XCTAssertEqual(entity.doubleFromInt, 22.0)
XCTAssertEqual(entity[\.nullToString], "nil")
XCTAssertEqual(entity.nullToString, "nil")
XCTAssertNoThrow(try TestEntity8.check(entity))
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_IntToString_deprecated() {
let entity = decoded(type: TestEntity8.self,
data: entity_int_to_string_attribute)
XCTAssertEqual(entity[\.string], "22")
XCTAssertEqual(entity[\.int], 22)
XCTAssertEqual(entity[\.stringFromInt], "22")
XCTAssertEqual(entity[\.plus], 122)
XCTAssertEqual(entity[\.doubleFromInt], 22.0)
XCTAssertEqual(entity[\.nullToString], "nil")
}
func test_IntToString_encode() {
test_DecodeEncodeEquality(type: TestEntity8.self,
data: entity_int_to_string_attribute)
@@ -503,7 +571,6 @@ extension ResourceObjectTests {
let entity = decoded(type: UnidentifiedTestEntity.self,
data: entity_unidentified)
XCTAssertNil(entity[\.me])
XCTAssertNil(entity.me)
XCTAssertEqual(entity.id, .unidentified)
XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity))
@@ -511,6 +578,14 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_UnidentifiedEntity_deprecated() {
let entity = decoded(type: UnidentifiedTestEntity.self,
data: entity_unidentified)
XCTAssertNil(entity[\.me])
}
func test_UnidentifiedEntity_encode() {
test_DecodeEncodeEquality(type: UnidentifiedTestEntity.self,
data: entity_unidentified)
@@ -520,7 +595,6 @@ extension ResourceObjectTests {
let entity = decoded(type: UnidentifiedTestEntity.self,
data: entity_unidentified_with_attributes)
XCTAssertEqual(entity[\.me], "unknown")
XCTAssertEqual(entity.me, "unknown")
XCTAssertEqual(entity.id, .unidentified)
XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity))
@@ -528,6 +602,14 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_UnidentifiedEntityWithAttributes_deprecated() {
let entity = decoded(type: UnidentifiedTestEntity.self,
data: entity_unidentified_with_attributes)
XCTAssertEqual(entity[\.me], "unknown")
}
func test_UnidentifiedEntityWithAttributes_encode() {
test_DecodeEncodeEquality(type: UnidentifiedTestEntity.self,
data: entity_unidentified_with_attributes)
@@ -541,7 +623,6 @@ extension ResourceObjectTests {
let entity = decoded(type: UnidentifiedTestEntityWithMeta.self,
data: entity_unidentified_with_attributes_and_meta)
XCTAssertEqual(entity[\.me], "unknown")
XCTAssertEqual(entity.me, "unknown")
XCTAssertEqual(entity.id, .unidentified)
XCTAssertEqual(entity.meta.x, "world")
@@ -551,6 +632,14 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_UnidentifiedEntityWithAttributesAndMeta_deprecated() {
let entity = decoded(type: UnidentifiedTestEntityWithMeta.self,
data: entity_unidentified_with_attributes_and_meta)
XCTAssertEqual(entity[\.me], "unknown")
}
func test_UnidentifiedEntityWithAttributesAndMeta_encode() {
test_DecodeEncodeEquality(type: UnidentifiedTestEntityWithMeta.self,
data: entity_unidentified_with_attributes_and_meta)
@@ -560,7 +649,6 @@ extension ResourceObjectTests {
let entity = decoded(type: UnidentifiedTestEntityWithLinks.self,
data: entity_unidentified_with_attributes_and_links)
XCTAssertEqual(entity[\.me], "unknown")
XCTAssertEqual(entity.me, "unknown")
XCTAssertEqual(entity.id, .unidentified)
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
@@ -569,6 +657,14 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_UnidentifiedEntityWithAttributesAndLinks_deprecated() {
let entity = decoded(type: UnidentifiedTestEntityWithLinks.self,
data: entity_unidentified_with_attributes_and_links)
XCTAssertEqual(entity[\.me], "unknown")
}
func test_UnidentifiedEntityWithAttributesAndLinks_encode() {
test_DecodeEncodeEquality(type: UnidentifiedTestEntityWithLinks.self,
data: entity_unidentified_with_attributes_and_links)
@@ -578,7 +674,6 @@ extension ResourceObjectTests {
let entity = decoded(type: UnidentifiedTestEntityWithMetaAndLinks.self,
data: entity_unidentified_with_attributes_and_meta_and_links)
XCTAssertEqual(entity[\.me], "unknown")
XCTAssertEqual(entity.me, "unknown")
XCTAssertEqual(entity.id, .unidentified)
XCTAssertEqual(entity.meta.x, "world")
@@ -589,6 +684,14 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_UnidentifiedEntityWithAttributesAndMetaAndLinks_deprecated() {
let entity = decoded(type: UnidentifiedTestEntityWithMetaAndLinks.self,
data: entity_unidentified_with_attributes_and_meta_and_links)
XCTAssertEqual(entity[\.me], "unknown")
}
func test_UnidentifiedEntityWithAttributesAndMetaAndLinks_encode() {
test_DecodeEncodeEquality(type: UnidentifiedTestEntityWithMetaAndLinks.self,
data: entity_unidentified_with_attributes_and_meta_and_links)
@@ -598,9 +701,7 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity4WithMeta.self,
data: entity_some_relationships_some_attributes_with_meta)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity.word, "coolio")
XCTAssertEqual(entity[\.number], 992299)
XCTAssertEqual(entity.number, 992299)
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
XCTAssertEqual(entity.meta.x, "world")
@@ -610,6 +711,15 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_EntitySomeRelationshipsSomeAttributesWithMeta_deprecated() {
let entity = decoded(type: TestEntity4WithMeta.self,
data: entity_some_relationships_some_attributes_with_meta)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity[\.number], 992299)
}
func test_EntitySomeRelationshipsSomeAttributesWithMeta_encode() {
test_DecodeEncodeEquality(type: TestEntity4WithMeta.self,
data: entity_some_relationships_some_attributes_with_meta)
@@ -619,9 +729,7 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity4WithLinks.self,
data: entity_some_relationships_some_attributes_with_links)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity.word, "coolio")
XCTAssertEqual(entity[\.number], 992299)
XCTAssertEqual(entity.number, 992299)
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
@@ -630,6 +738,15 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_EntitySomeRelationshipsSomeAttributesWithLinks_deprecated() {
let entity = decoded(type: TestEntity4WithLinks.self,
data: entity_some_relationships_some_attributes_with_links)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity[\.number], 992299)
}
func test_EntitySomeRelationshipsSomeAttributesWithLinks_encode() {
test_DecodeEncodeEquality(type: TestEntity4WithLinks.self,
data: entity_some_relationships_some_attributes_with_links)
@@ -639,9 +756,7 @@ extension ResourceObjectTests {
let entity = decoded(type: TestEntity4WithMetaAndLinks.self,
data: entity_some_relationships_some_attributes_with_meta_and_links)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity.word, "coolio")
XCTAssertEqual(entity[\.number], 992299)
XCTAssertEqual(entity.number, 992299)
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
XCTAssertEqual(entity.meta.x, "world")
@@ -652,6 +767,15 @@ extension ResourceObjectTests {
testEncoded(entity: entity)
}
@available(*, deprecated, message: "remove next major version")
func test_EntitySomeRelationshipsSomeAttributesWithMetaAndLinks_deprecated() {
let entity = decoded(type: TestEntity4WithMetaAndLinks.self,
data: entity_some_relationships_some_attributes_with_meta_and_links)
XCTAssertEqual(entity[\.word], "coolio")
XCTAssertEqual(entity[\.number], 992299)
}
func test_EntitySomeRelationshipsSomeAttributesWithMetaAndLinks_encode() {
test_DecodeEncodeEquality(type: TestEntity4WithMetaAndLinks.self,
data: entity_some_relationships_some_attributes_with_meta_and_links)
@@ -673,11 +797,26 @@ extension ResourceObjectTests {
meta: .none,
links: .none)
XCTAssertEqual(entity1[\.metaAttribute], true)
XCTAssertEqual(entity1.metaAttribute, true)
XCTAssertEqual(entity2[\.metaAttribute], false)
XCTAssertEqual(entity2.metaAttribute, false)
}
@available(*, deprecated, message: "remove next major version")
func test_MetaEntityAttributeAccessWorks_deprecated() {
let entity1 = TestEntityWithMetaAttribute(id: "even",
attributes: .init(),
relationships: .none,
meta: .none,
links: .none)
let entity2 = TestEntityWithMetaAttribute(id: "odd",
attributes: .init(),
relationships: .none,
meta: .none,
links: .none)
XCTAssertEqual(entity1[\.metaAttribute], true)
XCTAssertEqual(entity2[\.metaAttribute], false)
}
}
// MARK: With a Meta Relationship
@@ -31,6 +31,38 @@ class SparseFieldsetTests: XCTestCase {
XCTAssertNil(relationships)
XCTAssertEqual(attributesDict?.count, 9) // note not 10 because one value is omitted intentionally at initialization
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject.bool)
XCTAssertEqual(attributesDict?["int"] as? Int,
testEverythingObject.int)
XCTAssertEqual(attributesDict?["double"] as? Double,
testEverythingObject.double)
XCTAssertEqual(attributesDict?["string"] as? String,
testEverythingObject.string)
XCTAssertEqual((attributesDict?["nestedStruct"] as? [String: String])?["hello"],
testEverythingObject.nestedStruct.hello)
XCTAssertEqual(attributesDict?["nestedEnum"] as? String,
testEverythingObject.nestedEnum.rawValue)
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject.array)
XCTAssertNil(attributesDict?["optional"])
XCTAssertNotNil(attributesDict?["nullable"] as? NSNull)
XCTAssertNotNil(attributesDict?["optionalNullable"] as? NSNull)
}
@available(*, deprecated, message: "remove next major version")
func test_FullEncode_deprecated() {
let jsonEncoder = JSONEncoder()
let sparseWithEverything = SparseFieldset(testEverythingObject, fields: EverythingTest.Attributes.CodingKeys.allCases)
let encoded = try! jsonEncoder.encode(sparseWithEverything)
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
options: [])
let outerDict = deserialized as? [String: Any]
let attributesDict = outerDict?["attributes"] as? [String: Any]
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject[\.bool])
XCTAssertEqual(attributesDict?["int"] as? Int,
@@ -45,9 +77,6 @@ class SparseFieldsetTests: XCTestCase {
testEverythingObject[\.nestedEnum].rawValue)
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject[\.array])
XCTAssertNil(attributesDict?["optional"])
XCTAssertNotNil(attributesDict?["nullable"] as? NSNull)
XCTAssertNotNil(attributesDict?["optionalNullable"] as? NSNull)
}
func test_PartialEncode() {
@@ -71,20 +100,48 @@ class SparseFieldsetTests: XCTestCase {
XCTAssertEqual(attributesDict?.count, 3)
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject[\.bool])
testEverythingObject.bool)
XCTAssertNil(attributesDict?["int"])
XCTAssertNil(attributesDict?["double"])
XCTAssertEqual(attributesDict?["string"] as? String,
testEverythingObject[\.string])
testEverythingObject.string)
XCTAssertNil(attributesDict?["nestedStruct"])
XCTAssertNil(attributesDict?["nestedEnum"])
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject[\.array])
testEverythingObject.array)
XCTAssertNil(attributesDict?["optional"])
XCTAssertNil(attributesDict?["nullable"])
XCTAssertNil(attributesDict?["optionalNullable"])
}
@available(*, deprecated, message: "remove next major version")
func test_PartialEncode_deprecated() {
let jsonEncoder = JSONEncoder()
let sparseObject = SparseFieldset(testEverythingObject, fields: [.string, .bool, .array])
let encoded = try! jsonEncoder.encode(sparseObject)
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
options: [])
let outerDict = deserialized as? [String: Any]
let id = outerDict?["id"] as? String
let type = outerDict?["type"] as? String
let attributesDict = outerDict?["attributes"] as? [String: Any]
let relationships = outerDict?["relationships"]
XCTAssertEqual(id, testEverythingObject.id.rawValue)
XCTAssertEqual(type, EverythingTest.jsonType)
XCTAssertNil(relationships)
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject[\.bool])
XCTAssertEqual(attributesDict?["string"] as? String,
testEverythingObject[\.string])
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject[\.array])
}
func test_sparseFieldsMethod() {
let jsonEncoder = JSONEncoder()
let sparseObject = testEverythingObject.sparse(with: [.string, .bool, .array])
@@ -106,19 +163,47 @@ class SparseFieldsetTests: XCTestCase {
XCTAssertEqual(attributesDict?.count, 3)
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject[\.bool])
testEverythingObject.bool)
XCTAssertNil(attributesDict?["int"])
XCTAssertNil(attributesDict?["double"])
XCTAssertEqual(attributesDict?["string"] as? String,
testEverythingObject[\.string])
testEverythingObject.string)
XCTAssertNil(attributesDict?["nestedStruct"])
XCTAssertNil(attributesDict?["nestedEnum"])
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject[\.array])
testEverythingObject.array)
XCTAssertNil(attributesDict?["optional"])
XCTAssertNil(attributesDict?["nullable"])
XCTAssertNil(attributesDict?["optionalNullable"])
}
@available(*, deprecated, message: "remove next major version")
func test_sparseFieldsMethod_deprecated() {
let jsonEncoder = JSONEncoder()
let sparseObject = testEverythingObject.sparse(with: [.string, .bool, .array])
let encoded = try! jsonEncoder.encode(sparseObject)
let deserialized = try! JSONSerialization.jsonObject(with: encoded,
options: [])
let outerDict = deserialized as? [String: Any]
let id = outerDict?["id"] as? String
let type = outerDict?["type"] as? String
let attributesDict = outerDict?["attributes"] as? [String: Any]
let relationships = outerDict?["relationships"]
XCTAssertEqual(id, testEverythingObject.id.rawValue)
XCTAssertEqual(type, EverythingTest.jsonType)
XCTAssertNil(relationships)
XCTAssertEqual(attributesDict?["bool"] as? Bool,
testEverythingObject[\.bool])
XCTAssertEqual(attributesDict?["string"] as? String,
testEverythingObject[\.string])
XCTAssertEqual(attributesDict?["array"] as? [Bool],
testEverythingObject[\.array])
}
}
struct EverythingTestDescription: JSONAPI.ResourceObjectDescription {