mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-07-10 12:18:40 -07:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fc962f9a0d | |||
| 52eb123166 | |||
| 4ef147ec45 | |||
| 61074ecc69 | |||
| 4dbcff6023 | |||
| d6e82fab55 | |||
| 5fa9848f02 | |||
| f38399a1d6 | |||
| 28f664326d | |||
| 3b7ef4aeb9 | |||
| bb1ed30e89 |
@@ -67,7 +67,7 @@ Note that Playground support for importing non-system Frameworks is still a bit
|
||||
### JSONAPITestLib
|
||||
#### Entity Validator
|
||||
- [x] Disallow optional array in `Attribute` (should be empty array, not `null`).
|
||||
- [x] Only allow `TransformedAttribute` and its derivatives within `Attributes` struct.
|
||||
- [x] Only allow `TransformedAttribute` and its derivatives as stored properties within `Attributes` struct. Computed properties can still be any type because they do not get encoded or decoded.
|
||||
- [x] Only allow `ToManyRelationship` and `ToOneRelationship` within `Relationships` struct.
|
||||
|
||||
### Potential Improvements
|
||||
@@ -273,6 +273,23 @@ public var fullName: Attribute<String> {
|
||||
}
|
||||
```
|
||||
|
||||
### Copying `Entities`
|
||||
`Entity` is a value type, so copying is its default behavior. There are two common mutations you might want to make when copying an `Entity`:
|
||||
1. Assigning a new `Identifier` to the copy of an identified `Entity`.
|
||||
2. Assigning a new `Identifier` to the copy of an unidentified `Entity`.
|
||||
|
||||
The above can be accomplished with code like the following:
|
||||
|
||||
```
|
||||
// use case 1
|
||||
let person1 = person.withNewIdentifier()
|
||||
|
||||
// use case 2
|
||||
let newlyIdentifiedPerson1 = unidentifiedPerson.identified(byType: String.self)
|
||||
|
||||
let newlyIdentifiedPerson2 = unidentifiedPerson.identified(by: "2232")
|
||||
```
|
||||
|
||||
### `JSONAPI.Document`
|
||||
|
||||
The entirety of a JSON API request or response is encoded or decoded from- or to a `Document`. As an example, a JSON API response containing one `Person` and no included entities could be decoded as follows:
|
||||
|
||||
@@ -66,8 +66,13 @@ public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSON
|
||||
guard case let .errors(errors, meta: _, links: _) = self else { return nil }
|
||||
return errors
|
||||
}
|
||||
|
||||
public var data: Data? {
|
||||
guard case let .data(data) = self else { return nil }
|
||||
return data
|
||||
}
|
||||
|
||||
public var primaryData: PrimaryResourceBody? {
|
||||
public var primaryResource: PrimaryResourceBody? {
|
||||
guard case let .data(data) = self else { return nil }
|
||||
return data.primary
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ public protocol AttributeType: Codable {
|
||||
// MARK: TransformedAttribute
|
||||
/// A TransformedAttribute takes a Codable type and attempts to turn it into another type.
|
||||
public struct TransformedAttribute<RawValue: Codable, Transformer: JSONAPI.Transformer>: AttributeType where Transformer.From == RawValue {
|
||||
private let rawValue: RawValue
|
||||
let rawValue: RawValue
|
||||
|
||||
public let value: Transformer.To
|
||||
|
||||
|
||||
@@ -32,21 +32,25 @@ public protocol JSONTyped {
|
||||
static var type: String { get }
|
||||
}
|
||||
|
||||
/// An `EntityProxyDescription` is an `EntityDescription`
|
||||
/// without Codable conformance.
|
||||
public protocol EntityProxyDescription: JSONTyped {
|
||||
associatedtype Attributes: Equatable
|
||||
associatedtype Relationships: Equatable
|
||||
}
|
||||
|
||||
/// An `EntityDescription` describes a JSON API
|
||||
/// Resource Object. The Resource Object
|
||||
/// itself is encoded and decoded as an
|
||||
/// `Entity`, which gets specialized on an
|
||||
/// `EntityDescription`.
|
||||
public protocol EntityDescription: JSONTyped {
|
||||
associatedtype Attributes: JSONAPI.Attributes
|
||||
associatedtype Relationships: JSONAPI.Relationships
|
||||
}
|
||||
public protocol EntityDescription: EntityProxyDescription where Attributes: JSONAPI.Attributes, Relationships: JSONAPI.Relationships {}
|
||||
|
||||
/// EntityProxy is a protocol that can be used to create
|
||||
/// types that _act_ like Entities but cannot be encoded
|
||||
/// or decoded as Entities.
|
||||
public protocol EntityProxy: Equatable, JSONTyped {
|
||||
associatedtype Description: EntityDescription
|
||||
associatedtype Description: EntityProxyDescription
|
||||
associatedtype EntityRawIdType: JSONAPI.MaybeRawId
|
||||
|
||||
typealias Id = JSONAPI.Id<EntityRawIdType, Self>
|
||||
@@ -75,7 +79,9 @@ extension EntityProxy {
|
||||
/// EntityType is the protocol that Entity conforms to. This
|
||||
/// protocol lets other types accept any Entity as a generic
|
||||
/// specialization.
|
||||
public protocol EntityType: EntityProxy, PrimaryResource {
|
||||
public protocol EntityType: EntityProxy, PrimaryResource where Description: EntityDescription {
|
||||
associatedtype Meta: JSONAPI.Meta
|
||||
associatedtype Links: JSONAPI.Links
|
||||
}
|
||||
|
||||
public protocol IdentifiableEntityType: EntityType, Relatable where EntityRawIdType: JSONAPI.RawIdType {}
|
||||
@@ -85,6 +91,10 @@ public protocol IdentifiableEntityType: EntityType, Relatable where EntityRawIdT
|
||||
/// "Resource Object."
|
||||
/// See https://jsonapi.org/format/#document-resource-objects
|
||||
public struct Entity<Description: JSONAPI.EntityDescription, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links, EntityRawIdType: JSONAPI.MaybeRawId>: EntityType {
|
||||
|
||||
public typealias Meta = MetaType
|
||||
public typealias Links = LinksType
|
||||
|
||||
/// The `Entity`'s Id. This can be of type `Unidentified` if
|
||||
/// the entity is being created clientside and the
|
||||
/// server is being asked to create a unique Id. Otherwise,
|
||||
@@ -377,10 +387,15 @@ extension Entity where MetaType == NoMetadata, LinksType == NoLinks, EntityRawId
|
||||
public extension Entity where EntityRawIdType: JSONAPI.RawIdType {
|
||||
|
||||
/// An Entity.Pointer is a `ToOneRelationship` with no metadata or links.
|
||||
/// This is just a convenient way to reference an Entity given that
|
||||
/// This is just a convenient way to reference an Entity so that
|
||||
/// other Entities' Relationships can be built up from it.
|
||||
public typealias Pointer = ToOneRelationship<Entity, NoMetadata, NoLinks>
|
||||
|
||||
/// Entity.Pointers is a `ToManyRelationship` with no metadata or links.
|
||||
/// This is just a convenient way to reference a bunch of Entities so
|
||||
/// that other Entities' Relationships can be built up from them.
|
||||
public typealias Pointers = ToManyRelationship<Entity, NoMetadata, NoLinks>
|
||||
|
||||
/// Get a pointer to this entity that can be used as a
|
||||
/// relationship to another entity.
|
||||
public var pointer: Pointer {
|
||||
@@ -392,6 +407,27 @@ public extension Entity where EntityRawIdType: JSONAPI.RawIdType {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Identifying Unidentified Entities
|
||||
public extension Entity where EntityRawIdType == Unidentified {
|
||||
/// Create a new Entity from this one with a newly created
|
||||
/// unique Id of the given type.
|
||||
public func identified<RawIdType: CreatableRawIdType>(byType: RawIdType.Type) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
return .init(attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
|
||||
/// Create a new Entity from this one with the given Id.
|
||||
public func identified<RawIdType: JSONAPI.RawIdType>(by id: RawIdType) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
return .init(id: Entity<Description, MetaType, LinksType, RawIdType>.Identifier(rawValue: id), attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
public extension Entity where EntityRawIdType: CreatableRawIdType {
|
||||
/// Create a copy of this Entity with a new unique Id.
|
||||
public func withNewIdentifier() -> Entity {
|
||||
return Entity(attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Attribute Access
|
||||
public extension EntityProxy {
|
||||
/// Access the attribute at the given keypath. This just
|
||||
|
||||
@@ -30,6 +30,18 @@ class AttributeTests: XCTestCase {
|
||||
XCTAssertNoThrow(try TransformedAttribute<String, TestTransformer>(transformedValue: 10))
|
||||
}
|
||||
|
||||
func test_EncodedPrimitives() {
|
||||
testEncodedPrimitive(attribute: Attribute<Int>(value: 10))
|
||||
testEncodedPrimitive(attribute: Attribute<Bool>(value: false))
|
||||
testEncodedPrimitive(attribute: Attribute<Double>(value: 10.2))
|
||||
|
||||
testEncodedPrimitive(attribute: try! TransformedAttribute<Int, IntToString>(rawValue: 10))
|
||||
testEncodedPrimitive(attribute: try! TransformedAttribute<Int, IntToInt>(rawValue: 10))
|
||||
testEncodedPrimitive(attribute: try! TransformedAttribute<Int, IntToDouble>(rawValue: 10))
|
||||
testEncodedPrimitive(attribute: try! TransformedAttribute<String, TestTransformer>(rawValue: "10"))
|
||||
testEncodedPrimitive(attribute: try! TransformedAttribute<String?, OptionalToString<String>>(rawValue: "10"))
|
||||
}
|
||||
|
||||
func test_NullableIsNullIfNil() {
|
||||
struct Wrapper: Codable {
|
||||
let dummy: Attribute<String?>
|
||||
@@ -68,4 +80,28 @@ extension AttributeTests {
|
||||
return String(value)
|
||||
}
|
||||
}
|
||||
|
||||
enum IntToString: Transformer {
|
||||
public static func transform(_ from: Int) -> String {
|
||||
return String(from)
|
||||
}
|
||||
}
|
||||
|
||||
enum IntToInt: Transformer {
|
||||
public static func transform(_ from: Int) -> Int {
|
||||
return from + 100
|
||||
}
|
||||
}
|
||||
|
||||
enum IntToDouble: Transformer {
|
||||
public static func transform(_ from: Int) -> Double {
|
||||
return Double(from)
|
||||
}
|
||||
}
|
||||
|
||||
enum OptionalToString<T>: Transformer {
|
||||
public static func transform(_ from: T?) -> String {
|
||||
return String(describing: from)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@ class DocumentTests: XCTestCase {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData?.value)
|
||||
XCTAssertNil(document.body.primaryResource?.value)
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.links, NoLinks())
|
||||
XCTAssertEqual(document.apiDescription, .none)
|
||||
@@ -35,9 +35,9 @@ class DocumentTests: XCTestCase {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData?.value)
|
||||
XCTAssertNil(document.body.primaryResource?.value)
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.links, NoLinks())
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
@@ -73,7 +73,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -98,7 +98,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -123,7 +123,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.meta)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -146,7 +146,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.meta)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -171,7 +171,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -196,7 +196,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -222,7 +222,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -246,7 +246,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -271,7 +271,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -299,7 +299,7 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -327,7 +327,7 @@ extension DocumentTests {
|
||||
data: error_document_with_links)
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -353,7 +353,7 @@ extension DocumentTests {
|
||||
data: error_document_with_links_with_api_description)
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -380,7 +380,7 @@ extension DocumentTests {
|
||||
data: error_document_no_metadata)
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
|
||||
guard case let .errors(errors) = document.body else {
|
||||
@@ -403,7 +403,7 @@ extension DocumentTests {
|
||||
data: error_document_no_metadata_with_api_description)
|
||||
|
||||
XCTAssertTrue(document.body.isError)
|
||||
XCTAssertNil(document.body.primaryData)
|
||||
XCTAssertNil(document.body.primaryResource)
|
||||
XCTAssertNil(document.body.includes)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
|
||||
@@ -523,8 +523,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
}
|
||||
@@ -540,8 +540,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
@@ -558,8 +558,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value?.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value?.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
}
|
||||
@@ -575,8 +575,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value?.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value?.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
@@ -593,8 +593,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
}
|
||||
@@ -610,8 +610,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
@@ -628,8 +628,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
@@ -650,8 +650,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, NoMetadata())
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
@@ -673,8 +673,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
@@ -695,8 +695,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
@@ -726,8 +726,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
@@ -744,8 +744,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
@@ -763,8 +763,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
@@ -782,8 +782,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.includes?.count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 1)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
@@ -802,8 +802,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
XCTAssertEqual(document.body.links?.link.meta, NoMetadata())
|
||||
@@ -825,8 +825,8 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.value.id.rawValue, "1")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.value.id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.meta, TestPageMetadata(total: 70, limit: 40, offset: 10))
|
||||
XCTAssertEqual(document.body.links?.link.url, "https://website.com")
|
||||
XCTAssertEqual(document.body.links?.link.meta, NoMetadata())
|
||||
@@ -850,8 +850,8 @@ extension DocumentTests {
|
||||
let article = Article(id: Id(rawValue: "1"), attributes: .none, relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33"))), meta: .none, links: .none)
|
||||
let document = decoded(type: Document<SingleResourceBody<Poly2<Article, Author>>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, data: single_document_no_includes)
|
||||
|
||||
XCTAssertEqual(document.body.primaryData?.value[Article.self], article)
|
||||
XCTAssertNil(document.body.primaryData?.value[Author.self])
|
||||
XCTAssertEqual(document.body.primaryResource?.value[Article.self], article)
|
||||
XCTAssertNil(document.body.primaryResource?.value[Author.self])
|
||||
}
|
||||
|
||||
func test_singleDocument_PolyPrimaryResource_encode() {
|
||||
@@ -862,8 +862,8 @@ extension DocumentTests {
|
||||
let article = Article(id: Id(rawValue: "1"), attributes: .none, relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33"))), meta: .none, links: .none)
|
||||
let document = decoded(type: Document<SingleResourceBody<Poly2<Article, Author>>, NoMetadata, NoLinks, NoIncludes, TestAPIDescription, UnknownJSONAPIError>.self, data: single_document_no_includes_with_api_description)
|
||||
|
||||
XCTAssertEqual(document.body.primaryData?.value[Article.self], article)
|
||||
XCTAssertNil(document.body.primaryData?.value[Author.self])
|
||||
XCTAssertEqual(document.body.primaryResource?.value[Article.self], article)
|
||||
XCTAssertNil(document.body.primaryResource?.value[Author.self])
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
}
|
||||
|
||||
@@ -880,11 +880,11 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryData?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryData?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryData?.values[2].id.rawValue, "3")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryResource?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[2].id.rawValue, "3")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
}
|
||||
|
||||
@@ -899,11 +899,11 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryData?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryData?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryData?.values[2].id.rawValue, "3")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryResource?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[2].id.rawValue, "3")
|
||||
XCTAssertEqual(document.body.includes?.count, 0)
|
||||
XCTAssertEqual(document.apiDescription.version, "1.0")
|
||||
}
|
||||
@@ -919,11 +919,11 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryData?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryData?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryData?.values[2].id.rawValue, "3")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryResource?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[2].id.rawValue, "3")
|
||||
XCTAssertEqual(document.body.includes?.count, 3)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 3)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
@@ -942,11 +942,11 @@ extension DocumentTests {
|
||||
|
||||
XCTAssertFalse(document.body.isError)
|
||||
XCTAssertNil(document.body.errors)
|
||||
XCTAssertNotNil(document.body.primaryData)
|
||||
XCTAssertEqual(document.body.primaryData?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryData?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryData?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryData?.values[2].id.rawValue, "3")
|
||||
XCTAssertNotNil(document.body.primaryResource)
|
||||
XCTAssertEqual(document.body.primaryResource?.values.count, 3)
|
||||
XCTAssertEqual(document.body.primaryResource?.values[0].id.rawValue, "1")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[1].id.rawValue, "2")
|
||||
XCTAssertEqual(document.body.primaryResource?.values[2].id.rawValue, "3")
|
||||
XCTAssertEqual(document.body.includes?.count, 3)
|
||||
XCTAssertEqual(document.body.includes?[Author.self].count, 3)
|
||||
XCTAssertEqual(document.body.includes?[Author.self][0].id.rawValue, "33")
|
||||
|
||||
@@ -26,7 +26,10 @@ class EntityTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_optional_relationship_operator_access() {
|
||||
|
||||
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
|
||||
let entity = TestEntity9(attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: .init(entity: entity1, meta: .none, links: .none), optionalOne: .init(entity: entity1, meta: .none, links: .none), optionalNullableOne: nil, optionalMany: .init(entities: [entity1, entity1], meta: .none, links: .none)), meta: .none, links: .none)
|
||||
|
||||
XCTAssertEqual(entity ~> \.optionalOne, entity1.id)
|
||||
}
|
||||
|
||||
func test_toMany_relationship_operator_access() {
|
||||
@@ -39,7 +42,10 @@ class EntityTests: XCTestCase {
|
||||
}
|
||||
|
||||
func test_optionalToMany_relationship_opeartor_access() {
|
||||
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
|
||||
let entity = TestEntity9(attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: .init(entity: entity1, meta: .none, links: .none), optionalOne: nil, optionalNullableOne: nil, optionalMany: .init(entities: [entity1, entity1], meta: .none, links: .none)), meta: .none, links: .none)
|
||||
|
||||
XCTAssertEqual(entity ~> \.optionalMany, [entity1.id, entity1.id])
|
||||
}
|
||||
|
||||
func test_relationshipIds() {
|
||||
@@ -59,6 +65,12 @@ class EntityTests: XCTestCase {
|
||||
XCTAssertEqual(pointer.links.link1.url, "ok")
|
||||
}
|
||||
|
||||
func test_unidentifiedEntityAttributeAccess() {
|
||||
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(entity: entity1)), meta: .none, links: .none)
|
||||
@@ -73,6 +85,7 @@ class EntityTests: XCTestCase {
|
||||
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)), relationships: .none, meta: .none, links: .none))
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: nil, optionalNullableOne: nil, optionalMany: nil), meta: .none, links: .none)
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: .init(entity: nil), optionalOne: nil, optionalNullableOne: nil, optionalMany: nil), meta: .none, links: .none)
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: .init(id: nil), optionalOne: nil, optionalNullableOne: nil, optionalMany: nil), meta: .none, links: .none)
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: .init(entity: entity1, meta: .none, links: .none), optionalOne: nil, optionalNullableOne: nil, optionalMany: nil), meta: .none, links: .none)
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: entity1.pointer, optionalNullableOne: nil, optionalMany: nil), meta: .none, links: .none)
|
||||
let _ = TestEntity9(id: .init(rawValue: "9"), attributes: .none, relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: nil, optionalNullableOne: .init(entity: entity1, meta: .none, links: .none), optionalMany: nil), meta: .none, links: .none)
|
||||
@@ -88,6 +101,36 @@ class EntityTests: XCTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Identifying entity copies
|
||||
extension EntityTests {
|
||||
func test_copyIdentifiedByType() {
|
||||
let unidentifiedEntity = UnidentifiedTestEntity(attributes: .init(me: .init(value: "hello")), relationships: .none, meta: .none, links: .none)
|
||||
|
||||
let identifiedCopy = unidentifiedEntity.identified(byType: String.self)
|
||||
|
||||
XCTAssertEqual(unidentifiedEntity.attributes, identifiedCopy.attributes)
|
||||
XCTAssertEqual(unidentifiedEntity.relationships, identifiedCopy.relationships)
|
||||
}
|
||||
|
||||
func test_copyIdentifiedByValue() {
|
||||
let unidentifiedEntity = UnidentifiedTestEntity(attributes: .init(me: .init(value: "hello")), relationships: .none, meta: .none, links: .none)
|
||||
|
||||
let identifiedCopy = unidentifiedEntity.identified(by: "hello")
|
||||
|
||||
XCTAssertEqual(unidentifiedEntity.attributes, identifiedCopy.attributes)
|
||||
XCTAssertEqual(unidentifiedEntity.relationships, identifiedCopy.relationships)
|
||||
XCTAssertEqual(identifiedCopy.id, "hello")
|
||||
}
|
||||
|
||||
func test_copyWithNewId() {
|
||||
let identifiedEntity = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
|
||||
|
||||
let identifiedCopy = identifiedEntity.withNewIdentifier()
|
||||
|
||||
XCTAssertNotEqual(identifiedEntity.id, identifiedCopy.id)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Encode/Decode
|
||||
extension EntityTests {
|
||||
|
||||
@@ -98,6 +141,8 @@ extension EntityTests {
|
||||
XCTAssert(type(of: entity.relationships) == NoRelationships.self)
|
||||
XCTAssert(type(of: entity.attributes) == NoAttributes.self)
|
||||
XCTAssertNoThrow(try TestEntity1.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntityNoRelationshipsNoAttributes_encode() {
|
||||
@@ -113,6 +158,8 @@ extension EntityTests {
|
||||
|
||||
XCTAssertEqual(entity[\.floater], 123.321)
|
||||
XCTAssertNoThrow(try TestEntity5.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntityNoRelationshipsSomeAttributes_encode() {
|
||||
@@ -128,6 +175,8 @@ extension EntityTests {
|
||||
|
||||
XCTAssertEqual((entity ~> \.others).map { $0.rawValue }, ["364B3B69-4DF1-467F-B52E-B0C9E44F666E"])
|
||||
XCTAssertNoThrow(try TestEntity3.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsNoAttributes_encode() {
|
||||
@@ -143,6 +192,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.number], 992299)
|
||||
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertNoThrow(try TestEntity4.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsSomeAttributes_encode() {
|
||||
@@ -162,6 +213,8 @@ extension EntityTests {
|
||||
XCTAssertNil(entity[\.maybeHere])
|
||||
XCTAssertEqual(entity[\.maybeNull], "World")
|
||||
XCTAssertNoThrow(try TestEntity6.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_entityOneOmittedAttribute_encode() {
|
||||
@@ -177,6 +230,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.maybeHere], "World")
|
||||
XCTAssertNil(entity[\.maybeNull])
|
||||
XCTAssertNoThrow(try TestEntity6.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_entityOneNullAttribute_encode() {
|
||||
@@ -192,6 +247,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.maybeHere], "World")
|
||||
XCTAssertEqual(entity[\.maybeNull], "!")
|
||||
XCTAssertNoThrow(try TestEntity6.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_entityAllAttribute_encode() {
|
||||
@@ -208,7 +265,7 @@ extension EntityTests {
|
||||
XCTAssertNil(entity[\.maybeNull])
|
||||
XCTAssertNoThrow(try TestEntity6.check(entity))
|
||||
|
||||
print(encodable: entity)
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_entityOneNullAndOneOmittedAttribute_encode() {
|
||||
@@ -229,7 +286,7 @@ extension EntityTests {
|
||||
XCTAssertNil(entity[\.maybeHereMaybeNull])
|
||||
XCTAssertNoThrow(try TestEntity7.check(entity))
|
||||
|
||||
print(encodable: entity)
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_NullOptionalNullableAttribute_encode() {
|
||||
@@ -244,6 +301,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.here], "Hello")
|
||||
XCTAssertEqual(entity[\.maybeHereMaybeNull], "World")
|
||||
XCTAssertNoThrow(try TestEntity7.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_NonNullOptionalNullableAttribute_encode() {
|
||||
@@ -265,6 +324,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.doubleFromInt], 22.0)
|
||||
XCTAssertEqual(entity[\.nullToString], "nil")
|
||||
XCTAssertNoThrow(try TestEntity8.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_IntToString_encode() {
|
||||
@@ -299,6 +360,8 @@ extension EntityTests {
|
||||
XCTAssertNil(entity ~> \.optionalOne)
|
||||
XCTAssertEqual((entity ~> \.optionalNullableOne)?.rawValue, "1229")
|
||||
XCTAssertNoThrow(try TestEntity9.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_nullableRelationshipNotNullOrOmitted_encode() {
|
||||
@@ -314,6 +377,8 @@ extension EntityTests {
|
||||
XCTAssertEqual((entity ~> \.one).rawValue, "4459")
|
||||
XCTAssertNil(entity ~> \.optionalNullableOne)
|
||||
XCTAssertNoThrow(try TestEntity9.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_nullableRelationshipNotNull_encode() {
|
||||
@@ -329,6 +394,8 @@ extension EntityTests {
|
||||
XCTAssertEqual((entity ~> \.one).rawValue, "4459")
|
||||
XCTAssertNil(entity ~> \.optionalNullableOne)
|
||||
XCTAssertNoThrow(try TestEntity9.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_optionalNullableRelationshipNulled_encode() {
|
||||
@@ -344,6 +411,8 @@ extension EntityTests {
|
||||
XCTAssertEqual((entity ~> \.one).rawValue, "4452")
|
||||
XCTAssertNil(entity ~> \.optionalNullableOne)
|
||||
XCTAssertNoThrow(try TestEntity9.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_nullableRelationshipIsNull_encode() {
|
||||
@@ -360,6 +429,8 @@ extension EntityTests {
|
||||
XCTAssertEqual((entity ~> \.optionalMany)?[0].rawValue, "332223")
|
||||
XCTAssertNil(entity ~> \.optionalNullableOne)
|
||||
XCTAssertNoThrow(try TestEntity9.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_optionalToManyIsNotOmitted_encode() {
|
||||
@@ -377,6 +448,8 @@ extension EntityTests {
|
||||
|
||||
XCTAssertEqual((entity ~> \.selfRef).rawValue, "1")
|
||||
XCTAssertNoThrow(try TestEntity10.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_RleationshipsOfSameType_encode() {
|
||||
@@ -395,6 +468,8 @@ extension EntityTests {
|
||||
XCTAssertNil(entity[\.me])
|
||||
XCTAssertEqual(entity.id, .unidentified)
|
||||
XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntity_encode() {
|
||||
@@ -409,6 +484,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity[\.me], "unknown")
|
||||
XCTAssertEqual(entity.id, .unidentified)
|
||||
XCTAssertNoThrow(try UnidentifiedTestEntity.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntityWithAttributes_encode() {
|
||||
@@ -429,6 +506,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity.meta.x, "world")
|
||||
XCTAssertEqual(entity.meta.y, 5)
|
||||
XCTAssertNoThrow(try UnidentifiedTestEntityWithMeta.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntityWithAttributesAndMeta_encode() {
|
||||
@@ -444,6 +523,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity.id, .unidentified)
|
||||
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
|
||||
XCTAssertNoThrow(try UnidentifiedTestEntityWithLinks.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntityWithAttributesAndLinks_encode() {
|
||||
@@ -461,6 +542,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity.meta.y, 5)
|
||||
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
|
||||
XCTAssertNoThrow(try UnidentifiedTestEntityWithMetaAndLinks.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_UnidentifiedEntityWithAttributesAndMetaAndLinks_encode() {
|
||||
@@ -478,6 +561,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity.meta.x, "world")
|
||||
XCTAssertEqual(entity.meta.y, 5)
|
||||
XCTAssertNoThrow(try TestEntity4WithMeta.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsSomeAttributesWithMeta_encode() {
|
||||
@@ -494,6 +579,8 @@ extension EntityTests {
|
||||
XCTAssertEqual((entity ~> \.other).rawValue, "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF")
|
||||
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
|
||||
XCTAssertNoThrow(try TestEntity4WithLinks.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsSomeAttributesWithLinks_encode() {
|
||||
@@ -512,6 +599,8 @@ extension EntityTests {
|
||||
XCTAssertEqual(entity.meta.y, 5)
|
||||
XCTAssertEqual(entity.links.link1, .init(url: "https://image.com/image.png"))
|
||||
XCTAssertNoThrow(try TestEntity4WithMetaAndLinks.check(entity))
|
||||
|
||||
testEncoded(entity: entity)
|
||||
}
|
||||
|
||||
func test_EntitySomeRelationshipsSomeAttributesWithMetaAndLinks_encode() {
|
||||
|
||||
@@ -23,6 +23,7 @@ public class PolyProxyTests: XCTestCase {
|
||||
XCTAssertEqual(polyUserA[\.name], "Ken Moore")
|
||||
XCTAssertEqual(polyUserA.id, "1")
|
||||
XCTAssertEqual(polyUserA.relationships, .none)
|
||||
XCTAssertEqual(polyUserA[\.x], .init(x: "y"))
|
||||
}
|
||||
|
||||
func test_UserAAndBEncodeEquality() {
|
||||
@@ -57,6 +58,7 @@ public class PolyProxyTests: XCTestCase {
|
||||
XCTAssertEqual(polyUserB[\.name], "Ken Less")
|
||||
XCTAssertEqual(polyUserB.id, "2")
|
||||
XCTAssertEqual(polyUserB.relationships, .none)
|
||||
XCTAssertEqual(polyUserB[\.x], .init(x: "y"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,9 +113,9 @@ extension Poly2: EntityProxy, JSONTyped where A == PolyProxyTests.UserA, B == Po
|
||||
public var attributes: SharedUserDescription.Attributes {
|
||||
switch self {
|
||||
case .a(let a):
|
||||
return .init(name: .init(value: "\(a[\.firstName]) \(a[\.lastName])"))
|
||||
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: " ")))
|
||||
return .init(name: .init(value: b[\.name].joined(separator: " ")), x: .init(x: "y"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,14 +123,19 @@ extension Poly2: EntityProxy, JSONTyped where A == PolyProxyTests.UserA, B == Po
|
||||
return .none
|
||||
}
|
||||
|
||||
public enum SharedUserDescription: EntityDescription {
|
||||
public enum SharedUserDescription: EntityProxyDescription {
|
||||
public static var type: String { return A.type }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public struct Attributes: Equatable {
|
||||
let name: Attribute<String>
|
||||
let x: SomeRandomThingThatIsNotCodable
|
||||
}
|
||||
|
||||
public typealias Relationships = NoRelationships
|
||||
|
||||
public struct SomeRandomThingThatIsNotCodable: Equatable {
|
||||
let x: String
|
||||
}
|
||||
}
|
||||
|
||||
public typealias Description = SharedUserDescription
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// EncodedAttributeTest.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 12/21/18.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
@testable import JSONAPI
|
||||
import JSONAPITestLib
|
||||
|
||||
private struct Wrapper<Value: Equatable & Codable, Transform: Transformer>: Codable where Value == Transform.From {
|
||||
let x: TransformedAttribute<Value, Transform>
|
||||
|
||||
init(x: TransformedAttribute<Value, Transform>) {
|
||||
self.x = x
|
||||
}
|
||||
}
|
||||
|
||||
/// This function attempts to just cast to the type, so it only works
|
||||
/// for Attributes of primitive types (primitive to JSON).
|
||||
func testEncodedPrimitive<Value: Equatable & Codable, Transform: Transformer>(attribute: TransformedAttribute<Value, Transform>) {
|
||||
let encodedAttributeData = encoded(value: Wrapper<Value, Transform>(x: attribute))
|
||||
let wrapperObject = try! JSONSerialization.jsonObject(with: encodedAttributeData, options: []) as! [String: Any]
|
||||
let jsonObject = wrapperObject["x"]
|
||||
|
||||
guard let jsonAttribute = jsonObject as? Transform.From else {
|
||||
XCTFail("Attribute did not encode to the correct type")
|
||||
return
|
||||
}
|
||||
|
||||
XCTAssertEqual(attribute.rawValue, jsonAttribute)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//
|
||||
// EncodedEntityPropertyTest.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 12/21/18.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
import JSONAPITestLib
|
||||
|
||||
func testEncoded<E: EntityType>(entity: E) {
|
||||
let encodedEntityData = encoded(value: entity)
|
||||
let jsonObject = try! JSONSerialization.jsonObject(with: encodedEntityData, options: [])
|
||||
let jsonDict = jsonObject as? [String: Any]
|
||||
|
||||
XCTAssertNotNil(jsonDict)
|
||||
|
||||
let jsonId = jsonDict?["id"]
|
||||
|
||||
if E.EntityRawIdType.self == Unidentified.self {
|
||||
XCTAssertNil(jsonId)
|
||||
} else {
|
||||
XCTAssertNotNil(jsonId)
|
||||
}
|
||||
|
||||
let jsonType = jsonDict?["type"] as? String
|
||||
|
||||
XCTAssertEqual(jsonType, E.type)
|
||||
|
||||
let jsonAttributes = jsonDict?["attributes"] as? [String: Any]
|
||||
|
||||
if E.Attributes.self == NoAttributes.self {
|
||||
XCTAssertNil(jsonAttributes)
|
||||
} else {
|
||||
XCTAssertNotNil(jsonAttributes)
|
||||
}
|
||||
|
||||
let jsonRelationships = jsonDict?["relationships"] as? [String: Any]
|
||||
|
||||
if E.Relationships.self == NoRelationships.self {
|
||||
XCTAssertNil(jsonRelationships)
|
||||
} else {
|
||||
XCTAssertNotNil(jsonRelationships)
|
||||
}
|
||||
|
||||
let jsonMeta = jsonDict?["meta"] as? [String: Any]
|
||||
|
||||
if E.Meta.self == NoMetadata.self {
|
||||
XCTAssertNil(jsonMeta)
|
||||
} else {
|
||||
XCTAssertNotNil(jsonMeta)
|
||||
}
|
||||
|
||||
let jsonLinks = jsonDict?["links"] as? [String: Any]
|
||||
|
||||
if E.Links.self == NoLinks.self {
|
||||
XCTAssertNil(jsonLinks)
|
||||
} else {
|
||||
XCTAssertNotNil(jsonLinks)
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ extension AttributeTests {
|
||||
static let __allTests = [
|
||||
("test_AttributeIsTransformedAttribute", test_AttributeIsTransformedAttribute),
|
||||
("test_AttributeNonThrowingConstructor", test_AttributeNonThrowingConstructor),
|
||||
("test_EncodedPrimitives", test_EncodedPrimitives),
|
||||
("test_NullableIsEqualToNonNullableIfNotNil", test_NullableIsEqualToNonNullableIfNotNil),
|
||||
("test_NullableIsNullIfNil", test_NullableIsNullIfNil),
|
||||
("test_TransformedAttributeNoThrow", test_TransformedAttributeNoThrow),
|
||||
@@ -181,6 +182,9 @@ extension EntityCheckTests {
|
||||
|
||||
extension EntityTests {
|
||||
static let __allTests = [
|
||||
("test_copyIdentifiedByType", test_copyIdentifiedByType),
|
||||
("test_copyIdentifiedByValue", test_copyIdentifiedByValue),
|
||||
("test_copyWithNewId", test_copyWithNewId),
|
||||
("test_entityAllAttribute", test_entityAllAttribute),
|
||||
("test_entityAllAttribute_encode", test_entityAllAttribute_encode),
|
||||
("test_entityBrokenNullableOmittedAttribute", test_entityBrokenNullableOmittedAttribute),
|
||||
@@ -235,6 +239,7 @@ extension EntityTests {
|
||||
("test_toMany_relationship_operator_access", test_toMany_relationship_operator_access),
|
||||
("test_UnidentifiedEntity", test_UnidentifiedEntity),
|
||||
("test_UnidentifiedEntity_encode", test_UnidentifiedEntity_encode),
|
||||
("test_unidentifiedEntityAttributeAccess", test_unidentifiedEntityAttributeAccess),
|
||||
("test_UnidentifiedEntityWithAttributes", test_UnidentifiedEntityWithAttributes),
|
||||
("test_UnidentifiedEntityWithAttributes_encode", test_UnidentifiedEntityWithAttributes_encode),
|
||||
("test_UnidentifiedEntityWithAttributesAndLinks", test_UnidentifiedEntityWithAttributesAndLinks),
|
||||
|
||||
Reference in New Issue
Block a user