Add JSON:API Object to Document as the APIDescription type. Begin to add testing around this new type.

This commit is contained in:
Mathew Polzin
2018-12-02 01:43:27 -08:00
parent 5d666ec998
commit 339480264e
5 changed files with 206 additions and 67 deletions
@@ -11,7 +11,7 @@ Please enjoy these examples, but allow me the forced casting and the lack of err
// MARK: - Create a request or response body with one Dog in it
let dogFromCode = try! Dog(name: "Buddy", owner: nil)
typealias SingleDogDocument = JSONAPI.Document<SingleResourceBody<Dog>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>
typealias SingleDogDocument = JSONAPI.Document<SingleResourceBody<Dog>, NoMetadata, NoLinks, NoIncludes, NoJSONAPIDescription, UnknownJSONAPIError>
let singleDogDocument = SingleDogDocument(body: SingleResourceBody(entity: dogFromCode))
@@ -27,7 +27,7 @@ let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner
let houses = [House(), House()]
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>, UnknownJSONAPIError>
typealias BatchPeopleDocument = JSONAPI.Document<ManyResourceBody<Person>, NoMetadata, NoLinks, Include2<Dog, House>, NoJSONAPIDescription, UnknownJSONAPIError>
let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { BatchPeopleDocument.Include($0) }
let batchPeopleDocument = BatchPeopleDocument(body: .init(entities: people), includes: .init(values: includes))
@@ -0,0 +1,56 @@
//
// APIDescription.swift
// JSONAPI
//
// Created by Mathew Polzin on 12/1/18.
//
/// This is what the JSON API Spec calls the "JSON:API Object"
public protocol APIDescriptionType: Codable, Equatable {
associatedtype Meta
}
/// This is what the JSON API Spec calls the "JSON:API Object"
public struct APIDescription<Meta: JSONAPI.Meta>: APIDescriptionType {
public let version: String?
public let meta: Meta
}
public struct NoAPIDescription: APIDescriptionType, CustomStringConvertible {
public typealias Meta = NoMetadata
public init() {}
public static var none: NoAPIDescription { return .init() }
public var description: String { return "No JSON:API Object" }
}
extension APIDescription {
private enum CodingKeys: String, CodingKey {
case version
case meta
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
version = try container.decode(String?.self, forKey: .version)
if let metaVal = NoMetadata() as? Meta {
meta = metaVal
} else {
meta = try container.decode(Meta.self, forKey: .meta)
}
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(version, forKey: .version)
if Meta.self != NoMetadata.self {
try container.encode(meta, forKey: .meta)
}
}
}
+69 -18
View File
@@ -10,9 +10,10 @@ public protocol JSONAPIDocument: Codable, Equatable {
associatedtype MetaType: JSONAPI.Meta
associatedtype LinksType: JSONAPI.Links
associatedtype IncludeType: JSONAPI.Include
associatedtype APIDescription: APIDescriptionType
associatedtype Error: JSONAPIError
typealias Body = Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, Error>.Body
typealias Body = Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body
var body: Body { get }
}
@@ -24,11 +25,19 @@ public protocol JSONAPIDocument: Codable, Equatable {
/// API uses snake case, you will want to use
/// a conversion such as the one offerred by the
/// Foundation JSONEncoder/Decoder: `KeyDecodingStrategy`
public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links, IncludeType: JSONAPI.Include, Error: JSONAPIError>: JSONAPIDocument {
public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links, IncludeType: JSONAPI.Include, APIDescription: APIDescriptionType, Error: JSONAPIError>: JSONAPIDocument {
public typealias Include = IncludeType
/// The JSON API Spec calls this the JSON:API Object. It contains version
/// and metadata information about the API itself.
public let apiDescription: APIDescription
/// The Body of the Document. This body is either one or more errors
/// with links and metadata attempted to parse but not guaranteed or
/// it is a successful data struct containing all the primary and
/// included resources, the metadata, and the links that this
/// document type specifies.
public let body: Body
// public let jsonApi: APIDescription?
public enum Body: Equatable {
case errors([Error], meta: MetaType?, links: LinksType?)
@@ -91,54 +100,86 @@ public struct Document<PrimaryResourceBody: JSONAPI.ResourceBody, MetaType: JSON
}
}
public init(errors: [Error], meta: MetaType? = nil, links: LinksType? = nil) {
public init(apiDescription: APIDescription, errors: [Error], meta: MetaType? = nil, links: LinksType? = nil) {
body = .errors(errors, meta: meta, links: links)
self.apiDescription = apiDescription
}
public init(body: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType, links: LinksType) {
public init(apiDescription: APIDescription, body: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType, links: LinksType) {
self.body = .data(.init(primary: body, includes: includes, meta: meta, links: links))
self.apiDescription = apiDescription
}
}
extension Document where IncludeType == NoIncludes {
public init(body: PrimaryResourceBody, meta: MetaType, links: LinksType) {
self.body = .data(.init(primary: body, includes: .none, meta: meta, links: links))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, meta: MetaType, links: LinksType) {
self.init(apiDescription: apiDescription, body: body, includes: .none, meta: meta, links: links)
}
}
extension Document where MetaType == NoMetadata {
public init(body: PrimaryResourceBody, includes: Includes<Include>, links: LinksType) {
self.body = .data(.init(primary: body, includes: includes, meta: .none, links: links))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, includes: Includes<Include>, links: LinksType) {
self.init(apiDescription: apiDescription, body: body, includes: includes, meta: .none, links: links)
}
}
extension Document where LinksType == NoLinks {
public init(body: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType) {
self.body = .data(.init(primary: body, includes: includes, meta: meta, links: .none))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType) {
self.init(apiDescription: apiDescription, body: body, includes: includes, meta: meta, links: .none)
}
}
extension Document where APIDescription == NoAPIDescription {
public init(body: PrimaryResourceBody, includes: Includes<Include>, meta: MetaType, links: LinksType) {
self.init(apiDescription: .none, body: body, includes: includes, meta: meta, links: links)
}
}
extension Document where IncludeType == NoIncludes, LinksType == NoLinks {
public init(body: PrimaryResourceBody, meta: MetaType) {
self.body = .data(.init(primary: body, includes: .none, meta: meta, links: .none))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, meta: MetaType) {
self.init(apiDescription: apiDescription, body: body, meta: meta, links: .none)
}
}
extension Document where IncludeType == NoIncludes, MetaType == NoMetadata {
public init(body: PrimaryResourceBody, links: LinksType) {
self.body = .data(.init(primary: body, includes: .none, meta: .none, links: links))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, links: LinksType) {
self.init(apiDescription: apiDescription, body: body, meta: .none, links: links)
}
}
extension Document where IncludeType == NoIncludes, APIDescription == NoAPIDescription {
public init(body: PrimaryResourceBody, meta: MetaType, links: LinksType) {
self.init(apiDescription: .none, body: body, meta: meta, links: links)
}
}
extension Document where MetaType == NoMetadata, LinksType == NoLinks {
public init(body: PrimaryResourceBody, includes: Includes<Include>) {
self.body = .data(.init(primary: body, includes: includes, meta: .none, links: .none))
public init(apiDescription: APIDescription, body: PrimaryResourceBody, includes: Includes<Include>) {
self.init(apiDescription: apiDescription, body: body, includes: includes, links: .none)
}
}
extension Document where MetaType == NoMetadata, APIDescription == NoAPIDescription {
public init(body: PrimaryResourceBody, includes: Includes<Include>, links: LinksType) {
self.init(apiDescription: .none, body: body, includes: includes, links: links)
}
}
extension Document where IncludeType == NoIncludes, MetaType == NoMetadata, LinksType == NoLinks {
public init(apiDescription: APIDescription, body: PrimaryResourceBody) {
self.init(apiDescription: apiDescription, body: body, includes: .none)
}
}
extension Document where MetaType == NoMetadata, LinksType == NoLinks, APIDescription == NoAPIDescription {
public init(body: PrimaryResourceBody, includes: Includes<Include>) {
self.init(apiDescription: .none, body: body, includes: includes)
}
}
extension Document where IncludeType == NoIncludes, MetaType == NoMetadata, LinksType == NoLinks, APIDescription == NoAPIDescription {
public init(body: PrimaryResourceBody) {
self.body = .data(.init(primary: body, includes: .none, meta: .none, links: .none))
self.init(apiDescription: .none, body: body)
}
}
@@ -155,6 +196,12 @@ extension Document {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: RootCodingKeys.self)
if let noData = NoAPIDescription() as? APIDescription {
apiDescription = noData
} else {
apiDescription = try container.decode(APIDescription.self, forKey: .jsonapi)
}
let errors = try container.decodeIfPresent([Error].self, forKey: .errors)
let meta: MetaType?
@@ -242,6 +289,10 @@ extension Document {
try container.encode(data.links, forKey: .links)
}
}
if APIDescription.self != NoAPIDescription.self {
try container.encode(apiDescription, forKey: .jsonapi)
}
}
}
+70 -47
View File
@@ -11,7 +11,7 @@ import JSONAPI
class DocumentTests: XCTestCase {
func test_singleDocumentNull() {
let document = decoded(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_null)
XCTAssertFalse(document.body.isError)
@@ -20,15 +20,36 @@ class DocumentTests: XCTestCase {
XCTAssertEqual(document.body.meta, NoMetadata())
XCTAssertNil(document.body.primaryData?.value)
XCTAssertEqual(document.body.includes?.count, 0)
XCTAssertEqual(document.body.links, NoLinks())
XCTAssertEqual(document.apiDescription, .none)
}
func test_singleDocumentNull_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_null)
}
func test_singleDocumentNullWithAPIDescription() {
let document = decoded(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, TestAPIDescription, UnknownJSONAPIError>.self,
data: single_document_null_with_api_description)
XCTAssertFalse(document.body.isError)
XCTAssertNil(document.body.errors)
XCTAssertNotNil(document.body.primaryData)
XCTAssertEqual(document.body.meta, NoMetadata())
XCTAssertNil(document.body.primaryData?.value)
XCTAssertEqual(document.body.includes?.count, 0)
XCTAssertEqual(document.body.links, NoLinks())
XCTAssertEqual(document.apiDescription.version, "1.0")
}
func test_singleDocumentNullWithAPIDescription_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, TestAPIDescription, UnknownJSONAPIError>.self,
data: single_document_null_with_api_description)
}
func test_singleDocumentNonOptionalFailsOnNull() {
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
from: single_document_null))
}
}
@@ -36,7 +57,7 @@ class DocumentTests: XCTestCase {
// MARK: - Error Document Tests
extension DocumentTests {
func test_unknownErrorDocumentNoMeta() {
let document = decoded(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_no_metadata)
XCTAssertTrue(document.body.isError)
@@ -56,12 +77,12 @@ extension DocumentTests {
}
func test_unknownErrorDocumentNoMeta_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_no_metadata)
}
func test_unknownErrorDocumentMissingMeta() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: error_document_no_metadata)
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, data: error_document_no_metadata)
XCTAssertTrue(document.body.isError)
XCTAssertNil(document.body.meta)
@@ -80,11 +101,11 @@ extension DocumentTests {
}
func test_unknownErrorDocumentMissingMeta_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: error_document_no_metadata)
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, data: error_document_no_metadata)
}
func test_errorDocumentNoMeta() {
let document = decoded(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, TestError>.self,
let document = decoded(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, TestError>.self,
data: error_document_no_metadata)
XCTAssertTrue(document.body.isError)
@@ -104,12 +125,12 @@ extension DocumentTests {
}
func test_errorDocumentNoMeta_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, TestError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, TestError>.self,
data: error_document_no_metadata)
}
func test_unknownErrorDocumentWithMeta() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_metadata)
XCTAssertTrue(document.body.isError)
@@ -128,12 +149,12 @@ extension DocumentTests {
}
func test_unknownErrorDocumentWithMeta_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_metadata)
}
func test_unknownErrorDocumentWithMetaWithLinks() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_metadata_with_links)
XCTAssertTrue(document.body.isError)
@@ -156,12 +177,12 @@ extension DocumentTests {
}
func test_unknownErrorDocumentWithMetaWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_metadata_with_links)
}
func test_unknownErrorDocumentWithLinks() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_links)
XCTAssertTrue(document.body.isError)
@@ -182,12 +203,12 @@ extension DocumentTests {
}
func test_unknownErrorDocumentWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_with_links)
}
func test_unknownErrorDocumentMissingLinks() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_no_metadata)
XCTAssertTrue(document.body.isError)
@@ -205,7 +226,7 @@ extension DocumentTests {
}
func test_unknownErrorDocumentMissingLinks_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: error_document_no_metadata)
}
}
@@ -213,7 +234,7 @@ extension DocumentTests {
// MARK: - Meta Document Tests
extension DocumentTests {
func test_metaDataDocument() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: metadata_document)
XCTAssertFalse(document.body.isError)
@@ -224,12 +245,12 @@ extension DocumentTests {
}
func test_metaDataDocument_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: metadata_document)
}
func test_metaDataDocumentWithLinks() {
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: metadata_document_with_links)
XCTAssertFalse(document.body.isError)
@@ -244,14 +265,14 @@ extension DocumentTests {
}
func test_metaDataDocumentWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<NoResourceBody, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: metadata_document_with_links)
}
func test_metaDocumentMissingMeta() {
XCTAssertThrowsError(try JSONDecoder().decode(Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, from: metadata_document_missing_metadata))
XCTAssertThrowsError(try JSONDecoder().decode(Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, from: metadata_document_missing_metadata))
XCTAssertThrowsError(try JSONDecoder().decode(Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, from: metadata_document_missing_metadata2))
XCTAssertThrowsError(try JSONDecoder().decode(Document<NoResourceBody, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, from: metadata_document_missing_metadata2))
}
}
@@ -259,7 +280,7 @@ extension DocumentTests {
// MARK: Single Document Tests
extension DocumentTests {
func test_singleDocumentNoIncludes() {
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes)
XCTAssertFalse(document.body.isError)
@@ -271,12 +292,12 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludes_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes)
}
func test_singleDocumentNoIncludesOptionalNotNull() {
let document = decoded(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes)
XCTAssertFalse(document.body.isError)
@@ -288,12 +309,12 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludesOptionalNotNull_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article?>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes)
}
func test_singleDocumentNoIncludesWithMetadata() {
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_metadata)
XCTAssertFalse(document.body.isError)
@@ -305,12 +326,12 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludesWithMetadata_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_metadata)
}
func test_singleDocumentNoIncludesWithLinks() {
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_links)
XCTAssertFalse(document.body.isError)
@@ -327,12 +348,12 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludesWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_links)
}
func test_singleDocumentNoIncludesWithMetadataWithLinks() {
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_metadata_with_links)
XCTAssertFalse(document.body.isError)
@@ -349,20 +370,20 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludesWithMetadataWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_no_includes_with_metadata_with_links)
}
func test_singleDocumentNoIncludesWithMetadataMissingLinks() {
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes_with_metadata))
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, from: single_document_no_includes_with_metadata))
}
func test_singleDocumentNoIncludesMissingMetadata() {
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes))
XCTAssertThrowsError(try JSONDecoder().decode(Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, from: single_document_no_includes))
}
func test_singleDocumentSomeIncludes() {
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes)
XCTAssertFalse(document.body.isError)
@@ -375,12 +396,12 @@ extension DocumentTests {
}
func test_singleDocumentSomeIncludes_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes)
}
func test_singleDocumentSomeIncludesWithMetadata() {
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes_with_metadata)
XCTAssertFalse(document.body.isError)
@@ -394,12 +415,12 @@ extension DocumentTests {
}
func test_singleDocumentSomeIncludesWithMetadata_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes_with_metadata)
}
func test_singleDocumentNoIncludesWithSomeIncludesWithMetadataWithLinks() {
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, Include1<Author>, UnknownJSONAPIError>.self,
let document = decoded(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes_with_metadata_with_links)
XCTAssertFalse(document.body.isError)
@@ -417,7 +438,7 @@ extension DocumentTests {
}
func test_singleDocumentNoIncludesWithSomeIncludesMetadataWithLinks_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, Include1<Author>, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Article>, TestPageMetadata, TestLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: single_document_some_includes_with_metadata_with_links)
}
}
@@ -426,21 +447,21 @@ extension DocumentTests {
extension DocumentTests {
func test_singleDocument_PolyPrimaryResource() {
let article = Article(id: Id(rawValue: "1"), relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33"))))
let document = decoded(type: Document<SingleResourceBody<Poly2<Article, Author>>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes)
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])
}
func test_singleDocument_PolyPrimaryResource_encode() {
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Poly2<Article, Author>>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes)
test_DecodeEncodeEquality(type: Document<SingleResourceBody<Poly2<Article, Author>>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self, data: single_document_no_includes)
}
}
// MARK: - ManyResourceBody Tests
extension DocumentTests {
func test_manyDocumentNoIncludes() {
let document = decoded(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
let document = decoded(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: many_document_no_includes)
XCTAssertFalse(document.body.isError)
@@ -454,12 +475,12 @@ extension DocumentTests {
}
func test_manyDocumentNoIncludes_encode() {
test_DecodeEncodeEquality(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>.self,
data: many_document_no_includes)
}
func test_manyDocumentSomeIncludes() {
let document = decoded(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
let document = decoded(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: many_document_some_includes)
XCTAssertFalse(document.body.isError)
@@ -477,7 +498,7 @@ extension DocumentTests {
}
func test_manyDocumentSomeIncludes_encode() {
test_DecodeEncodeEquality(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, UnknownJSONAPIError>.self,
test_DecodeEncodeEquality(type: Document<ManyResourceBody<Article>, NoMetadata, NoLinks, Include1<Author>, NoAPIDescription, UnknownJSONAPIError>.self,
data: many_document_some_includes)
}
}
@@ -520,6 +541,8 @@ extension DocumentTests {
}
}
typealias TestAPIDescription = APIDescription<NoMetadata>
enum TestError: JSONAPIError {
case unknownError
case basic(BasicError)
@@ -11,6 +11,15 @@ let single_document_null = """
}
""".data(using: .utf8)!
let single_document_null_with_api_description = """
{
"data": null,
"jsonapi": {
"version": "1.0"
}
}
""".data(using: .utf8)!
let single_document_no_includes = """
{
"data": {