mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-07-10 12:18:40 -07:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8defe82536 | |||
| 1f83216b03 | |||
| 6e6973c170 | |||
| 4f52cc2fd1 | |||
| 35d6cbb440 | |||
| d667e91a6a |
@@ -23,8 +23,10 @@ extension String: CreatableRawIdType {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Entity typealias for convenience
|
||||
public typealias ExampleEntity<Description: EntityDescription> = Entity<Description, String>
|
||||
// MARK: - typealiases for convenience
|
||||
public typealias ExampleEntity<Description: EntityDescription> = Entity<Description, NoMetadata, NoLinks, String>
|
||||
public typealias ToOne<E: OptionalRelatable> = ToOneRelationship<E, NoMetadata, NoLinks>
|
||||
public typealias ToMany<E: Relatable> = ToManyRelationship<E, NoMetadata, NoLinks>
|
||||
|
||||
// MARK: - A few resource objects (entities)
|
||||
public enum PersonDescription: EntityDescription {
|
||||
@@ -46,11 +48,11 @@ public enum PersonDescription: EntityDescription {
|
||||
}
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
public let friends: ToManyRelationship<Person>
|
||||
public let dogs: ToManyRelationship<Dog>
|
||||
public let home: ToOneRelationship<House>
|
||||
public let friends: ToMany<Person>
|
||||
public let dogs: ToMany<Dog>
|
||||
public let home: ToOne<House>
|
||||
|
||||
public init(friends: ToManyRelationship<Person>, dogs: ToManyRelationship<Dog>, home: ToOneRelationship<House>) {
|
||||
public init(friends: ToMany<Person>, dogs: ToMany<Dog>, home: ToOne<House>) {
|
||||
self.friends = friends
|
||||
self.dogs = dogs
|
||||
self.home = home
|
||||
@@ -60,7 +62,7 @@ public enum PersonDescription: EntityDescription {
|
||||
|
||||
public typealias Person = ExampleEntity<PersonDescription>
|
||||
|
||||
public extension Entity where Description == PersonDescription, EntityRawIdType == String {
|
||||
public extension Entity where Description == PersonDescription, MetaType == NoMetadata, LinksType == NoLinks, 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)))
|
||||
}
|
||||
@@ -79,9 +81,9 @@ public enum DogDescription: EntityDescription {
|
||||
}
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
public let owner: ToOneRelationship<Person?>
|
||||
public let owner: ToOne<Person?>
|
||||
|
||||
public init(owner: ToOneRelationship<Person?>) {
|
||||
public init(owner: ToOne<Person?>) {
|
||||
self.owner = owner
|
||||
}
|
||||
}
|
||||
@@ -89,7 +91,7 @@ public enum DogDescription: EntityDescription {
|
||||
|
||||
public typealias Dog = ExampleEntity<DogDescription>
|
||||
|
||||
public extension Entity where Description == DogDescription, EntityRawIdType == String {
|
||||
public extension Entity where Description == DogDescription, MetaType == NoMetadata, LinksType == NoLinks, 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)))
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ Note that Playground support for importing non-system Frameworks is still a bit
|
||||
|
||||
#### Relationship Object
|
||||
- [x] `data`
|
||||
- [ ] `links`
|
||||
- [ ] `meta`
|
||||
- [x] `links`
|
||||
- [x] `meta`
|
||||
|
||||
#### Links Object
|
||||
- [x] `href`
|
||||
@@ -186,9 +186,11 @@ Note that I am assuming an unidentified person is a "new" person. I suspect that
|
||||
|
||||
There are two types of `Relationships`: `ToOneRelationship` and `ToManyRelationship`. An `EntityDescription`'s `Relationships` type can contain any number of `Relationship` properties of either of these types. Do not store anything other than `Relationship` properties in the `Relationships` struct of an `EntityDescription`.
|
||||
|
||||
To describe a relationship that may be omitted (i.e. the key is not even present in the JSON object), you make the entire `ToOneRelationship` or `ToManyRelationship` optional. However, this is not recommended because you can also represent optional relationships as nullable which means the key is always present. A `ToManyRelationship` can naturally represent the absence of related values with an empty array, so `ToManyRelationship` does not support nullability at all. A `ToOneRelationship` can be marked as nullable (i.e. the value might be `null` or it might be a resource identifier) like this:
|
||||
In addition to identifying entities by Id and type, `Relationships` can contain `Meta` or `Links` that follow the same rules as [`Meta`](#jsonapimeta) and [`Links`](#jsonapilinks) elsewhere in the JSON API Document.
|
||||
|
||||
To describe a relationship that may be omitted (i.e. the key is not even present in the JSON object), you make the entire `ToOneRelationship` or `ToManyRelationship` optional. However, this is not recommended because you can also represent optional relationships as nullable which means the key is always present. A `ToManyRelationship` can naturally represent the absence of related values with an empty array, so `ToManyRelationship` does not support nullability at all. A `ToOneRelationship` can be marked as nullable (i.e. the value could be either `null` or a resource identifier) like this:
|
||||
```
|
||||
let nullableRelative: ToOneRelationship<Person?>
|
||||
let nullableRelative: ToOneRelationship<Person?, NoMetadata, NoLinks>
|
||||
```
|
||||
|
||||
An entity that does not have relationships can be described by adding the following to an `EntityDescription`:
|
||||
|
||||
@@ -320,24 +320,46 @@ extension Entity where MetaType == NoMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
extension Entity 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 Entity where LinksType == NoLinks {
|
||||
public init(id: Entity.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) {
|
||||
self.init(id: id, attributes: attributes, relationships: relationships, meta: meta, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
extension Entity 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 Entity where MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public init(id: Entity.Id, attributes: Description.Attributes, relationships: Description.Relationships) {
|
||||
self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
extension Entity 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)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Pointer for Relationships use.
|
||||
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<Entity> {
|
||||
return ToOneRelationship(entity: self)
|
||||
public var pointer: ToOneRelationship<Entity, NoMetadata, NoLinks> {
|
||||
return ToOneRelationship(entity: self, meta: .none, links: .none)
|
||||
}
|
||||
|
||||
public func pointer<MType: JSONAPI.Meta, LType: JSONAPI.Links>(withMeta meta: MType, links: LType) -> ToOneRelationship<Entity, MType, LType> {
|
||||
return ToOneRelationship(entity: self, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,14 +392,14 @@ public extension EntityProxy {
|
||||
/// Access to an Id of a `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other.id`.
|
||||
public static func ~><OtherEntity: OptionalRelatable>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity>>) -> OtherEntity.WrappedIdentifier {
|
||||
public static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>>) -> OtherEntity.WrappedIdentifier {
|
||||
return entity.relationships[keyPath: path].id
|
||||
}
|
||||
|
||||
/// Access to all Ids of a `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others.ids`.
|
||||
public static func ~><OtherEntity: Relatable>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity>>) -> [OtherEntity.Identifier] {
|
||||
public static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity, MType, LType>>) -> [OtherEntity.Identifier] {
|
||||
return entity.relationships[keyPath: path].ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,30 +5,59 @@
|
||||
// Created by Mathew Polzin on 8/31/18.
|
||||
//
|
||||
|
||||
public protocol RelationshipType: Codable {}
|
||||
public protocol RelationshipType: Codable {
|
||||
associatedtype LinksType
|
||||
associatedtype MetaType
|
||||
|
||||
var links: LinksType { get }
|
||||
var meta: MetaType { get }
|
||||
}
|
||||
|
||||
/// An Entity relationship that can be encoded to or decoded from
|
||||
/// a JSON API "Resource Linkage."
|
||||
/// See https://jsonapi.org/format/#document-resource-object-linkage
|
||||
/// A convenient typealias might make your code much more legible: `One<EntityDescription>`
|
||||
public struct ToOneRelationship<Relatable: JSONAPI.OptionalRelatable>: RelationshipType, Equatable {
|
||||
public struct ToOneRelationship<Relatable: JSONAPI.OptionalRelatable, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links>: RelationshipType, Equatable {
|
||||
|
||||
public let id: Relatable.WrappedIdentifier
|
||||
|
||||
public init(id: Relatable.WrappedIdentifier) {
|
||||
public let meta: MetaType
|
||||
public let links: LinksType
|
||||
|
||||
public init(id: Relatable.WrappedIdentifier, meta: MetaType, links: LinksType) {
|
||||
self.id = id
|
||||
self.meta = meta
|
||||
self.links = links
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public init(id: Relatable.WrappedIdentifier) {
|
||||
self.init(id: id, meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier {
|
||||
public init<E: EntityType>(entity: E, meta: MetaType, links: LinksType) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
self.init(id: entity.id, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public init<E: EntityType>(entity: E) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
id = entity.id
|
||||
self.init(id: entity.id, meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier? {
|
||||
public init<E: EntityType>(entity: E?, meta: MetaType, links: LinksType) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
self.init(id: entity?.id, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Identifier?, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public init<E: EntityType>(entity: E?) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
id = entity?.id
|
||||
self.init(id: entity?.id, meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,30 +65,54 @@ extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Ident
|
||||
/// a JSON API "Resource Linkage."
|
||||
/// See https://jsonapi.org/format/#document-resource-object-linkage
|
||||
/// A convenient typealias might make your code much more legible: `Many<EntityDescription>`
|
||||
public struct ToManyRelationship<Relatable: JSONAPI.Relatable>: RelationshipType, Equatable {
|
||||
public struct ToManyRelationship<Relatable: JSONAPI.Relatable, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links>: RelationshipType, Equatable {
|
||||
|
||||
public let ids: [Relatable.Identifier]
|
||||
|
||||
public init(ids: [Relatable.Identifier]) {
|
||||
public let meta: MetaType
|
||||
public let links: LinksType
|
||||
|
||||
public init(ids: [Relatable.Identifier], meta: MetaType, links: LinksType) {
|
||||
self.ids = ids
|
||||
self.meta = meta
|
||||
self.links = links
|
||||
}
|
||||
|
||||
public init<T: JSONAPI.Relatable>(relationships: [ToOneRelationship<T>]) where T.WrappedIdentifier == Relatable.Identifier {
|
||||
public init<T: JSONAPI.Relatable>(relationships: [ToOneRelationship<T, NoMetadata, NoLinks>], meta: MetaType, links: LinksType) where T.WrappedIdentifier == Relatable.Identifier {
|
||||
ids = relationships.map { $0.id }
|
||||
self.meta = meta
|
||||
self.links = links
|
||||
}
|
||||
|
||||
private init() {
|
||||
ids = []
|
||||
public init<E: EntityType>(entities: [E], meta: MetaType, links: LinksType) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
self.init(ids: entities.map { $0.id }, meta: meta, links: links)
|
||||
}
|
||||
|
||||
private init(meta: MetaType, links: LinksType) {
|
||||
self.init(ids: [], meta: meta, links: links)
|
||||
}
|
||||
|
||||
public static var none: ToManyRelationship {
|
||||
return .init()
|
||||
public static func none(withMeta meta: MetaType, links: LinksType) -> ToManyRelationship {
|
||||
return ToManyRelationship(meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToManyRelationship {
|
||||
extension ToManyRelationship where MetaType == NoMetadata, LinksType == NoLinks {
|
||||
|
||||
public init(ids: [Relatable.Identifier]) {
|
||||
self.init(ids: ids, meta: .none, links: .none)
|
||||
}
|
||||
|
||||
public init<T: JSONAPI.Relatable>(relationships: [ToOneRelationship<T, NoMetadata, NoLinks>]) where T.WrappedIdentifier == Relatable.Identifier {
|
||||
self.init(relationships: relationships, meta: .none, links: .none)
|
||||
}
|
||||
|
||||
public static var none: ToManyRelationship {
|
||||
return .none(withMeta: .none, links: .none)
|
||||
}
|
||||
|
||||
public init<E: EntityType>(entities: [E]) where E.Description == Relatable.Description, E.Id == Relatable.Identifier {
|
||||
ids = entities.map { $0.id }
|
||||
self.init(entities: entities, meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,6 +138,8 @@ extension Optional: OptionalRelatable where Wrapped: Relatable {
|
||||
// MARK: Codable
|
||||
private enum ResourceLinkageCodingKeys: String, CodingKey {
|
||||
case data = "data"
|
||||
case meta = "meta"
|
||||
case links = "links"
|
||||
}
|
||||
private enum ResourceIdentifierCodingKeys: String, CodingKey {
|
||||
case id = "id"
|
||||
@@ -103,6 +158,18 @@ extension ToOneRelationship {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self)
|
||||
|
||||
if let noMeta = NoMetadata() as? MetaType {
|
||||
meta = noMeta
|
||||
} else {
|
||||
meta = try container.decode(MetaType.self, forKey: .meta)
|
||||
}
|
||||
|
||||
if let noLinks = NoLinks() as? LinksType {
|
||||
links = noLinks
|
||||
} else {
|
||||
links = try container.decode(LinksType.self, forKey: .links)
|
||||
}
|
||||
|
||||
// A little trickery follows. If the id is nil, the
|
||||
// container.decode(Identifier.self) will fail even if Identifier
|
||||
// is Optional. However, we can check if decoding nil
|
||||
@@ -133,6 +200,14 @@ extension ToOneRelationship {
|
||||
try container.encodeNil(forKey: .data)
|
||||
}
|
||||
|
||||
if MetaType.self != NoMetadata.self {
|
||||
try container.encode(meta, forKey: .meta)
|
||||
}
|
||||
|
||||
if LinksType.self != NoLinks.self {
|
||||
try container.encode(links, forKey: .links)
|
||||
}
|
||||
|
||||
var identifier = container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data)
|
||||
|
||||
try identifier.encode(id, forKey: .id)
|
||||
@@ -143,7 +218,19 @@ extension ToOneRelationship {
|
||||
extension ToManyRelationship {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self)
|
||||
|
||||
|
||||
if let noMeta = NoMetadata() as? MetaType {
|
||||
meta = noMeta
|
||||
} else {
|
||||
meta = try container.decode(MetaType.self, forKey: .meta)
|
||||
}
|
||||
|
||||
if let noLinks = NoLinks() as? LinksType {
|
||||
links = noLinks
|
||||
} else {
|
||||
links = try container.decode(LinksType.self, forKey: .links)
|
||||
}
|
||||
|
||||
var identifiers = try container.nestedUnkeyedContainer(forKey: .data)
|
||||
|
||||
var newIds = [Relatable.Identifier]()
|
||||
@@ -163,6 +250,15 @@ extension ToManyRelationship {
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: ResourceLinkageCodingKeys.self)
|
||||
|
||||
if MetaType.self != NoMetadata.self {
|
||||
try container.encode(meta, forKey: .meta)
|
||||
}
|
||||
|
||||
if LinksType.self != NoLinks.self {
|
||||
try container.encode(links, forKey: .links)
|
||||
}
|
||||
|
||||
var identifiers = container.nestedUnkeyedContainer(forKey: .data)
|
||||
|
||||
for id in ids {
|
||||
|
||||
@@ -45,6 +45,10 @@ extension TransformedAttribute: AttributeTypeWithOptionalArray where RawValue: O
|
||||
private protocol OptionalRelationshipType {}
|
||||
extension Optional: OptionalRelationshipType where Wrapped: RelationshipType {}
|
||||
|
||||
private protocol _RelationshipType {}
|
||||
extension ToOneRelationship: _RelationshipType {}
|
||||
extension ToManyRelationship: _RelationshipType {}
|
||||
|
||||
public extension Entity {
|
||||
public static func check(_ entity: Entity) throws {
|
||||
var problems = [EntityCheckError]()
|
||||
@@ -72,7 +76,7 @@ public extension Entity {
|
||||
}
|
||||
|
||||
for relationship in relationshipsMirror.children {
|
||||
if relationship.value as? RelationshipType == nil {
|
||||
if relationship.value as? _RelationshipType == nil {
|
||||
problems.append(.nonRelationship(named: relationship.label ?? "unnamed"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
import JSONAPI
|
||||
|
||||
extension ToOneRelationship: ExpressibleByNilLiteral where Relatable.WrappedIdentifier: ExpressibleByNilLiteral {
|
||||
extension ToOneRelationship: ExpressibleByNilLiteral where Relatable.WrappedIdentifier: ExpressibleByNilLiteral, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public init(nilLiteral: ()) {
|
||||
|
||||
self.init(id: Relatable.WrappedIdentifier(nilLiteral: ()))
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Relatable.WrappedIdentifier: ExpressibleByUnicodeScalarLiteral {
|
||||
extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Relatable.WrappedIdentifier: ExpressibleByUnicodeScalarLiteral, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public typealias UnicodeScalarLiteralType = Relatable.WrappedIdentifier.UnicodeScalarLiteralType
|
||||
|
||||
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
|
||||
@@ -22,7 +22,7 @@ extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Relatable.W
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where Relatable.WrappedIdentifier: ExpressibleByExtendedGraphemeClusterLiteral {
|
||||
extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where Relatable.WrappedIdentifier: ExpressibleByExtendedGraphemeClusterLiteral, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public typealias ExtendedGraphemeClusterLiteralType = Relatable.WrappedIdentifier.ExtendedGraphemeClusterLiteralType
|
||||
|
||||
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
|
||||
@@ -30,7 +30,7 @@ extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where R
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByStringLiteral where Relatable.WrappedIdentifier: ExpressibleByStringLiteral {
|
||||
extension ToOneRelationship: ExpressibleByStringLiteral where Relatable.WrappedIdentifier: ExpressibleByStringLiteral, MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public typealias StringLiteralType = Relatable.WrappedIdentifier.StringLiteralType
|
||||
|
||||
public init(stringLiteral value: StringLiteralType) {
|
||||
@@ -38,7 +38,7 @@ extension ToOneRelationship: ExpressibleByStringLiteral where Relatable.WrappedI
|
||||
}
|
||||
}
|
||||
|
||||
extension ToManyRelationship: ExpressibleByArrayLiteral {
|
||||
extension ToManyRelationship: ExpressibleByArrayLiteral where MetaType == NoMetadata, LinksType == NoLinks {
|
||||
public typealias ArrayLiteralElement = Relatable.Identifier
|
||||
|
||||
public init(arrayLiteral elements: ArrayLiteralElement...) {
|
||||
|
||||
@@ -10,6 +10,10 @@ import JSONAPI
|
||||
|
||||
class APIDescriptionTests: XCTestCase {
|
||||
|
||||
func test_NoDescriptionString() {
|
||||
XCTAssertEqual(String(describing: NoAPIDescription()), "No JSON:API Object")
|
||||
}
|
||||
|
||||
func test_empty() {
|
||||
let description = decoded(type: APIDescription<NoMetadata>.self, data: api_description_empty)
|
||||
|
||||
|
||||
@@ -49,9 +49,9 @@ extension ComputedPropertiesTests {
|
||||
}
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
public let other: ToOneRelationship<TestType>
|
||||
public let other: ToOneRelationship<TestType, NoMetadata, NoLinks>
|
||||
|
||||
public var computed: ToOneRelationship<TestType> {
|
||||
public var computed: ToOneRelationship<TestType, NoMetadata, NoLinks> {
|
||||
return other
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +978,7 @@ extension DocumentTests {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let author: ToOneRelationship<Author>
|
||||
let author: ToOneRelationship<Author, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,16 +41,31 @@ class EntityTests: XCTestCase {
|
||||
XCTAssertEqual(entity2.relationships.other.id, entity1.id)
|
||||
}
|
||||
|
||||
func test_pointerWithMetaAndLinks() {
|
||||
let entity = TestEntity4WithMetaAndLinks(attributes: .init(word: "hello", number: 10, array: []), relationships: .init(other: .init(id: "2")), meta: .init(x: "world", y: nil), links: .init(link1: .init(url: "ok")))
|
||||
|
||||
let pointer = entity.pointer(withMeta: TestEntityMeta(x: "world", y: nil), links: TestEntityLinks(link1: .init(url: "ok")))
|
||||
|
||||
XCTAssertEqual(pointer.id, entity.id)
|
||||
XCTAssertEqual(pointer.meta.x, "world")
|
||||
XCTAssertEqual(pointer.links.link1.url, "ok")
|
||||
}
|
||||
|
||||
func test_initialization() {
|
||||
let entity1 = TestEntity1(id: .init(rawValue: "wow"))
|
||||
let entity2 = TestEntity2(id: .init(rawValue: "cool"), relationships: .init(other: .init(entity: entity1)))
|
||||
let _ = TestEntity2(id: .init(rawValue: "cool"), attributes: .none, relationships: .init(other: .init(entity: entity1)))
|
||||
let _ = TestEntity2(id: .init(rawValue: "cool"), relationships: .init(other: .init(entity: entity1)), meta: .none)
|
||||
let _ = TestEntity3(id: .init(rawValue: "3"), relationships: .init(others: .init(ids: [.init(rawValue: "10"), .init(rawValue: "20"), entity1.id])))
|
||||
let _ = TestEntity3(id: .init(rawValue: "3"), relationships: .init(others: .none))
|
||||
let _ = TestEntity4(id: .init(rawValue: "4"), attributes: .init(word: .init(value: "hello"), number: .init(value: 10), array: .init(value: [10.2, 10.3])), relationships: .init(other: entity2.pointer))
|
||||
let _ = TestEntity5(id: .init(rawValue: "5"), attributes: .init(floater: .init(value: 10.2)))
|
||||
let _ = TestEntity6(id: .init(rawValue: "6"), attributes: .init(here: .init(value: "here"), maybeHere: nil, maybeNull: .init(value: nil)))
|
||||
let _ = TestEntity7(id: .init(rawValue: "7"), attributes: .init(here: .init(value: "hello"), maybeHereMaybeNull: .init(value: "world")))
|
||||
XCTAssertNoThrow(try TestEntity8(id: .init(rawValue: "8"), attributes: .init(string: .init(value: "hello"), int: .init(value: 10), stringFromInt: .init(rawValue: 20), plus: .init(rawValue: 30), doubleFromInt: .init(rawValue: 32), omitted: nil, nullToString: .init(rawValue: nil))))
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: nil))
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: .init(entity: nil)))
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: .init(entity: entity1, meta: .none, links: .none)))
|
||||
let e10id1 = TestEntity10.Identifier(rawValue: "hello")
|
||||
let e10id2 = TestEntity10.Id(rawValue: "world")
|
||||
let e10id3: TestEntity10.Id = "!"
|
||||
@@ -459,7 +474,7 @@ extension EntityTests {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let other: ToOneRelationship<TestEntity1>
|
||||
let other: ToOneRelationship<TestEntity1, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,7 +486,7 @@ extension EntityTests {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let others: ToManyRelationship<TestEntity1>
|
||||
let others: ToManyRelationship<TestEntity1, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -481,7 +496,7 @@ extension EntityTests {
|
||||
static var type: String { return "fourth_test_entities"}
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let other: ToOneRelationship<TestEntity2>
|
||||
let other: ToOneRelationship<TestEntity2, NoMetadata, NoLinks>
|
||||
}
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
@@ -562,9 +577,9 @@ extension EntityTests {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let one: ToOneRelationship<TestEntity1>
|
||||
let one: ToOneRelationship<TestEntity1, NoMetadata, NoLinks>
|
||||
|
||||
let nullableOne: ToOneRelationship<TestEntity1?>
|
||||
let nullableOne: ToOneRelationship<TestEntity1?, NoMetadata, NoLinks>
|
||||
|
||||
// a nullable many is not allowed. it should
|
||||
// just be an empty array.
|
||||
@@ -584,8 +599,8 @@ extension EntityTests {
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let selfRef: ToOneRelationship<TestEntity10>
|
||||
let selfRefs: ToManyRelationship<TestEntity10>
|
||||
let selfRef: ToOneRelationship<TestEntity10, NoMetadata, NoLinks>
|
||||
let selfRefs: ToManyRelationship<TestEntity10, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ extension IncludedTests {
|
||||
public static var type: String { return "test_entity2" }
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let entity1: ToOneRelationship<TestEntity>
|
||||
let entity1: ToOneRelationship<TestEntity, NoMetadata, NoLinks>
|
||||
}
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
@@ -162,8 +162,8 @@ extension IncludedTests {
|
||||
public static var type: String { return "test_entity3" }
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let entity1: ToOneRelationship<TestEntity>
|
||||
let entity2: ToManyRelationship<TestEntity2>
|
||||
let entity1: ToOneRelationship<TestEntity, NoMetadata, NoLinks>
|
||||
let entity2: ToManyRelationship<TestEntity2, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ extension IncludedTests {
|
||||
public static var type: String { return "test_entity6" }
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let entity4: ToOneRelationship<TestEntity4>
|
||||
let entity4: ToOneRelationship<TestEntity4, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ extension EntityCheckTests {
|
||||
public typealias Attributes = NoAttributes
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let x: ToOneRelationship<OkEntity>
|
||||
let x: ToOneRelationship<OkEntity, NoMetadata, NoLinks>
|
||||
let y: Id<String, OkEntity>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,16 +12,16 @@ import JSONAPITestLib
|
||||
class Relationship_LiteralTests: XCTestCase {
|
||||
|
||||
func test_NilLiteral() {
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity?>(id: nil), nil)
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity?, NoMetadata, NoLinks>(id: nil), nil)
|
||||
}
|
||||
|
||||
func test_ArrayLiteral() {
|
||||
XCTAssertEqual(ToManyRelationship<TestEntity>(ids: ["1", "2", "3"]), ["1", "2", "3"])
|
||||
XCTAssertEqual(ToManyRelationship<TestEntity, NoMetadata, NoLinks>(ids: ["1", "2", "3"]), ["1", "2", "3"])
|
||||
}
|
||||
|
||||
func test_StringLiteral() {
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity>(id: "123"), "123")
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity?>(id: "123"), "123")
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity, NoMetadata, NoLinks>(id: "123"), "123")
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity?, NoMetadata, NoLinks>(id: "123"), "123")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ extension PolyTests {
|
||||
public static var type: String { return "test_entity2" }
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let entity1: ToOneRelationship<TestEntity>
|
||||
let entity1: ToOneRelationship<TestEntity, NoMetadata, NoLinks>
|
||||
}
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
@@ -300,8 +300,8 @@ extension PolyTests {
|
||||
public static var type: String { return "test_entity3" }
|
||||
|
||||
public struct Relationships: JSONAPI.Relationships {
|
||||
let entity1: ToOneRelationship<TestEntity>
|
||||
let entity2: ToManyRelationship<TestEntity2>
|
||||
let entity1: ToOneRelationship<TestEntity, NoMetadata, NoLinks>
|
||||
let entity2: ToManyRelationship<TestEntity2, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ extension PolyTests {
|
||||
public static var type: String { return "test_entity6" }
|
||||
|
||||
struct Relationships: JSONAPI.Relationships {
|
||||
let entity4: ToOneRelationship<TestEntity4>
|
||||
let entity4: ToOneRelationship<TestEntity4, NoMetadata, NoLinks>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class RelationshipTests: XCTestCase {
|
||||
let entity2 = TestEntity1()
|
||||
let entity3 = TestEntity1()
|
||||
let entity4 = TestEntity1()
|
||||
let relationship = ToManyRelationship<TestEntity1>(entities: [entity1, entity2, entity3, entity4])
|
||||
let relationship = ToManyRelationship<TestEntity1, NoMetadata, NoLinks>(entities: [entity1, entity2, entity3, entity4])
|
||||
|
||||
XCTAssertEqual(relationship.ids.count, 4)
|
||||
XCTAssertEqual(relationship.ids, [entity1, entity2, entity3, entity4].map { $0.id })
|
||||
@@ -26,7 +26,7 @@ class RelationshipTests: XCTestCase {
|
||||
let entity2 = TestEntity1()
|
||||
let entity3 = TestEntity1()
|
||||
let entity4 = TestEntity1()
|
||||
let relationship = ToManyRelationship<TestEntity1>(relationships: [entity1.pointer, entity2.pointer, entity3.pointer, entity4.pointer])
|
||||
let relationship = ToManyRelationship<TestEntity1, NoMetadata, NoLinks>(relationships: [entity1.pointer, entity2.pointer, entity3.pointer, entity4.pointer])
|
||||
|
||||
XCTAssertEqual(relationship.ids.count, 4)
|
||||
XCTAssertEqual(relationship.ids, [entity1, entity2, entity3, entity4].map { $0.id })
|
||||
@@ -36,38 +36,118 @@ class RelationshipTests: XCTestCase {
|
||||
// MARK: - Encode/Decode
|
||||
extension RelationshipTests {
|
||||
func test_ToOneRelationship() {
|
||||
let relationship = decoded(type: ToOneRelationship<TestEntity1>.self,
|
||||
let relationship = decoded(type: ToOneRelationship<TestEntity1, NoMetadata, NoLinks>.self,
|
||||
data: to_one_relationship)
|
||||
|
||||
XCTAssertEqual(relationship.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
}
|
||||
|
||||
func test_ToOneRelationship_encode() {
|
||||
test_DecodeEncodeEquality(type: ToOneRelationship<TestEntity1>.self,
|
||||
test_DecodeEncodeEquality(type: ToOneRelationship<TestEntity1, NoMetadata, NoLinks>.self,
|
||||
data: to_one_relationship)
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithMeta() {
|
||||
let relationship = decoded(type: ToOneWithMeta.self,
|
||||
data: to_one_relationship_with_meta)
|
||||
|
||||
XCTAssertEqual(relationship.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(relationship.meta.a, "hello")
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithMeta_encode() {
|
||||
test_DecodeEncodeEquality(type: ToOneWithMeta.self,
|
||||
data: to_one_relationship_with_meta)
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithLinks() {
|
||||
let relationship = decoded(type: ToOneWithLinks.self,
|
||||
data: to_one_relationship_with_links)
|
||||
|
||||
XCTAssertEqual(relationship.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(relationship.links.b, .init(url: "world"))
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithLinks_encode() {
|
||||
test_DecodeEncodeEquality(type: ToOneWithLinks.self,
|
||||
data: to_one_relationship_with_links)
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithMetaAndLinks() {
|
||||
let relationship = decoded(type: ToOneWithMetaAndLinks.self,
|
||||
data: to_one_relationship_with_meta_and_links)
|
||||
|
||||
XCTAssertEqual(relationship.id.rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(relationship.meta.a, "hello")
|
||||
XCTAssertEqual(relationship.links.b, .init(url: "world"))
|
||||
}
|
||||
|
||||
func test_ToOneRelationshipWithMetaAndLinks_encode() {
|
||||
test_DecodeEncodeEquality(type: ToOneWithMetaAndLinks.self,
|
||||
data: to_one_relationship_with_meta_and_links)
|
||||
}
|
||||
|
||||
func test_ToManyRelationship() {
|
||||
let relationship = decoded(type: ToManyRelationship<TestEntity1>.self,
|
||||
let relationship = decoded(type: ToManyRelationship<TestEntity1, NoMetadata, NoLinks>.self,
|
||||
data: to_many_relationship)
|
||||
|
||||
XCTAssertEqual(relationship.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
}
|
||||
|
||||
func test_ToManyRelationship_encode() {
|
||||
test_DecodeEncodeEquality(type: ToManyRelationship<TestEntity1>.self,
|
||||
test_DecodeEncodeEquality(type: ToManyRelationship<TestEntity1, NoMetadata, NoLinks>.self,
|
||||
data: to_many_relationship)
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithMeta() {
|
||||
let relationship = decoded(type: ToManyWithMeta.self,
|
||||
data: to_many_relationship_with_meta)
|
||||
|
||||
XCTAssertEqual(relationship.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
XCTAssertEqual(relationship.meta.a, "hello")
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithMeta_encode() {
|
||||
test_DecodeEncodeEquality(type: ToManyWithMeta.self,
|
||||
data: to_many_relationship_with_meta)
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithLinks() {
|
||||
let relationship = decoded(type: ToManyWithLinks.self,
|
||||
data: to_many_relationship_with_links)
|
||||
|
||||
XCTAssertEqual(relationship.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
XCTAssertEqual(relationship.links.b, .init(url: "world"))
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithLinks_encode() {
|
||||
test_DecodeEncodeEquality(type: ToManyWithLinks.self,
|
||||
data: to_many_relationship_with_links)
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithMetaAndLinks() {
|
||||
let relationship = decoded(type: ToManyWithMetaAndLinks.self,
|
||||
data: to_many_relationship_with_meta_and_links)
|
||||
|
||||
XCTAssertEqual(relationship.ids.map { $0.rawValue }, ["2DF03B69-4B0A-467F-B52E-B0C9E44FCECF", "90F03B69-4DF1-467F-B52E-B0C9E44FC333", "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"])
|
||||
XCTAssertEqual(relationship.meta.a, "hello")
|
||||
XCTAssertEqual(relationship.links.b, .init(url: "world"))
|
||||
}
|
||||
|
||||
func test_ToManyRelationshipWithMetaAndLinks_encode() {
|
||||
test_DecodeEncodeEquality(type: ToManyWithMetaAndLinks.self,
|
||||
data: to_many_relationship_with_meta_and_links)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Failure tests
|
||||
extension RelationshipTests {
|
||||
func test_ToManyTypeMismatch() {
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(ToManyRelationship<TestEntity1>.self, from: to_many_relationship_type_mismatch))
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(ToManyRelationship<TestEntity1, NoMetadata, NoLinks>.self, from: to_many_relationship_type_mismatch))
|
||||
}
|
||||
|
||||
func test_ToOneTypeMismatch() {
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(ToOneRelationship<TestEntity1>.self, from: to_one_relationship_type_mismatch))
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(ToOneRelationship<TestEntity1, NoMetadata, NoLinks>.self, from: to_one_relationship_type_mismatch))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,4 +162,23 @@ extension RelationshipTests {
|
||||
}
|
||||
|
||||
typealias TestEntity1 = BasicEntity<TestEntityType1>
|
||||
|
||||
typealias ToOneWithMeta = ToOneRelationship<TestEntity1, TestMeta, NoLinks>
|
||||
|
||||
typealias ToOneWithLinks = ToOneRelationship<TestEntity1, NoMetadata, TestLinks>
|
||||
typealias ToOneWithMetaAndLinks = ToOneRelationship<TestEntity1, TestMeta, TestLinks>
|
||||
|
||||
typealias ToManyWithMeta = ToManyRelationship<TestEntity1, TestMeta, NoLinks>
|
||||
typealias ToManyWithLinks = ToManyRelationship<TestEntity1, NoMetadata, TestLinks>
|
||||
typealias ToManyWithMetaAndLinks = ToManyRelationship<TestEntity1, TestMeta, TestLinks>
|
||||
|
||||
struct TestMeta: JSONAPI.Meta {
|
||||
let a: String
|
||||
}
|
||||
|
||||
typealias TestLink = JSONAPI.Link<String, NoMetadata>
|
||||
|
||||
struct TestLinks: JSONAPI.Links {
|
||||
let b: TestLink
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,45 @@ let to_one_relationship_type_mismatch = """
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_one_relationship_with_meta = """
|
||||
{
|
||||
"data": {
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
"meta": {
|
||||
"a": "hello"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_one_relationship_with_links = """
|
||||
{
|
||||
"data": {
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
"links": {
|
||||
"b": "world"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_one_relationship_with_meta_and_links = """
|
||||
{
|
||||
"data": {
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
"meta": {
|
||||
"a": "hello"
|
||||
},
|
||||
"links": {
|
||||
"b": "world"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_many_relationship = """
|
||||
{
|
||||
"data": [
|
||||
@@ -42,6 +81,75 @@ let to_many_relationship = """
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_many_relationship_with_meta = """
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "90F03B69-4DF1-467F-B52E-B0C9E44FC333"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"a": "hello"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_many_relationship_with_links = """
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "90F03B69-4DF1-467F-B52E-B0C9E44FC333"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
}
|
||||
],
|
||||
"links": {
|
||||
"b": "world"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_many_relationship_with_meta_and_links = """
|
||||
{
|
||||
"data": [
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "90F03B69-4DF1-467F-B52E-B0C9E44FC333"
|
||||
},
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"a": "hello"
|
||||
},
|
||||
"links": {
|
||||
"b": "world"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let to_many_relationship_type_mismatch = """
|
||||
{
|
||||
"data": [
|
||||
|
||||
@@ -10,6 +10,16 @@ import JSONAPI
|
||||
|
||||
class ResourceBodyTests: XCTestCase {
|
||||
|
||||
func test_initializers() {
|
||||
let articles = [
|
||||
Article(attributes: .init(title: "hello")),
|
||||
Article(attributes: .init(title: "world"))
|
||||
]
|
||||
let _ = SingleResourceBody(entity: articles[0])
|
||||
let _ = ManyResourceBody(entities: articles)
|
||||
let _: NoResourceBody = .none
|
||||
}
|
||||
|
||||
func test_singleResourceBody() {
|
||||
let body = decoded(type: SingleResourceBody<Article>.self,
|
||||
data: single_resource_body)
|
||||
|
||||
@@ -4,6 +4,7 @@ extension APIDescriptionTests {
|
||||
static let __allTests = [
|
||||
("test_empty", test_empty),
|
||||
("test_failsMissingMeta", test_failsMissingMeta),
|
||||
("test_NoDescriptionString", test_NoDescriptionString),
|
||||
("test_WithMeta", test_WithMeta),
|
||||
("test_WithVersion", test_WithVersion),
|
||||
("test_WithVersionAndMeta", test_WithVersionAndMeta),
|
||||
@@ -195,6 +196,7 @@ extension EntityTests {
|
||||
("test_nullableRelationshipNotNull_encode", test_nullableRelationshipNotNull_encode),
|
||||
("test_NullOptionalNullableAttribute", test_NullOptionalNullableAttribute),
|
||||
("test_NullOptionalNullableAttribute_encode", test_NullOptionalNullableAttribute_encode),
|
||||
("test_pointerWithMetaAndLinks", test_pointerWithMetaAndLinks),
|
||||
("test_relationship_access", test_relationship_access),
|
||||
("test_relationship_operator_access", test_relationship_operator_access),
|
||||
("test_relationshipIds", test_relationshipIds),
|
||||
@@ -300,9 +302,21 @@ extension RelationshipTests {
|
||||
("test_initToManyWithRelationships", test_initToManyWithRelationships),
|
||||
("test_ToManyRelationship", test_ToManyRelationship),
|
||||
("test_ToManyRelationship_encode", test_ToManyRelationship_encode),
|
||||
("test_ToManyRelationshipWithLinks", test_ToManyRelationshipWithLinks),
|
||||
("test_ToManyRelationshipWithLinks_encode", test_ToManyRelationshipWithLinks_encode),
|
||||
("test_ToManyRelationshipWithMeta", test_ToManyRelationshipWithMeta),
|
||||
("test_ToManyRelationshipWithMeta_encode", test_ToManyRelationshipWithMeta_encode),
|
||||
("test_ToManyRelationshipWithMetaAndLinks", test_ToManyRelationshipWithMetaAndLinks),
|
||||
("test_ToManyRelationshipWithMetaAndLinks_encode", test_ToManyRelationshipWithMetaAndLinks_encode),
|
||||
("test_ToManyTypeMismatch", test_ToManyTypeMismatch),
|
||||
("test_ToOneRelationship", test_ToOneRelationship),
|
||||
("test_ToOneRelationship_encode", test_ToOneRelationship_encode),
|
||||
("test_ToOneRelationshipWithLinks", test_ToOneRelationshipWithLinks),
|
||||
("test_ToOneRelationshipWithLinks_encode", test_ToOneRelationshipWithLinks_encode),
|
||||
("test_ToOneRelationshipWithMeta", test_ToOneRelationshipWithMeta),
|
||||
("test_ToOneRelationshipWithMeta_encode", test_ToOneRelationshipWithMeta_encode),
|
||||
("test_ToOneRelationshipWithMetaAndLinks", test_ToOneRelationshipWithMetaAndLinks),
|
||||
("test_ToOneRelationshipWithMetaAndLinks_encode", test_ToOneRelationshipWithMetaAndLinks_encode),
|
||||
("test_ToOneTypeMismatch", test_ToOneTypeMismatch),
|
||||
]
|
||||
}
|
||||
@@ -317,6 +331,7 @@ extension Relationship_LiteralTests {
|
||||
|
||||
extension ResourceBodyTests {
|
||||
static let __allTests = [
|
||||
("test_initializers", test_initializers),
|
||||
("test_manyResourceBody", test_manyResourceBody),
|
||||
("test_manyResourceBody_encode", test_manyResourceBody_encode),
|
||||
("test_manyResourceBodyEmpty", test_manyResourceBodyEmpty),
|
||||
|
||||
Reference in New Issue
Block a user