Compare commits

..

15 Commits

Author SHA1 Message Date
Mathew Polzin be2530f41e Add parsing invariant structure even though I do not have a solid enough use-case to implement an invariant fully just yet. 2018-12-26 14:19:54 -08:00
Mathew Polzin fc962f9a0d Lift the constraint that Attributes and Relationships are Codable for EntityProxies. 2018-12-24 07:05:35 -08:00
Mathew Polzin 52eb123166 update documentation 2018-12-22 13:57:38 -08:00
Mathew Polzin 4ef147ec45 Update linuxmain 2018-12-22 13:49:10 -08:00
Mathew Polzin 61074ecc69 Add methods that make it easy to copy an entity with a new ID or copy an unidentified entity and give it an ID 2018-12-22 13:41:34 -08:00
Mathew Polzin 4dbcff6023 Add another way to initialize a nullable attribute to the tests 2018-12-22 13:10:05 -08:00
Mathew Polzin d6e82fab55 get id and type tests into the encoded entity test function 2018-12-21 08:53:55 -08:00
Mathew Polzin 5fa9848f02 test some attribute encoding a bit further 2018-12-21 08:45:51 -08:00
Mathew Polzin f38399a1d6 Add a bit of entity structure testing 2018-12-21 07:50:32 -08:00
Mathew Polzin 28f664326d Added a couple of tests 2018-12-12 21:05:07 -08:00
Mathew Polzin 3b7ef4aeb9 Add access to easy optional access to entire data on Document.Body 2018-12-12 20:05:29 -08:00
Mathew Polzin bb1ed30e89 Rename Document.Body.primaryData to primaryResource 2018-12-12 20:04:14 -08:00
Mathew Polzin dfdc266645 remove a bunch of convenience initializers that appeared to be giving the compiler some strife 2018-12-10 22:45:28 -08:00
Mathew Polzin 585cad0a83 Added literal initialization for nullable Attributes (TestLib) 2018-12-10 21:50:30 -08:00
Mathew Polzin 89abdd4cca fix example code in Playground 2018-12-10 21:11:48 -08:00
23 changed files with 693 additions and 168 deletions
@@ -13,7 +13,7 @@ Please enjoy these examples, but allow me the forced casting and the lack of err
// MARK: - Literal Expressibility
// The JSONAPITestLib provides literal expressibility for key types to
// make creating tests easier
let dog = Dog(id: "1234", attributes: Dog.Attributes(name: "Buddy"), relationships: Dog.Relationships(owner: nil))
let dog = Dog(id: "1234", attributes: Dog.Attributes(name: "Buddy"), relationships: Dog.Relationships(owner: nil), meta: .none, links: .none)
// MARK: - JSON API structure checking
// The JSONAPITestLib provides a `check` function for each Entity type
@@ -13,7 +13,7 @@ let dogFromCode = try! Dog(name: "Buddy", owner: nil)
typealias SingleDogDocument = JSONAPI.Document<SingleResourceBody<Dog>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>
let singleDogDocument = SingleDogDocument(body: SingleResourceBody(entity: dogFromCode))
let singleDogDocument = SingleDogDocument(apiDescription: .none, body: .init(entity: dogFromCode), includes: .none, meta: .none, links: .none)
let singleDogData = try! JSONEncoder().encode(singleDogDocument)
@@ -24,13 +24,13 @@ let dogFromData = dogResponse.body.primaryData?.value
// MARK: - Create a request or response with multiple people and dogs and houses included
let personIds = [Person.Identifier(), Person.Identifier()]
let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner: personIds[0]), Dog(name: "Travis", owner: personIds[1])]
let houses = [House(), House()]
let houses = [House(attributes: .none, relationships: .none, meta: .none, links: .none), House(attributes: .none, relationships: .none, meta: .none, links: .none)]
let people = try! [Person(id: personIds[0], name: ["Gary", "Doe"], favoriteColor: "Orange-Red", friends: [], dogs: [dogs[0], dogs[1]], home: houses[0]), Person(id: personIds[1], name: ["Elise", "Joy"], favoriteColor: "Red", friends: [], dogs: [dogs[2]], home: houses[1])]
typealias BatchPeopleDocument = JSONAPI.Document<ManyResourceBody<Person>, NoMetadata, NoLinks, Include2<Dog, House>, NoAPIDescription, UnknownJSONAPIError>
let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { BatchPeopleDocument.Include($0) }
let batchPeopleDocument = BatchPeopleDocument(body: .init(entities: people), includes: .init(values: includes))
let batchPeopleDocument = BatchPeopleDocument(apiDescription: .none, body: .init(entities: people), includes: .init(values: includes), meta: .none, links: .none)
let batchPeopleData = try! JSONEncoder().encode(batchPeopleDocument)
// MARK: - Parse a request or response body with multiple people in it and dogs and houses included
+4 -4
View File
@@ -25,7 +25,7 @@ extension String: CreatableRawIdType {
// 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 ToOne<E: Identifiable> = ToOneRelationship<E, NoMetadata, NoLinks>
public typealias ToMany<E: Relatable> = ToManyRelationship<E, NoMetadata, NoLinks>
// MARK: - A few resource objects (entities)
@@ -64,7 +64,7 @@ public typealias Person = ExampleEntity<PersonDescription>
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)))
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)), meta: .none, links: .none)
}
}
@@ -93,11 +93,11 @@ public typealias Dog = ExampleEntity<DogDescription>
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)))
self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: DogDescription.Relationships(owner: .init(entity: owner)), meta: .none, links: .none)
}
public init(name: String, owner: Person.Id) throws {
self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: .init(owner: .init(id: owner)))
self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: .init(owner: .init(id: owner)), meta: .none, links: .none)
}
}
+18 -1
View File
@@ -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:
+8 -2
View File
@@ -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
}
@@ -110,7 +115,7 @@ public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSON
self.apiDescription = apiDescription
}
}
/*
extension Document where IncludeType == NoIncludes {
public init(apiDescription: APIDescription, body: PrimaryResourceBody, meta: MetaType, links: LinksType) {
self.init(apiDescription: apiDescription, body: body, includes: .none, meta: meta, links: links)
@@ -182,6 +187,7 @@ extension Document where IncludeType == NoIncludes, MetaType == NoMetadata, Link
self.init(apiDescription: .none, body: body)
}
}
*/
extension Document {
private enum RootCodingKeys: String, CodingKey {
@@ -0,0 +1,76 @@
//
// ParsingInvariant.swift
// JSONAPI
//
// Created by Mathew Polzin on 12/24/18.
//
/// An Error produced when an invariant fails.
public enum InvariantError: Swift.Error {
case failure(description: String)
}
/// Set a reaction to a particular type of invariant failure.
/// `Warning` and `Quiet` will take a default strategy for handling
/// the invariant and parsing will not fail. `Error` will cause parsing
/// to fail due to the given invariant failing.
public protocol IReaction {
/// Perform the given Invariant strategy.
static func trigger(invariant: InvariantType.Type) throws
}
public enum Invariant {
/// Used to indicate an invariant failure shoud be considered an error.
/// Parsing will fail if an Error invariant fails.
public enum Error: IReaction {
public static func trigger(invariant: InvariantType.Type) throws {
throw InvariantError.failure(description: String(describing: invariant))
}
}
/// Used to indicate an invariant failure should be considered a warning.
/// The invariant description will be printed to the console but parsing
/// will not fail. A default strategy for addressing the invariant will
/// be taken. See the given invariant's documentation for details.
public enum Warning: IReaction {
public static func trigger(invariant: InvariantType.Type) throws {
print("**WARN** \(String(describing: invariant))")
}
}
/// Used to indicate an invariant failures should be considered inconsequential.
/// Parsing will continue and a default strategy for addressing the invariant
/// will be taken. See the given invariant's documentation for details.
public enum Quiet: IReaction {
public static func trigger(invariant: InvariantType.Type) throws {}
}
/// A strategy pairs an invariant type with the desired reaction.
public enum Strategy<IType: InvariantType, IReaction: JSONAPI.IReaction>: IStrategy {}
}
public protocol InvariantType {}
public protocol IStrategy {
associatedtype IType: InvariantType
associatedtype IReaction: JSONAPI.IReaction
}
// TODO: Does this invariant make sense? I can't actually know whether arbitrary
// Id types are "empty" so I think I started down this path without having fully
// thought through it. Perhaps there are still other obvious invariants to add
// though.
public protocol RelationshipNonEmptyIdInvariant: IStrategy where IType == Invariant.Relationships.NonEmptyId {}
extension Invariant {
public enum Relationships {
/// The Empty Id Invariant holds as long as a relationships's Id
/// is not "empty"
public enum NonEmptyId: InvariantType {}
public enum Strategies<NonEmptyId: RelationshipNonEmptyIdInvariant> {}
}
}
// Would be used like `ToOneRelationship<OtherEntity, Invariant.Relationships.Strategies<Invariant.Strategy<Invariant.Relationships.NonEmptyId, Invariant.Error>>>`
+1 -1
View File
@@ -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
+45 -7
View File
@@ -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,
@@ -143,6 +153,7 @@ extension Entity where EntityRawIdType == Unidentified {
}
}
/*
extension Entity where Description.Attributes == NoAttributes {
public init(id: Entity.Id, relationships: Description.Relationships, meta: MetaType, links: LinksType) {
self.init(id: id, attributes: NoAttributes(), relationships: relationships, meta: meta, links: links)
@@ -370,15 +381,21 @@ extension Entity where MetaType == NoMetadata, LinksType == NoLinks, EntityRawId
self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none)
}
}
*/
// MARK: Pointer for Relationships use.
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 {
@@ -390,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
@@ -39,6 +39,14 @@ extension TransformedAttribute: ExpressibleByFloatLiteral where RawValue: Expres
}
}
extension Optional: ExpressibleByFloatLiteral where Wrapped: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Wrapped.FloatLiteralType
public init(floatLiteral value: FloatLiteralType) {
self = .some(Wrapped(floatLiteral: value))
}
}
extension TransformedAttribute: ExpressibleByBooleanLiteral where RawValue: ExpressibleByBooleanLiteral, Transformer == IdentityTransformer<RawValue> {
public typealias BooleanLiteralType = RawValue.BooleanLiteralType
@@ -47,6 +55,14 @@ extension TransformedAttribute: ExpressibleByBooleanLiteral where RawValue: Expr
}
}
extension Optional: ExpressibleByBooleanLiteral where Wrapped: ExpressibleByBooleanLiteral {
public typealias BooleanLiteralType = Wrapped.BooleanLiteralType
public init(booleanLiteral value: BooleanLiteralType) {
self = .some(Wrapped(booleanLiteral: value))
}
}
extension TransformedAttribute: ExpressibleByIntegerLiteral where RawValue: ExpressibleByIntegerLiteral, Transformer == IdentityTransformer<RawValue> {
public typealias IntegerLiteralType = RawValue.IntegerLiteralType
@@ -55,6 +71,14 @@ extension TransformedAttribute: ExpressibleByIntegerLiteral where RawValue: Expr
}
}
extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Wrapped.IntegerLiteralType
public init(integerLiteral value: IntegerLiteralType) {
self = .some(Wrapped(integerLiteral: value))
}
}
// regretably, array and dictionary literals are not so easy because Dictionaries and Arrays
// cannot be turned back into variadic arguments to pass onto the RawValue type's constructor.
@@ -79,6 +103,16 @@ extension TransformedAttribute: ExpressibleByDictionaryLiteral where RawValue: D
}
}
extension Optional: DictionaryType where Wrapped: DictionaryType {
public typealias Key = Wrapped.Key
public typealias Value = Wrapped.Value
public init<S>(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary<Key, Value>.Value, Dictionary<Key, Value>.Value) throws -> Dictionary<Key, Value>.Value) rethrows where S : Sequence, S.Element == (Key, Value) {
self = try .some(Wrapped(keysAndValues, uniquingKeysWith: combine))
}
}
public protocol ArrayType {
associatedtype Element
@@ -94,3 +128,11 @@ extension TransformedAttribute: ExpressibleByArrayLiteral where RawValue: ArrayT
self.init(value: RawValue(elements))
}
}
extension Optional: ArrayType where Wrapped: ArrayType {
public typealias Element = Wrapped.Element
public init<S>(_ s: S) where Element == S.Element, S : Sequence {
self = .some(Wrapped(s))
}
}
@@ -11,7 +11,7 @@ import JSONAPITestLib
class Attribute_FunctorTests: XCTestCase {
func test_mapGuaranteed() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)))
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)), relationships: .none, meta: .none, links: .none)
XCTAssertNotNil(entity)
@@ -19,7 +19,7 @@ class Attribute_FunctorTests: XCTestCase {
}
func test_mapOptionalSuccess() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)))
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.0)), relationships: .none, meta: .none, links: .none)
XCTAssertNotNil(entity)
@@ -27,7 +27,7 @@ class Attribute_FunctorTests: XCTestCase {
}
func test_mapOptionalFailure() {
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.5)))
let entity = try? TestType(attributes: .init(name: "Frankie", number: .init(rawValue: 22.5)), relationships: .none, meta: .none, links: .none)
XCTAssertNotNil(entity)
@@ -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)
}
}
}
+76 -76
View File
@@ -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())
@@ -847,11 +847,11 @@ extension DocumentTests {
// MARK: Poly PrimaryResource Tests
extension DocumentTests {
func test_singleDocument_PolyPrimaryResource() {
let article = Article(id: Id(rawValue: "1"), relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33"))))
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() {
@@ -859,11 +859,11 @@ extension DocumentTests {
}
func test_singleDocument_PolyPrimaryResourceWithAPIDescription() {
let article = Article(id: Id(rawValue: "1"), relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33"))))
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")
+124 -35
View File
@@ -12,39 +12,45 @@ import JSONAPITestLib
class EntityTests: XCTestCase {
func test_relationship_access() {
let entity1 = TestEntity1()
let entity2 = TestEntity2(relationships: .init(other: entity1.pointer))
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity2(attributes: .none, relationships: .init(other: entity1.pointer), meta: .none, links: .none)
XCTAssertEqual(entity2.relationships.other, entity1.pointer)
}
func test_relationship_operator_access() {
let entity1 = TestEntity1()
let entity2 = TestEntity2(relationships: .init(other: entity1.pointer))
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity2(attributes: .none, relationships: .init(other: entity1.pointer), meta: .none, links: .none)
XCTAssertEqual(entity2 ~> \.other, entity1.id)
}
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() {
let entity1 = TestEntity1()
let entity2 = TestEntity1()
let entity4 = TestEntity1()
let entity3 = TestEntity3(relationships: .init(others: .init(pointers: [entity1.pointer, entity2.pointer, entity4.pointer])))
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity4 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity3 = TestEntity3(attributes: .none, relationships: .init(others: .init(pointers: [entity1.pointer, entity2.pointer, entity4.pointer])), meta: .none, links: .none)
XCTAssertEqual(entity3 ~> \.others, [entity1.id, entity2.id, entity4.id])
}
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() {
let entity1 = TestEntity1()
let entity2 = TestEntity2(relationships: .init(other: entity1.pointer))
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity2(attributes: .none, relationships: .init(other: entity1.pointer), meta: .none, links: .none)
XCTAssertEqual(entity2.relationships.other.id, entity1.id)
}
@@ -59,32 +65,69 @@ 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"))
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, optionalOne: nil, optionalNullableOne: nil, optionalMany: nil))
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: .init(entity: nil), optionalOne: nil, optionalNullableOne: nil, optionalMany: nil))
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: .init(entity: entity1, meta: .none, links: .none), optionalOne: nil, optionalNullableOne: nil, optionalMany: nil))
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: entity1.pointer, optionalNullableOne: nil, optionalMany: nil))
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: nil, optionalNullableOne: .init(entity: entity1, meta: .none, links: .none), optionalMany: nil))
let _ = TestEntity9(id: .init(rawValue: "9"), relationships: .init(one: entity1.pointer, nullableOne: nil, optionalOne: nil, optionalNullableOne: .init(entity: entity1, meta: .none, links: .none), optionalMany: .init(entities: [], meta: .none, links: .none)))
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)
let _ = TestEntity2(id: .init(rawValue: "cool"), attributes: .none, relationships: .init(other: .init(entity: entity1)), meta: .none, links: .none)
let _ = TestEntity2(id: .init(rawValue: "cool"), attributes: .none, relationships: .init(other: .init(entity: entity1)), meta: .none, links: .none)
let _ = TestEntity3(id: .init(rawValue: "3"), attributes: .none, relationships: .init(others: .init(ids: [.init(rawValue: "10"), .init(rawValue: "20"), entity1.id])), meta: .none, links: .none)
let _ = TestEntity3(id: .init(rawValue: "3"), attributes: .none, relationships: .init(others: .none), meta: .none, links: .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), meta: .none, links: .none)
let _ = TestEntity5(id: .init(rawValue: "5"), attributes: .init(floater: .init(value: 10.2)), relationships: .none, meta: .none, links: .none)
let _ = TestEntity6(id: .init(rawValue: "6"), attributes: .init(here: .init(value: "here"), maybeHere: nil, maybeNull: .init(value: nil)), relationships: .none, meta: .none, links: .none)
let _ = TestEntity7(id: .init(rawValue: "7"), attributes: .init(here: .init(value: "hello"), maybeHereMaybeNull: .init(value: "world")), relationships: .none, meta: .none, links: .none)
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)
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: .init(entities: [], meta: .none, links: .none)), meta: .none, links: .none)
let e10id1 = TestEntity10.Identifier(rawValue: "hello")
let e10id2 = TestEntity10.Id(rawValue: "world")
let e10id3: TestEntity10.Id = "!"
let _ = TestEntity10(id: .init(rawValue: "10"), relationships: .init(selfRef: .init(id: e10id1), selfRefs: .init(ids: [e10id2, e10id3])))
XCTAssertNoThrow(try TestEntity11(id: .init(rawValue: "11"), attributes: .init(number: .init(rawValue: 11))))
let _ = UnidentifiedTestEntity(attributes: .init(me: .init(value: "hello")))
let _ = UnidentifiedTestEntityWithMeta(attributes: .init(me: .init(value: "hello")), meta: .init(x: "world", y: nil))
let _ = UnidentifiedTestEntityWithLinks(attributes: .init(me: .init(value: "hello")), links: .init(link1: .init(url: "hmmm")))
let _ = TestEntity10(id: .init(rawValue: "10"), attributes: .none, relationships: .init(selfRef: .init(id: e10id1), selfRefs: .init(ids: [e10id2, e10id3])), meta: .none, links: .none)
XCTAssertNoThrow(try TestEntity11(id: .init(rawValue: "11"), attributes: .init(number: .init(rawValue: 11)), relationships: .none, meta: .none, links: .none))
let _ = UnidentifiedTestEntity(attributes: .init(me: .init(value: "hello")), relationships: .none, meta: .none, links: .none)
let _ = UnidentifiedTestEntityWithMeta(attributes: .init(me: .init(value: "hello")), relationships: .none, meta: .init(x: "world", y: nil), links: .none)
let _ = UnidentifiedTestEntityWithLinks(attributes: .init(me: .init(value: "hello")), relationships: .none, meta: .none, links: .init(link1: .init(url: "hmmm")))
}
}
// 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)
}
}
@@ -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() {
@@ -15,28 +15,121 @@ class Attribute_LiteralTests: XCTestCase {
XCTAssertEqual(Attribute<String>(value: "hello"), "hello")
}
func test_NullableStringLiteral() {
XCTAssertEqual(Attribute<String?>(value: "world"), "world")
}
func test_OptionalStringLiteral() {
let x: Attribute<String>? = .init(value: "ok")
XCTAssertEqual(x, "ok")
}
func test_NullableOptionalStringLiteral() {
let x: Attribute<String?>? = .init(value: "hello")
XCTAssertEqual(x, "hello")
}
func test_BooleanLiteral() {
XCTAssertEqual(Attribute<Bool>(value: false), false)
}
func test_NullableBooleanLiteral() {
XCTAssertEqual(Attribute<Bool?>(value: true), true)
}
func test_OptionalBooleanLiteral() {
let x: Attribute<Bool>? = .init(value: false)
XCTAssertEqual(x, false)
}
func test_NullableOptionalBooleanLiteral() {
let x: Attribute<Bool?>? = .init(value: true)
XCTAssertEqual(x, true)
}
func test_IntegerLiteral() {
XCTAssertEqual(Attribute<Int>(value: 12), 12)
}
func test_NullableIntegerLiteral() {
XCTAssertEqual(Attribute<Int?>(value: 13), 13)
}
func test_OptionalIntegerLiteral() {
let x: Attribute<Int>? = .init(value: 14)
XCTAssertEqual(x, 14)
}
func test_NullableOptionalIntegerLiteral() {
let x: Attribute<Int?>? = .init(value: 15)
XCTAssertEqual(x, 15)
}
func test_FloatLiteral() {
XCTAssertEqual(Attribute<Float>(value: 1.2), 1.2)
XCTAssertEqual(Attribute<Double>(value: 1.2), 1.2)
}
func test_NullableFloatLiteral() {
XCTAssertEqual(Attribute<Float?>(value: 2.3), 2.3)
XCTAssertEqual(Attribute<Double?>(value: 3.4), 3.4)
}
func test_OptionalFloatLiteral() {
let x: Attribute<Float>? = .init(value: 2.3)
let y: Attribute<Double>? = .init(value: 3.4)
XCTAssertEqual(x, 2.3)
XCTAssertEqual(y, 3.4)
}
func test_NullableOptionalFloatLiteral() {
let x: Attribute<Float?>? = .init(value: 2.3)
let y: Attribute<Double?>? = .init(value: 3.4)
XCTAssertEqual(x, 2.3)
XCTAssertEqual(y, 3.4)
}
func test_ArrayLiteral() {
XCTAssertEqual(Attribute<[String]>(value: ["hello", "world"]), ["hello", "world"])
}
func test_NullableArrayLiteral() {
XCTAssertEqual(Attribute<[String]?>(value: ["hello", "world"]), ["hello", "world"])
}
func test_OptionalArrayLiteral() {
let x: Attribute<[String]>? = .init(value: ["hello", "world"])
XCTAssertEqual(x, ["hello", "world"])
}
func test_NullableOptionalArrayLiteral() {
let x: Attribute<[String]?>? = .init(value: ["hello", "world"])
XCTAssertEqual(x, ["hello", "world"])
}
func test_DictionaryLiteral() {
XCTAssertEqual(Attribute<[String : Int]>(value: ["hello": 1]), ["hello": 1])
}
func test_NullableDictionaryLiteral() {
XCTAssertEqual(Attribute<[String: Int]?>(value: ["hello": 1]), ["hello": 1])
}
func test_OptionalDictionaryLiteral() {
let x: Attribute<[String: Int]>? = .init(value: ["hello": 1])
XCTAssertEqual(x, ["hello": 1])
}
func test_NullableOptionalDictionaryLiteral() {
let x: Attribute<[String: Int]?>? = .init(value: ["hello": 1])
XCTAssertEqual(x, ["hello": 1])
}
func test_NilLiteral() {
XCTAssertEqual(Attribute<String?>(value: nil), nil)
}
func test_OptionalNilLiteral() {
let _: Attribute<String?>? = nil
}
}
@@ -13,27 +13,27 @@ import JSONAPITestLib
// in this file.
class EntityCheckTests: XCTestCase {
func test_failsWithEnumAttributes() {
let entity = EnumAttributesEntity(attributes: .hello)
let entity = EnumAttributesEntity(attributes: .hello, relationships: .none, meta: .none, links: .none)
XCTAssertThrowsError(try EnumAttributesEntity.check(entity))
}
func test_failsWithEnumRelationships() {
let entity = EnumRelationshipsEntity(relationships: .hello)
let entity = EnumRelationshipsEntity(attributes: .none, relationships: .hello, meta: .none, links: .none)
XCTAssertThrowsError(try EnumRelationshipsEntity.check(entity))
}
func test_failsWithBadAttribute() {
let entity = BadAttributeEntity(attributes: .init(x: "ok", y: "not ok"))
let entity = BadAttributeEntity(attributes: .init(x: "ok", y: "not ok"), relationships: .none, meta: .none, links: .none)
XCTAssertThrowsError(try BadAttributeEntity.check(entity))
}
func test_failsWithBadRelationship() {
let entity = BadRelationshipEntity(relationships: .init(x: OkEntity().pointer, y: OkEntity().id))
let entity = BadRelationshipEntity(attributes: .none, relationships: .init(x: OkEntity(attributes: .none, relationships: .none, meta: .none, links: .none).pointer, y: OkEntity(attributes: .none, relationships: .none, meta: .none, links: .none).id), meta: .none, links: .none)
XCTAssertThrowsError(try BadRelationshipEntity.check(entity))
}
func test_failsWithOptionalArrayAttribute() {
let entity = OptionalArrayAttributeEntity(attributes: .init(x: ["hello"], y: nil))
let entity = OptionalArrayAttributeEntity(attributes: .init(x: ["hello"], y: nil), relationships: .none, meta: .none, links: .none)
XCTAssertThrowsError(try OptionalArrayAttributeEntity.check(entity))
}
}
@@ -13,7 +13,7 @@ class NonJSONAPIRelatableTests: XCTestCase {
let e1 = NonJSONAPIEntity(id: .init(rawValue: "hello"))
let e2 = NonJSONAPIEntity(id: .init(rawValue: "world"))
let entity = TestEntity(relationships: .init(one: .init(id: e1.id), many: .init(ids: [e1.id, e2.id])))
let entity = TestEntity(attributes: .none, relationships: .init(one: .init(id: e1.id), many: .init(ids: [e1.id, e2.id])), meta: .none, links: .none)
XCTAssertEqual(entity ~> \.one, e1.id)
XCTAssertEqual(entity ~> \.many, [e1.id, e2.id])
@@ -25,7 +25,7 @@ class NonJSONAPIRelatableTests: XCTestCase {
let e1 = NonJSONAPIEntity(id: .init(rawValue: "hello"))
let e2 = NonJSONAPIEntity(id: .init(rawValue: "world"))
let entity = TestEntity2(relationships: .init(nullableOne: .init(id: e1.id), nullableMaybeOne: .init(id: e2.id), maybeOne: .init(id: e2.id), maybeMany: .init(ids: [e2.id, e1.id])))
let entity = TestEntity2(attributes: .none, relationships: .init(nullableOne: .init(id: e1.id), nullableMaybeOne: .init(id: e2.id), maybeOne: .init(id: e2.id), maybeMany: .init(ids: [e2.id, e1.id])), meta: .none, links: .none)
XCTAssertEqual((entity ~> \.nullableOne)?.rawValue, "hello")
XCTAssertEqual((entity ~> \.nullableMaybeOne)?.rawValue, "world")
@@ -35,8 +35,8 @@ class NonJSONAPIRelatableTests: XCTestCase {
func test_initialization2_all_relationships_missing() {
let entity = TestEntity2(relationships: .init(nullableOne: .init(id: nil), nullableMaybeOne: .init(id: nil), maybeOne: nil, maybeMany: nil))
let entity2 = TestEntity2(relationships: .init(nullableOne: .init(id: nil), nullableMaybeOne: nil, maybeOne: nil, maybeMany: nil))
let entity = TestEntity2(attributes: .none, relationships: .init(nullableOne: .init(id: nil), nullableMaybeOne: .init(id: nil), maybeOne: nil, maybeMany: nil), meta: .none, links: .none)
let entity2 = TestEntity2(attributes: .none, relationships: .init(nullableOne: .init(id: nil), nullableMaybeOne: nil, maybeOne: nil, maybeMany: nil), meta: .none, links: .none)
XCTAssertNil((entity ~> \.nullableOne))
XCTAssertNil((entity ~> \.nullableMaybeOne))
+11 -4
View File
@@ -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
+7 -7
View File
@@ -15,13 +15,13 @@ class PolyTests: XCTestCase {
}
func test_init_Poly1() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly1(entity)
XCTAssertEqual(poly.a, entity)
}
func test_init_Poly2() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly2<TestEntity5, TestEntity>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -32,7 +32,7 @@ class PolyTests: XCTestCase {
}
func test_init_Poly3() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly3<TestEntity5, TestEntity, TestEntity2>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -50,7 +50,7 @@ class PolyTests: XCTestCase {
}
func test_init_Poly4() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly4<TestEntity5, TestEntity, TestEntity2, TestEntity3>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -77,7 +77,7 @@ class PolyTests: XCTestCase {
}
func test_init_Poly5() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly5<TestEntity5, TestEntity, TestEntity2, TestEntity3, TestEntity4>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -115,7 +115,7 @@ class PolyTests: XCTestCase {
}
func test_init_Poly6() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly6<TestEntity5, TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -166,7 +166,7 @@ class PolyTests: XCTestCase {
}
func test_init_Poly7() {
let entity = TestEntity5()
let entity = TestEntity5(attributes: .none, relationships: .none, meta: .none, links: .none)
let poly = Poly7<TestEntity5, TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6, TestEntity7>(entity)
XCTAssertEqual(poly.a, entity)
XCTAssertNil(poly.b)
@@ -11,10 +11,10 @@ import JSONAPI
class RelationshipTests: XCTestCase {
func test_initToManyWithEntities() {
let entity1 = TestEntity1()
let entity2 = TestEntity1()
let entity3 = TestEntity1()
let entity4 = TestEntity1()
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity3 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity4 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let relationship = ToManyRelationship<TestEntity1, NoMetadata, NoLinks>(entities: [entity1, entity2, entity3, entity4])
XCTAssertEqual(relationship.ids.count, 4)
@@ -22,10 +22,10 @@ class RelationshipTests: XCTestCase {
}
func test_initToManyWithRelationships() {
let entity1 = TestEntity1()
let entity2 = TestEntity1()
let entity3 = TestEntity1()
let entity4 = TestEntity1()
let entity1 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity2 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity3 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let entity4 = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let relationship = ToManyRelationship<TestEntity1, NoMetadata, NoLinks>(pointers: [entity1.pointer, entity2.pointer, entity3.pointer, entity4.pointer])
XCTAssertEqual(relationship.ids.count, 4)
@@ -151,7 +151,7 @@ extension RelationshipTests {
}
func test_ToOneNullableIsEqualToNonNullableIfNotNil() {
let entity = TestEntity1()
let entity = TestEntity1(attributes: .none, relationships: .none, meta: .none, links: .none)
let relationship1 = ToOneNonNullable(entity: entity)
let relationship2 = ToOneNullable(entity: entity)
@@ -12,8 +12,8 @@ class ResourceBodyTests: XCTestCase {
func test_initializers() {
let articles = [
Article(attributes: .init(title: "hello")),
Article(attributes: .init(title: "world"))
Article(attributes: .init(title: "hello"), relationships: .none, meta: .none, links: .none),
Article(attributes: .init(title: "world"), relationships: .none, meta: .none, links: .none)
]
let _ = SingleResourceBody(entity: articles[0])
let _ = ManyResourceBody(entities: articles)
@@ -25,7 +25,7 @@ class ResourceBodyTests: XCTestCase {
data: single_resource_body)
XCTAssertEqual(body.value, Article(id: Id<String, Article>(rawValue: "1"),
attributes: ArticleType.Attributes(title: try! .init(rawValue: "JSON:API paints my bikeshed!"))))
attributes: ArticleType.Attributes(title: try! .init(rawValue: "JSON:API paints my bikeshed!")), relationships: .none, meta: .none, links: .none))
}
func test_singleResourceBody_encode() {
@@ -38,9 +38,9 @@ class ResourceBodyTests: XCTestCase {
data: many_resource_body)
XCTAssertEqual(body.values, [
Article(id: .init(rawValue: "1"), attributes: try! .init(title: .init(rawValue: "JSON:API paints my bikeshed!"))),
Article(id: .init(rawValue: "2"), attributes: try! .init(title: .init(rawValue: "Sick"))),
Article(id: .init(rawValue: "3"), attributes: try! .init(title: .init(rawValue: "Hello World")))
Article(id: .init(rawValue: "1"), attributes: try! .init(title: .init(rawValue: "JSON:API paints my bikeshed!")), relationships: .none, meta: .none, links: .none),
Article(id: .init(rawValue: "2"), attributes: try! .init(title: .init(rawValue: "Sick")), relationships: .none, meta: .none, links: .none),
Article(id: .init(rawValue: "3"), attributes: try! .init(title: .init(rawValue: "Hello World")), relationships: .none, meta: .none, links: .none)
])
}

Some files were not shown because too many files have changed in this diff Show More