Files
JSONAPI/Tests/JSONAPIOpenAPITests/JSONAPIEntityOpenAPITests.swift
T
2019-01-26 18:55:47 -08:00

365 lines
12 KiB
Swift

//
// JSONAPIEntityOpenAPITests.swift
// JSONAPIOpenAPITests
//
// Created by Mathew Polzin on 1/15/19.
//
import XCTest
import JSONAPI
import JSONAPIOpenAPI
import AnyCodable
class JSONAPIEntityOpenAPITests: XCTestCase {
func test_EmptyEntity() {
let node = try! TestType1.openAPINode(using: JSONEncoder())
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,
allowedValues: [.init(TestType1.jsonType)]),
.init()))
}
func test_UnidentifiedEmptyEntity() {
let node = try! UnidentifiedTestType1.openAPINode(using: JSONEncoder())
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, 1)
XCTAssertEqual(Set(objectContext1.requiredProperties), Set(["type"]))
XCTAssertEqual(Set(objectContext1.properties.keys), Set(["type"]))
XCTAssertEqual(objectContext1.properties["type"], .string(.init(format: .generic,
required: true,
allowedValues: [.init(TestType1.jsonType)]),
.init()))
}
func test_AttributesEntity() {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .short
dateFormatter.locale = Locale(identifier: "en_US")
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .formatted(dateFormatter)
let node = try! TestType2.openAPINode(using: encoder)
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,
allowedValues: [.init(TestType2.jsonType)]),
.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, 4)
XCTAssertEqual(Set(attributesContext.requiredProperties), Set(["stringProperty", "enumProperty", "dateProperty", "nullableProperty"]))
XCTAssertEqual(Set(attributesContext.properties.keys), Set(["stringProperty", "enumProperty", "dateProperty", "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["dateProperty"],
.string(.init(format: .dateTime,
required: true,
nullable: false,
allowedValues: nil),
.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()))
}
func test_RelationshipsEntity() {
let node = try! TestType3.openAPINode(using: JSONEncoder())
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,
allowedValues: [.init(TestType3.jsonType)]),
.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,
allowedValues: [.init(TestType1.jsonType)]),
.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)
*/
}
}
// MARK: Test Types
extension JSONAPIEntityOpenAPITests {
enum TestType1Description: EntityDescription {
public static var jsonType: String { return "test1" }
public typealias Attributes = NoAttributes
public typealias Relationships = NoRelationships
}
typealias TestType1 = BasicEntity<TestType1Description>
typealias UnidentifiedTestType1 = JSONAPI.Entity<TestType1Description, NoMetadata, NoLinks, Unidentified>
enum TestType2Description: EntityDescription {
public static var jsonType: String { return "test2" }
public enum EnumType: String, CaseIterable, Codable, Equatable {
case one
case two
}
public struct Attributes: JSONAPI.Attributes, Sampleable {
let stringProperty: Attribute<String>
let enumProperty: Attribute<EnumType>
let dateProperty: Attribute<Date>
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),
dateProperty: .init(value: Date()),
optionalProperty: nil,
nullableProperty: .init(value: nil),
nullableOptionalProperty: nil)
}
}
public typealias Relationships = NoRelationships
}
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>
}