From 95f9d8084d0ab232a33006ce90d35091d20e2d9a Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Mon, 21 Jan 2019 21:56:33 -0800 Subject: [PATCH] Add Arbitrary conformance for UnknownJSONAPIError. Fix weird encoding exception that I cannot quite figure out or explain at the moment. --- .../Contents.swift | 10 ++++++ .../Usage.xcplaygroundpage/Contents.swift | 4 --- JSONAPI.playground/Sources/Entities.swift | 2 ++ .../Sources/OpenAPISupport.swift | 32 +++++++++++++++++++ .../JSONAPIArbitrary/Error+Arbitrary.swift | 15 +++++++++ Sources/JSONAPIOpenAPI/OpenAPITypes.swift | 8 ++++- .../JSONAPIEntityOpenAPITests.swift | 7 ++-- 7 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 Sources/JSONAPIArbitrary/Error+Arbitrary.swift diff --git a/JSONAPI.playground/Pages/OpenAPI Documentation.xcplaygroundpage/Contents.swift b/JSONAPI.playground/Pages/OpenAPI Documentation.xcplaygroundpage/Contents.swift index c1b6cc9..e9c018a 100644 --- a/JSONAPI.playground/Pages/OpenAPI Documentation.xcplaygroundpage/Contents.swift +++ b/JSONAPI.playground/Pages/OpenAPI Documentation.xcplaygroundpage/Contents.swift @@ -10,4 +10,14 @@ encoder.outputFormatting = .prettyPrinted let personSchemaData = try? encoder.encode(Person.openAPINode()) +print("Person Schema") +print("====") print(personSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed") +print("====") + +let dogDocumentSchemaData = try? encoder.encode(SingleDogDocument.openAPINodeWithExample()) + +print("Dog Document Schema") +print("====") +print(dogDocumentSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed") +print("====") diff --git a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift index bd94b45..25b0235 100644 --- a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift +++ b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift @@ -11,8 +11,6 @@ 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, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError> - let singleDogDocument = SingleDogDocument(apiDescription: .none, body: .init(entity: dogFromCode), includes: .none, meta: .none, links: .none) let singleDogData = try! JSONEncoder().encode(singleDogDocument) @@ -34,8 +32,6 @@ let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner 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, NoMetadata, NoLinks, Include2, NoAPIDescription, UnknownJSONAPIError> - let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { BatchPeopleDocument.Include($0) } let batchPeopleDocument = BatchPeopleDocument(apiDescription: .none, body: .init(entities: people), includes: .init(values: includes), meta: .none, links: .none) let batchPeopleData = try! JSONEncoder().encode(batchPeopleDocument) diff --git a/JSONAPI.playground/Sources/Entities.swift b/JSONAPI.playground/Sources/Entities.swift index 48559cf..c340862 100644 --- a/JSONAPI.playground/Sources/Entities.swift +++ b/JSONAPI.playground/Sources/Entities.swift @@ -139,4 +139,6 @@ public enum HouseDescription: EntityDescription { public typealias House = ExampleEntity +public typealias SingleDogDocument = JSONAPI.Document, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError> +public typealias BatchPeopleDocument = JSONAPI.Document, NoMetadata, NoLinks, Include2, NoAPIDescription, UnknownJSONAPIError> diff --git a/JSONAPI.playground/Sources/OpenAPISupport.swift b/JSONAPI.playground/Sources/OpenAPISupport.swift index 5b7e895..9a1bb9a 100644 --- a/JSONAPI.playground/Sources/OpenAPISupport.swift +++ b/JSONAPI.playground/Sources/OpenAPISupport.swift @@ -2,6 +2,8 @@ import Foundation import JSONAPI import JSONAPITesting // for the convenience of literal initialization import JSONAPIOpenAPI +import SwiftCheck +import JSONAPIArbitrary extension PersonDescription.Attributes: Sampleable { public static var sample: PersonDescription.Attributes { @@ -14,3 +16,33 @@ extension PersonDescription.Relationships: Sampleable { return .init(friends: ["1", "2"], dogs: ["2"], home: "1") } } + +extension DogDescription.Attributes: Arbitrary, Sampleable { + public static var arbitrary: Gen { + return Gen.compose { c in + return DogDescription.Attributes(name: c.generate()) + } + } + + public static var sample: DogDescription.Attributes { + return DogDescription.Attributes.arbitrary.generate + } +} + +extension DogDescription.Relationships: Arbitrary, Sampleable { + public static var arbitrary: Gen { + return Gen.compose { c in + return DogDescription.Relationships(owner: c.generate()) + } + } + + public static var sample: DogDescription.Relationships { + return DogDescription.Relationships.arbitrary.generate + } +} + +extension Document: Sampleable where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary, APIDescription: Arbitrary { + public static var sample: Document { + return Document.arbitrary.generate + } +} diff --git a/Sources/JSONAPIArbitrary/Error+Arbitrary.swift b/Sources/JSONAPIArbitrary/Error+Arbitrary.swift new file mode 100644 index 0000000..0369c69 --- /dev/null +++ b/Sources/JSONAPIArbitrary/Error+Arbitrary.swift @@ -0,0 +1,15 @@ +// +// Error+Arbitrary.swift +// JSONAPIArbitrary +// +// Created by Mathew Polzin on 1/21/19. +// + +import SwiftCheck +import JSONAPI + +extension UnknownJSONAPIError: Arbitrary { + public static var arbitrary: Gen { + return Gen.pure(.unknownError) + } +} diff --git a/Sources/JSONAPIOpenAPI/OpenAPITypes.swift b/Sources/JSONAPIOpenAPI/OpenAPITypes.swift index 65ec92b..30a5338 100644 --- a/Sources/JSONAPIOpenAPI/OpenAPITypes.swift +++ b/Sources/JSONAPIOpenAPI/OpenAPITypes.swift @@ -267,7 +267,11 @@ public enum JSONNode: Equatable { /// into an allowed value. public let allowedValues: [AnyCodable]? - public let example: AnyCodable? + // I wanted example to be AnyCodable, but alas that causes + // runtime problems when encoding in a very strange way. + // For now, a String (which is OK by the OpenAPI spec) will + // have to do. + public let example: String? public init(format: Format, required: Bool, @@ -279,6 +283,8 @@ public enum JSONNode: Equatable { self.nullable = nullable self.allowedValues = allowedValues self.example = example + .flatMap { try? JSONEncoder().encode($0)} + .flatMap { String(data: $0, encoding: .utf8) } } /// Return the optional version of this Context diff --git a/Tests/JSONAPIOpenAPITests/JSONAPIEntityOpenAPITests.swift b/Tests/JSONAPIOpenAPITests/JSONAPIEntityOpenAPITests.swift index 329e0fb..1fc31ae 100644 --- a/Tests/JSONAPIOpenAPITests/JSONAPIEntityOpenAPITests.swift +++ b/Tests/JSONAPIOpenAPITests/JSONAPIEntityOpenAPITests.swift @@ -117,11 +117,6 @@ class JSONAPIEntityOpenAPITests: XCTestCase { nullable: true, allowedValues: nil), .init())) - - let encoder = JSONEncoder() - encoder.outputFormatting = .prettyPrinted - let string = String(data: try! encoder.encode(node), encoding: .utf8)! - print(string) } func test_RelationshipsEntity() { @@ -230,6 +225,8 @@ class JSONAPIEntityOpenAPITests: XCTestCase { nullable: false, allowedValues: nil), manyPointerContext)) + + let tmpData = try! JSONEncoder().encode(node) } func test_AttributesAndRelationshipsEntity() {