Fill out a fair bit of OpenAPI Entity testing

This commit is contained in:
Mathew Polzin
2019-01-21 15:32:38 -08:00
parent 45eb7d06bd
commit 845d085455
5 changed files with 271 additions and 17 deletions
@@ -110,7 +110,7 @@ extension JSONNode.ArrayContext: Encodable {
}
}
extension JSONNode.ObjectContext : Encodable{
extension JSONNode.ObjectContext : Encodable {
private enum CodingKeys: String, CodingKey {
case maxProperties
case minProperties
@@ -132,13 +132,9 @@ extension JSONNode.ObjectContext : Encodable{
try container.encode(additionalProperties, forKey: .additionalProperties)
}
let required = properties.filter { (name, node) in
node.required
}.keys
try container.encode(requiredProperties, forKey: .required)
try container.encode(Array(required), forKey: .required)
try container.encode(max(minProperties, required.count), forKey: .minProperties)
try container.encode(minProperties, forKey: .minProperties)
}
}
+11 -3
View File
@@ -371,7 +371,7 @@ public enum JSONNode: Equatable {
public struct ObjectContext: Equatable {
public let maxProperties: Int?
public let minProperties: Int
let _minProperties: Int
public let properties: [String: JSONNode]
public let additionalProperties: [String: JSONNode]?
@@ -379,8 +379,16 @@ public enum JSONNode: Equatable {
// NOTE that an object's required properties
// array is determined by looking at its properties'
// required Bool.
public let required: [String]
*/
public var requiredProperties: [String] {
return Array(properties.filter { (name, node) in
node.required
}.keys)
}
public var minProperties: Int {
return max(_minProperties, requiredProperties.count)
}
public init(properties: [String: JSONNode],
additionalProperties: [String: JSONNode]? = nil,
@@ -389,7 +397,7 @@ public enum JSONNode: Equatable {
self.properties = properties
self.additionalProperties = additionalProperties
self.maxProperties = maxProperties
self.minProperties = minProperties
self._minProperties = minProperties
}
}
@@ -429,7 +429,7 @@ extension JSONAPIAttributeOpenAPITests {
extension JSONAPIAttributeOpenAPITests {
func test_EnumAttribute() {
let node = try! Attribute<EnumAttribute>.rawOpenAPINode()
print(EnumAttribute.allCases)
XCTAssertTrue(node.required)
XCTAssertEqual(node.jsonTypeFormat, .string(.generic))
@@ -8,12 +8,115 @@
import XCTest
import JSONAPI
import JSONAPIOpenAPI
import AnyCodable
class JSONAPIEntityOpenAPITests: XCTestCase {
func test_EmptyEntity() {
let node = try! TestType1.openAPINode()
// TODO: Write test
XCTAssertTrue(node.required)
XCTAssertEqual(node.jsonTypeFormat, .object(.generic))
guard case let .object(contextA, objectContext1) = node else {
XCTFail("Expected Object node")
return
}
XCTAssertEqual(contextA, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(objectContext1.minProperties, 2)
XCTAssertEqual(Set(objectContext1.requiredProperties), Set(["id", "type"]))
XCTAssertEqual(Set(objectContext1.properties.keys), Set(["id", "type"]))
XCTAssertEqual(objectContext1.properties["id"], .string(.init(format: .generic,
required: true),
.init()))
XCTAssertEqual(objectContext1.properties["type"], .string(.init(format: .generic,
required: true),
.init()))
}
func test_AttributesEntity() {
let node = try! TestType2.openAPINode()
XCTAssertTrue(node.required)
XCTAssertEqual(node.jsonTypeFormat, .object(.generic))
guard case let .object(contextA, objectContext1) = node else {
XCTFail("Expected Object node")
return
}
XCTAssertEqual(contextA, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(objectContext1.minProperties, 3)
XCTAssertEqual(Set(objectContext1.requiredProperties), Set(["id", "type", "attributes"]))
XCTAssertEqual(Set(objectContext1.properties.keys), Set(["id", "type", "attributes"]))
XCTAssertEqual(objectContext1.properties["id"], .string(.init(format: .generic,
required: true),
.init()))
XCTAssertEqual(objectContext1.properties["type"], .string(.init(format: .generic,
required: true),
.init()))
let attributesNode = objectContext1.properties["attributes"]
XCTAssertNotNil(attributesNode)
XCTAssertTrue(attributesNode?.required ?? false)
XCTAssertEqual(attributesNode?.jsonTypeFormat, .object(.generic))
guard case let .object(contextB, attributesContext)? = attributesNode else {
XCTFail("Expected Object node for attributes")
return
}
XCTAssertEqual(contextB, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(attributesContext.minProperties, 3)
XCTAssertEqual(Set(attributesContext.requiredProperties), Set(["stringProperty", "enumProperty", "nullableProperty"]))
XCTAssertEqual(Set(attributesContext.properties.keys), Set(["stringProperty", "enumProperty", "optionalProperty", "nullableProperty", "nullableOptionalProperty"]))
XCTAssertEqual(attributesContext.properties["stringProperty"],
.string(.init(format: .generic,
required: true),
.init()))
XCTAssertEqual(attributesContext.properties["enumProperty"],
.string(.init(format: .generic,
required: true,
nullable: false,
allowedValues: ["one", "two"].map(AnyCodable.init)),
.init()))
XCTAssertEqual(attributesContext.properties["optionalProperty"],
.string(.init(format: .generic,
required: false,
nullable: false,
allowedValues: nil),
.init()))
XCTAssertEqual(attributesContext.properties["nullableProperty"],
.string(.init(format: .generic,
required: true,
nullable: true,
allowedValues: nil),
.init()))
XCTAssertEqual(attributesContext.properties["nullableOptionalProperty"],
.string(.init(format: .generic,
required: false,
nullable: true,
allowedValues: nil),
.init()))
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
@@ -21,15 +124,125 @@ class JSONAPIEntityOpenAPITests: XCTestCase {
print(string)
}
func test_AttributesEntity() {
let node = try! TestType2.openAPINode()
func test_RelationshipsEntity() {
let node = try! TestType3.openAPINode()
// TODO: Write test
XCTAssertTrue(node.required)
XCTAssertEqual(node.jsonTypeFormat, .object(.generic))
guard case let .object(contextA, objectContext1) = node else {
XCTFail("Expected Object node")
return
}
XCTAssertEqual(contextA, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(objectContext1.minProperties, 3)
XCTAssertEqual(Set(objectContext1.requiredProperties), Set(["id", "type", "relationships"]))
XCTAssertEqual(Set(objectContext1.properties.keys), Set(["id", "type", "relationships"]))
XCTAssertEqual(objectContext1.properties["id"], .string(.init(format: .generic,
required: true),
.init()))
XCTAssertEqual(objectContext1.properties["type"], .string(.init(format: .generic,
required: true),
.init()))
let relationshipsNode = objectContext1.properties["relationships"]
XCTAssertNotNil(relationshipsNode)
XCTAssertTrue(relationshipsNode?.required ?? false)
XCTAssertEqual(relationshipsNode?.jsonTypeFormat, .object(.generic))
guard case let .object(contextB, relationshipsContext)? = relationshipsNode else {
XCTFail("Expected Object node for relationships")
return
}
XCTAssertEqual(contextB, .init(format: .generic,
required: true,
nullable: false,
allowedValues: nil))
XCTAssertEqual(relationshipsContext.minProperties, 3)
XCTAssertEqual(Set(relationshipsContext.requiredProperties), Set(["toOne", "nullableToOne", "toMany"]))
XCTAssertEqual(Set(relationshipsContext.properties.keys), Set(["toOne", "optionalTooOne", "nullableToOne", "nullableOptionalToOne", "toMany", "optionalToMany"]))
let pointerDataContext = JSONNode.ObjectContext(properties: ["id": .string(.init(format: .generic,
required: true),
.init()),
"type": .string(.init(format: .generic,
required: true),
.init())])
let pointerContext = JSONNode.ObjectContext(properties: ["data": .object(.init(format: .generic,
required: true),
pointerDataContext)])
let nullablePointerContext = JSONNode.ObjectContext(properties: ["data": .object(.init(format: .generic,
required: true,
nullable: true),
pointerDataContext)])
let manyPointerContext = JSONNode.ObjectContext(properties: ["data": .array(.init(format: .generic,
required: true),
.init(items: .object(.init(format: .generic,
required: true),
pointerDataContext)))])
XCTAssertEqual(relationshipsContext.properties["toOne"],
.object(.init(format: .generic,
required: true),
pointerContext))
XCTAssertEqual(relationshipsContext.properties["optionalTooOne"],
.object(.init(format: .generic,
required: false,
nullable: false,
allowedValues: nil),
pointerContext))
XCTAssertEqual(relationshipsContext.properties["nullableToOne"],
.object(.init(format: .generic,
required: true,
nullable: false,
allowedValues: nil),
nullablePointerContext))
XCTAssertEqual(relationshipsContext.properties["nullableOptionalToOne"],
.object(.init(format: .generic,
required: false,
nullable: false,
allowedValues: nil),
nullablePointerContext))
XCTAssertEqual(relationshipsContext.properties["toMany"],
.object(.init(format: .generic,
required: true),
manyPointerContext))
XCTAssertEqual(relationshipsContext.properties["optionalToMany"],
.object(.init(format: .generic,
required: false,
nullable: false,
allowedValues: nil),
manyPointerContext))
}
func test_AttributesAndRelationshipsEntity() {
// TODO: write test
/*
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let string = String(data: try! encoder.encode(node), encoding: .utf8)!
print(string)
*/
}
}
@@ -46,7 +259,7 @@ extension JSONAPIEntityOpenAPITests {
typealias TestType1 = BasicEntity<TestType1Description>
enum TestType2Description: EntityDescription {
public static var jsonType: String { return "test1" }
public static var jsonType: String { return "test2" }
public enum EnumType: String, CaseIterable, Codable, Equatable {
case one
@@ -56,13 +269,19 @@ extension JSONAPIEntityOpenAPITests {
public struct Attributes: JSONAPI.Attributes, Sampleable {
let stringProperty: Attribute<String>
let enumProperty: Attribute<EnumType>
let optionalProperty: Attribute<String>?
let nullableProperty: Attribute<String?>
let nullableOptionalProperty: Attribute<String?>?
var computedProperty: Attribute<EnumType> {
return enumProperty
}
public static var sample: Attributes {
return Attributes(stringProperty: .init(value: "hello"),
enumProperty: .init(value: .one))
enumProperty: .init(value: .one),
optionalProperty: nil,
nullableProperty: .init(value: nil),
nullableOptionalProperty: nil)
}
}
@@ -70,4 +289,33 @@ extension JSONAPIEntityOpenAPITests {
}
typealias TestType2 = BasicEntity<TestType2Description>
enum TestType3Description: EntityDescription {
public static var jsonType: String { return "test3" }
public typealias Attributes = NoAttributes
public struct Relationships: JSONAPI.Relationships, Sampleable {
public let toOne: ToOneRelationship<TestType1, NoMetadata, NoLinks>
public let optionalTooOne: ToOneRelationship<TestType1, NoMetadata, NoLinks>?
public let nullableToOne: ToOneRelationship<TestType1?, NoMetadata, NoLinks>
public let nullableOptionalToOne: ToOneRelationship<TestType1?, NoMetadata, NoLinks>?
public let toMany: ToManyRelationship<TestType1, NoMetadata, NoLinks>
public let optionalToMany: ToManyRelationship<TestType1, NoMetadata, NoLinks>?
// Note there is no such thing as nullable to-many relationships (Just use
// an empty array)
public static var sample: Relationships {
return Relationships(toOne: .init(id: .init(rawValue: "1")),
optionalTooOne: nil,
nullableToOne: .init(id: nil),
nullableOptionalToOne: nil,
toMany: .init(ids: [.init(rawValue: "1")]),
optionalToMany: nil)
}
}
}
typealias TestType3 = BasicEntity<TestType3Description>
}
@@ -32,8 +32,10 @@ extension JSONAPIAttributeOpenAPITests {
extension JSONAPIEntityOpenAPITests {
static let __allTests = [
("test_AttributesAndRelationshipsEntity", test_AttributesAndRelationshipsEntity),
("test_AttributesEntity", test_AttributesEntity),
("test_EmptyEntity", test_EmptyEntity),
("test_RelationshipsEntity", test_RelationshipsEntity),
]
}