mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-07-10 12:18:40 -07:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04bf96a0cf | |||
| 8668311307 | |||
| 689517c633 | |||
| 65b80ee0eb | |||
| e91a03b396 | |||
| 82088c7852 | |||
| 34a4c8e7fc |
@@ -13,7 +13,6 @@ public protocol JSONAPIDocument: Codable, Equatable {
|
||||
associatedtype Error: JSONAPIError
|
||||
|
||||
typealias Body = Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, Error>.Body
|
||||
typealias BodyData = Body.Data
|
||||
|
||||
var body: Body { get }
|
||||
}
|
||||
@@ -40,6 +39,13 @@ public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSON
|
||||
public let includes: Includes<Include>
|
||||
public let meta: MetaType
|
||||
public let links: LinksType
|
||||
|
||||
public init(primary: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType, links: LinksType) {
|
||||
self.primary = primary
|
||||
self.includes = includes
|
||||
self.meta = meta
|
||||
self.links = links
|
||||
}
|
||||
}
|
||||
|
||||
public var isError: Bool {
|
||||
|
||||
@@ -32,7 +32,7 @@ public struct NoResourceBody: ResourceBody {
|
||||
public static var none: NoResourceBody { return NoResourceBody() }
|
||||
}
|
||||
|
||||
// MARK: Decodable
|
||||
// MARK: Codable
|
||||
extension SingleResourceBody {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
@@ -19,6 +19,13 @@ public struct TransformedAttribute<RawValue: Codable, Transformer: JSONAPI.Trans
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute where Transformer: ReversibleTransformer {
|
||||
public init(transformedValue: Transformer.To) throws {
|
||||
self.value = transformedValue
|
||||
rawValue = try Transformer.reverse(value)
|
||||
}
|
||||
}
|
||||
|
||||
extension TransformedAttribute: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return "Attribute<\(String(describing: Transformer.From.self)) -> \(String(describing: Transformer.To.self))>(\(String(describing: value)))"
|
||||
|
||||
@@ -16,11 +16,15 @@ public typealias Attributes = Codable & Equatable
|
||||
|
||||
/// Can be used as `Relationships` Type for Entities that do not
|
||||
/// have any Relationships.
|
||||
public struct NoRelationships: Relationships {}
|
||||
public struct NoRelationships: Relationships {
|
||||
public static var none: NoRelationships { return .init() }
|
||||
}
|
||||
|
||||
/// Can be used as `Attributes` Type for Entities that do not
|
||||
/// have any Attributes.
|
||||
public struct NoAttributes: Attributes {}
|
||||
public struct NoAttributes: Attributes {
|
||||
public static var none: NoAttributes { return .init() }
|
||||
}
|
||||
|
||||
/// An `EntityDescription` describes a JSON API
|
||||
/// Resource Object. The Resource Object
|
||||
@@ -34,10 +38,10 @@ public protocol EntityDescription {
|
||||
static var type: String { get }
|
||||
}
|
||||
|
||||
/// EntityType is the protocol that Entity conforms to. This
|
||||
/// protocol lets other types accept any Entity as a generic
|
||||
/// specialization.
|
||||
public protocol EntityType: PrimaryResource {
|
||||
/// 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 {
|
||||
associatedtype Description: EntityDescription
|
||||
associatedtype EntityRawIdType: JSONAPI.MaybeRawId
|
||||
|
||||
@@ -59,6 +63,17 @@ public protocol EntityType: PrimaryResource {
|
||||
var relationships: Relationships { get }
|
||||
}
|
||||
|
||||
extension EntityProxy {
|
||||
/// The JSON API compliant "type" of this `Entity`.
|
||||
public static var type: String { return Description.type }
|
||||
}
|
||||
|
||||
/// 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 IdentifiableEntityType: EntityType, Relatable where EntityRawIdType: JSONAPI.RawIdType {}
|
||||
|
||||
/// An `Entity` is a single model type that can be
|
||||
@@ -66,10 +81,6 @@ public protocol IdentifiableEntityType: EntityType, Relatable where EntityRawIdT
|
||||
/// "Resource Object."
|
||||
/// See https://jsonapi.org/format/#document-resource-objects
|
||||
public struct Entity<Description: JSONAPI.EntityDescription, EntityRawIdType: JSONAPI.MaybeRawId>: EntityType {
|
||||
|
||||
/// The JSON API compliant "type" of this `Entity`.
|
||||
public static var type: String { return Description.type }
|
||||
|
||||
/// 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,
|
||||
@@ -155,21 +166,21 @@ public extension Entity where EntityRawIdType: JSONAPI.RawIdType {
|
||||
}
|
||||
|
||||
// MARK: Attribute Access
|
||||
public extension Entity {
|
||||
public extension EntityProxy {
|
||||
/// Access the attribute at the given keypath. This just
|
||||
/// allows you to write `entity[\.propertyName]` instead
|
||||
/// of `entity.relationships.propertyName`.
|
||||
subscript<T, TFRM: Transformer>(_ path: KeyPath<Description.Attributes, TransformedAttribute<T, TFRM>>) -> TFRM.To {
|
||||
return attributes[keyPath: path].value
|
||||
}
|
||||
|
||||
|
||||
/// Access the attribute at the given keypath. This just
|
||||
/// allows you to write `entity[\.propertyName]` instead
|
||||
/// of `entity.relationships.propertyName`.
|
||||
subscript<T, TFRM: Transformer>(_ path: KeyPath<Description.Attributes, TransformedAttribute<T, TFRM>?>) -> TFRM.To? {
|
||||
return attributes[keyPath: path]?.value
|
||||
}
|
||||
|
||||
|
||||
/// Access the attribute at the given keypath. This just
|
||||
/// allows you to write `entity[\.propertyName]` instead
|
||||
/// of `entity.relationships.propertyName`.
|
||||
@@ -179,18 +190,18 @@ public extension Entity {
|
||||
}
|
||||
|
||||
// MARK: Relationship Access
|
||||
public extension Entity {
|
||||
public extension EntityProxy {
|
||||
/// Access to an Id of a `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other.id`.
|
||||
public static func ~><OtherEntity: OptionalRelatable>(entity: Entity, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity>>) -> OtherEntity.WrappedIdentifier {
|
||||
public static func ~><OtherEntity: OptionalRelatable>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity>>) -> OtherEntity.WrappedIdentifier {
|
||||
return entity.relationships[keyPath: path].id
|
||||
}
|
||||
|
||||
/// Access to all Ids of a `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others.ids`.
|
||||
public static func ~><OtherEntity: Relatable>(entity: Entity, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity>>) -> [OtherEntity.Identifier] {
|
||||
public static func ~><OtherEntity: Relatable>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity>>) -> [OtherEntity.Identifier] {
|
||||
return entity.relationships[keyPath: path].ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public struct Unidentified: MaybeRawId, CustomStringConvertible {
|
||||
}
|
||||
|
||||
public protocol MaybeId: Codable {
|
||||
associatedtype EntityType: JSONAPI.EntityType
|
||||
associatedtype EntityType: JSONAPI.EntityProxy
|
||||
associatedtype RawType: MaybeRawId
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public protocol CreatableIdType: IdType {
|
||||
|
||||
/// An Entity ID. These IDs can be encoded to or decoded from
|
||||
/// JSON API IDs.
|
||||
public struct Id<RawType: MaybeRawId, EntityType: JSONAPI.EntityType>: Codable, Equatable, MaybeId {
|
||||
public struct Id<RawType: MaybeRawId, EntityType: JSONAPI.EntityProxy>: Codable, Equatable, MaybeId {
|
||||
|
||||
public let rawValue: RawType
|
||||
|
||||
|
||||
@@ -9,11 +9,16 @@ public protocol Transformer {
|
||||
associatedtype From
|
||||
associatedtype To
|
||||
|
||||
static func transform(_ from: From) throws -> To
|
||||
static func transform(_ value: From) throws -> To
|
||||
}
|
||||
|
||||
public enum IdentityTransformer<T>: Transformer {
|
||||
public static func transform(_ from: T) throws -> T { return from }
|
||||
public protocol ReversibleTransformer: Transformer {
|
||||
static func reverse(_ value: To) throws -> From
|
||||
}
|
||||
|
||||
public enum IdentityTransformer<T>: ReversibleTransformer {
|
||||
public static func transform(_ value: T) throws -> T { return value }
|
||||
public static func reverse(_ value: T) throws -> T { return value }
|
||||
}
|
||||
|
||||
// MARK: - Validator
|
||||
@@ -22,10 +27,19 @@ public enum IdentityTransformer<T>: Transformer {
|
||||
/// is passed to it but it does not change the type of the value. Any
|
||||
/// Transformer will perform validation in one sense so a Validator is
|
||||
/// really just semantic sugar (it can provide clarity in its use).
|
||||
public protocol Validator: Transformer where From == To {}
|
||||
/// To enforce the semantics, any change of the value in your implementation
|
||||
/// of `Validator.transform()` will be ignored.
|
||||
public protocol Validator: ReversibleTransformer where From == To {
|
||||
}
|
||||
|
||||
extension Validator {
|
||||
public static func reverse(_ value: To) throws -> To {
|
||||
let _ = try transform(value)
|
||||
return value
|
||||
}
|
||||
|
||||
public static func validate(_ value: To) throws -> To {
|
||||
return try transform(value)
|
||||
let _ = try transform(value)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,12 +8,25 @@
|
||||
import JSONAPI
|
||||
|
||||
public enum EntityCheckError: Swift.Error {
|
||||
/// The attributes should live in a struct, not
|
||||
/// another type class.
|
||||
case attributesNotStruct
|
||||
|
||||
/// The relationships should live in a struct, not
|
||||
/// another type class.
|
||||
case relationshipsNotStruct
|
||||
|
||||
/// All stored properties on an Attributes struct should
|
||||
/// be one of the supplied Attribute types.
|
||||
case nonAttribute(named: String)
|
||||
|
||||
/// All stored properties on a Relationships struct should
|
||||
/// be one of the supplied Relationship types.
|
||||
case nonRelationship(named: String)
|
||||
|
||||
/// It is explicitly stated by the JSON spec
|
||||
/// a "none" value for arrays is an empty array, not `nil`.
|
||||
case nullArray(named: String)
|
||||
case badId
|
||||
}
|
||||
|
||||
public struct EntityCheckErrors: Swift.Error {
|
||||
@@ -36,10 +49,6 @@ public extension Entity {
|
||||
public static func check(_ entity: Entity) throws {
|
||||
var problems = [EntityCheckError]()
|
||||
|
||||
if Swift.type(of: entity.id).EntityType.Description.self != Description.self {
|
||||
problems.append(.badId)
|
||||
}
|
||||
|
||||
let attributesMirror = Mirror(reflecting: entity.attributes)
|
||||
|
||||
if attributesMirror.displayStyle != .`struct` {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// Optional+Literal.swift
|
||||
// JSONAPITestLib
|
||||
//
|
||||
// Created by Mathew Polzin on 11/29/18.
|
||||
//
|
||||
|
||||
extension Optional: ExpressibleByUnicodeScalarLiteral where Wrapped: ExpressibleByUnicodeScalarLiteral {
|
||||
public typealias UnicodeScalarLiteralType = Wrapped.UnicodeScalarLiteralType
|
||||
|
||||
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
|
||||
self = .some(Wrapped(unicodeScalarLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Optional: ExpressibleByExtendedGraphemeClusterLiteral where Wrapped: ExpressibleByExtendedGraphemeClusterLiteral {
|
||||
public typealias ExtendedGraphemeClusterLiteralType = Wrapped.ExtendedGraphemeClusterLiteralType
|
||||
|
||||
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
|
||||
self = .some(Wrapped(extendedGraphemeClusterLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension Optional: ExpressibleByStringLiteral where Wrapped: ExpressibleByStringLiteral {
|
||||
public typealias StringLiteralType = Wrapped.StringLiteralType
|
||||
|
||||
public init(stringLiteral value: StringLiteralType) {
|
||||
self = .some(Wrapped(stringLiteral: value))
|
||||
}
|
||||
}
|
||||
@@ -9,10 +9,35 @@ import JSONAPI
|
||||
|
||||
extension ToOneRelationship: ExpressibleByNilLiteral where Relatable.WrappedIdentifier: ExpressibleByNilLiteral {
|
||||
public init(nilLiteral: ()) {
|
||||
|
||||
self.init(id: Relatable.WrappedIdentifier(nilLiteral: ()))
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Relatable.WrappedIdentifier: ExpressibleByUnicodeScalarLiteral {
|
||||
public typealias UnicodeScalarLiteralType = Relatable.WrappedIdentifier.UnicodeScalarLiteralType
|
||||
|
||||
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
|
||||
self.init(id: Relatable.WrappedIdentifier(unicodeScalarLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where Relatable.WrappedIdentifier: ExpressibleByExtendedGraphemeClusterLiteral {
|
||||
public typealias ExtendedGraphemeClusterLiteralType = Relatable.WrappedIdentifier.ExtendedGraphemeClusterLiteralType
|
||||
|
||||
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
|
||||
self.init(id: Relatable.WrappedIdentifier(extendedGraphemeClusterLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship: ExpressibleByStringLiteral where Relatable.WrappedIdentifier: ExpressibleByStringLiteral {
|
||||
public typealias StringLiteralType = Relatable.WrappedIdentifier.StringLiteralType
|
||||
|
||||
public init(stringLiteral value: StringLiteralType) {
|
||||
self.init(id: Relatable.WrappedIdentifier(stringLiteral: value))
|
||||
}
|
||||
}
|
||||
|
||||
extension ToManyRelationship: ExpressibleByArrayLiteral {
|
||||
public typealias ArrayLiteralElement = Relatable.Identifier
|
||||
|
||||
|
||||
@@ -18,4 +18,31 @@ class AttributeTests: XCTestCase {
|
||||
XCTAssertEqual(try Attribute<String>(rawValue: "hello"), Attribute<String>(value: "hello"))
|
||||
}
|
||||
|
||||
func test_TransformedAttributeNoThrow() {
|
||||
XCTAssertNoThrow(try TransformedAttribute<String, TestTransformer>(rawValue: "10"))
|
||||
}
|
||||
|
||||
func test_TransformedAttributeThrows() {
|
||||
XCTAssertThrowsError(try TransformedAttribute<String, TestTransformer>(rawValue: "10.3"))
|
||||
}
|
||||
|
||||
func test_TransformedAttributeReversNoThrow() {
|
||||
XCTAssertNoThrow(try TransformedAttribute<String, TestTransformer>(transformedValue: 10))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Test types
|
||||
extension AttributeTests {
|
||||
enum TestTransformer: ReversibleTransformer {
|
||||
public static func transform(_ value: String) throws -> Int {
|
||||
guard let ret = Int(value) else {
|
||||
throw DecodingError.typeMismatch(Int.self, .init(codingPath: [], debugDescription: "Expected Int from String."))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
public static func reverse(_ value: Int) throws -> String {
|
||||
return String(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,11 @@ class Relationship_LiteralTests: XCTestCase {
|
||||
func test_ArrayLiteral() {
|
||||
XCTAssertEqual(ToManyRelationship<TestEntity>(ids: ["1", "2", "3"]), ["1", "2", "3"])
|
||||
}
|
||||
|
||||
func test_StringLiteral() {
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity>(id: "123"), "123")
|
||||
XCTAssertEqual(ToOneRelationship<TestEntity?>(id: "123"), "123")
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test types
|
||||
|
||||
@@ -0,0 +1,159 @@
|
||||
//
|
||||
// PolyProxyTests.swift
|
||||
// JSONAPITests
|
||||
//
|
||||
// Created by Mathew Polzin on 11/29/18.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
import JSONAPI
|
||||
|
||||
public class PolyProxyTests: XCTestCase {
|
||||
func test_generalReasonableness() {
|
||||
XCTAssertNotEqual(decoded(type: User.self, data: poly_user_stub_1), decoded(type: User.self, data: poly_user_stub_2))
|
||||
XCTAssertEqual(User.type, "users")
|
||||
}
|
||||
|
||||
func test_UserADecode() {
|
||||
let polyUserA = decoded(type: User.self, data: poly_user_stub_1)
|
||||
let userA = decoded(type: UserA.self, data: poly_user_stub_1)
|
||||
|
||||
XCTAssertEqual(polyUserA.userA, userA)
|
||||
XCTAssertNil(polyUserA.userB)
|
||||
XCTAssertEqual(polyUserA[\.name], "Ken Moore")
|
||||
XCTAssertEqual(polyUserA.id, "1")
|
||||
XCTAssertEqual(polyUserA.relationships, .none)
|
||||
}
|
||||
|
||||
func test_UserAAndBEncodeEquality() {
|
||||
test_DecodeEncodeEquality(type: User.self, data: poly_user_stub_1)
|
||||
test_DecodeEncodeEquality(type: User.self, data: poly_user_stub_2)
|
||||
}
|
||||
|
||||
func test_AsymmetricEncodeDecodeUserA() {
|
||||
let userA = decoded(type: UserA.self, data: poly_user_stub_1)
|
||||
let polyUserA = decoded(type: User.self, data: poly_user_stub_1)
|
||||
|
||||
let encodedPoly = try! JSONEncoder().encode(polyUserA)
|
||||
|
||||
XCTAssertEqual(decoded(type: UserA.self, data: encodedPoly), userA)
|
||||
}
|
||||
|
||||
func test_AsymmetricEncodeDecodeUserB() {
|
||||
let userB = decoded(type: UserB.self, data: poly_user_stub_2)
|
||||
let polyUserB = decoded(type: User.self, data: poly_user_stub_2)
|
||||
|
||||
let encodedPoly = try! JSONEncoder().encode(polyUserB)
|
||||
|
||||
XCTAssertEqual(decoded(type: UserB.self, data: encodedPoly), userB)
|
||||
}
|
||||
|
||||
func test_UserBDecode() {
|
||||
let polyUserB = decoded(type: User.self, data: poly_user_stub_2)
|
||||
let userB = decoded(type: UserB.self, data: poly_user_stub_2)
|
||||
|
||||
XCTAssertEqual(polyUserB.userB, userB)
|
||||
XCTAssertNil(polyUserB.userA)
|
||||
XCTAssertEqual(polyUserB[\.name], "Ken Less")
|
||||
XCTAssertEqual(polyUserB.id, "2")
|
||||
XCTAssertEqual(polyUserB.relationships, .none)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test types
|
||||
public extension PolyProxyTests {
|
||||
public enum UserDescription1: EntityDescription {
|
||||
public static var type: String { return "users" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
let firstName: Attribute<String>
|
||||
let lastName: Attribute<String>
|
||||
}
|
||||
|
||||
public typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
public enum UserDescription2: EntityDescription {
|
||||
public static var type: String { return "users" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<[String]>
|
||||
}
|
||||
|
||||
public typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
public typealias UserA = Entity<UserDescription1>
|
||||
public typealias UserB = Entity<UserDescription2>
|
||||
|
||||
public typealias User = Poly2<UserA, UserB>
|
||||
}
|
||||
|
||||
extension Poly2: EntityProxy where A == PolyProxyTests.UserA, B == PolyProxyTests.UserB {
|
||||
|
||||
public var userA: PolyProxyTests.UserA? {
|
||||
return a
|
||||
}
|
||||
|
||||
public var userB: PolyProxyTests.UserB? {
|
||||
return b
|
||||
}
|
||||
|
||||
public var id: Id<EntityRawIdType, PolyProxyTests.User> {
|
||||
switch self {
|
||||
case .a(let a):
|
||||
return Id(rawValue: a.id.rawValue)
|
||||
case .b(let b):
|
||||
return Id(rawValue: b.id.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var attributes: SharedUserDescription.Attributes {
|
||||
switch self {
|
||||
case .a(let a):
|
||||
return .init(name: .init(value: "\(a[\.firstName]) \(a[\.lastName])"))
|
||||
case .b(let b):
|
||||
return .init(name: .init(value: b[\.name].joined(separator: " ")))
|
||||
}
|
||||
}
|
||||
|
||||
public var relationships: NoRelationships {
|
||||
return .none
|
||||
}
|
||||
|
||||
public enum SharedUserDescription: EntityDescription {
|
||||
public static var type: String { return A.type }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
}
|
||||
|
||||
public typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
public typealias Description = SharedUserDescription
|
||||
|
||||
public typealias EntityRawIdType = A.EntityRawIdType
|
||||
}
|
||||
|
||||
// MARK: - Test stubs
|
||||
private let poly_user_stub_1 = """
|
||||
{
|
||||
"id": "1",
|
||||
"type": "users",
|
||||
"attributes": {
|
||||
"firstName": "Ken",
|
||||
"lastName": "Moore"
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
private let poly_user_stub_2 = """
|
||||
{
|
||||
"id": "2",
|
||||
"type": "users",
|
||||
"attributes": {
|
||||
"name": ["Ken", "Less"]
|
||||
}
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
@@ -4,6 +4,9 @@ extension AttributeTests {
|
||||
static let __allTests = [
|
||||
("test_AttributeIsTransformedAttribute", test_AttributeIsTransformedAttribute),
|
||||
("test_AttributeNonThrowingConstructor", test_AttributeNonThrowingConstructor),
|
||||
("test_TransformedAttributeNoThrow", test_TransformedAttributeNoThrow),
|
||||
("test_TransformedAttributeReversNoThrow", test_TransformedAttributeReversNoThrow),
|
||||
("test_TransformedAttributeThrows", test_TransformedAttributeThrows),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -180,6 +183,17 @@ extension LinksTests {
|
||||
]
|
||||
}
|
||||
|
||||
extension PolyProxyTests {
|
||||
static let __allTests = [
|
||||
("test_AsymmetricEncodeDecodeUserA", test_AsymmetricEncodeDecodeUserA),
|
||||
("test_AsymmetricEncodeDecodeUserB", test_AsymmetricEncodeDecodeUserB),
|
||||
("test_generalReasonableness", test_generalReasonableness),
|
||||
("test_UserAAndBEncodeEquality", test_UserAAndBEncodeEquality),
|
||||
("test_UserADecode", test_UserADecode),
|
||||
("test_UserBDecode", test_UserBDecode),
|
||||
]
|
||||
}
|
||||
|
||||
extension PolyTests {
|
||||
static let __allTests = [
|
||||
("test_init_Poly0", test_init_Poly0),
|
||||
@@ -223,6 +237,7 @@ extension Relationship_LiteralTests {
|
||||
static let __allTests = [
|
||||
("test_ArrayLiteral", test_ArrayLiteral),
|
||||
("test_NilLiteral", test_NilLiteral),
|
||||
("test_StringLiteral", test_StringLiteral),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -250,6 +265,7 @@ public func __allTests() -> [XCTestCaseEntry] {
|
||||
testCase(Id_LiteralTests.__allTests),
|
||||
testCase(IncludedTests.__allTests),
|
||||
testCase(LinksTests.__allTests),
|
||||
testCase(PolyProxyTests.__allTests),
|
||||
testCase(PolyTests.__allTests),
|
||||
testCase(RelationshipTests.__allTests),
|
||||
testCase(Relationship_LiteralTests.__allTests),
|
||||
|
||||
Reference in New Issue
Block a user