Skip to content

Commit

Permalink
Merge pull request #19 from mattpolzin/add-to-compat-suite
Browse files Browse the repository at this point in the history
Add to compat suite
  • Loading branch information
mattpolzin authored Feb 18, 2020
2 parents 96ba674 + 3ab8709 commit 02bf3f4
Show file tree
Hide file tree
Showing 5 changed files with 232 additions and 46 deletions.
10 changes: 9 additions & 1 deletion Sources/OpenAPIKit/Schema Object/SchemaObjectContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,15 @@ extension JSONSchema.Context: Decodable {

deprecated = try container.decodeIfPresent(Bool.self, forKey: .deprecated) ?? false

example = try container.decodeIfPresent(String.self, forKey: .example)
if let decodedExample = try container.decodeIfPresent(AnyCodable.self, forKey: .example) {
if let fragment = decodedExample.value as? String {
example = fragment
} else {
example = try String(data: JSONEncoder().encode(decodedExample), encoding: .utf8)!
}
} else {
example = nil
}
}
}

Expand Down
20 changes: 14 additions & 6 deletions Sources/OpenAPIKit/Schema Object/TypesAndFormats.swift
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,23 @@ extension JSONTypeFormat {
}

extension JSONTypeFormat.StringFormat {
public enum Extended {
public static let uuid: JSONTypeFormat.StringFormat = .other("uuid")
public static let email: JSONTypeFormat.StringFormat = .other("email")
public enum Extended: String, Equatable {
case uuid = "uuid"
case email = "email"
}

public static func extended(_ format: Extended) -> Self {
return .other(format.rawValue)
}
}

extension JSONTypeFormat.IntegerFormat {
public enum Extended {
public static let uint32: JSONTypeFormat.IntegerFormat = .other("uint32")
public static let uint64: JSONTypeFormat.IntegerFormat = .other("uint64")
public enum Extended: String, Equatable {
case uint32 = "uint32"
case uint64 = "uint64"
}

public static func extended(_ format: Extended) -> Self {
return .other(format.rawValue)
}
}
13 changes: 0 additions & 13 deletions Tests/OpenAPIKitCompatibilitySuite/GoogleBooksAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,6 @@ import Foundation
import FoundationNetworking
#endif

/*

Currently failing to parse because OpenAPIKit lacks support for JSON references.

Is it worth failing to parse this? sometimes, yeah, it would be good to know if you were accidentally publishing
an empty server URL when you meant to publish one.

failed - The data couldn’t be read because it isn’t in the correct format.
coding path: servers -> Index 0 -> url
debug description: Invalid URL string.

*/

final class GoogleBooksAPICampatibilityTests: XCTestCase {
var booksAPI: Result<OpenAPI.Document, Error>? = nil
var apiDoc: OpenAPI.Document? {
Expand Down
113 changes: 113 additions & 0 deletions Tests/OpenAPIKitCompatibilitySuite/TomTomAPI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// TomTomAPI.swift
//
//
// Created by Mathew Polzin on 2/17/20.
//

import XCTest
import OpenAPIKit
import Yams
import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

final class TomTomAPICampatibilityTests: XCTestCase {
var tomtomAPI: Result<OpenAPI.Document, Error>? = nil
var apiDoc: OpenAPI.Document? {
guard case .success(let document) = tomtomAPI else { return nil }
return document
}

override func setUp() {
if tomtomAPI == nil {
tomtomAPI = Result {
try YAMLDecoder().decode(
OpenAPI.Document.self,
from: String(contentsOf: URL(string: "https://raw.githubusercontent.com/APIs-guru/openapi-directory/c9190db19e5cb151592d44f0d4482839e1e5a8e0/APIs/tomtom.com/search/1.0.0/openapi.yaml")!)
)
}
}
}

func test_successfullyParsedDocument() {
switch tomtomAPI {
case nil:
XCTFail("Did not attempt to pull Google Books API documentation like expected.")
case .failure(let error as DecodingError):
let codingPath: String
let debugDetails: String
let underlyingError: String
switch error {
case .dataCorrupted(let context), .keyNotFound(_, let context), .typeMismatch(_, let context), .valueNotFound(_, let context):
codingPath = context.codingPath.map { $0.stringValue }.joined(separator: " -> ")
debugDetails = context.debugDescription
underlyingError = context.underlyingError.map { "\n underlying error: " + String(describing: $0) } ?? ""
@unknown default:
codingPath = ""
debugDetails = ""
underlyingError = ""
}
XCTFail(error.failureReason ?? error.errorDescription ?? error.localizedDescription + "\n coding path: " + codingPath + "\n debug description: " + debugDetails + underlyingError)
case .failure(let error):
XCTFail(error.localizedDescription)
case .success:
break
}
}

func test_successfullyParsedBasicMetadata() {
guard let apiDoc = apiDoc else { return }

// title is Search
XCTAssertEqual(apiDoc.info.title, "Search")

// description is set
XCTAssertFalse(apiDoc.info.description?.isEmpty ?? true)

// contact name is "Contact Us"
XCTAssertEqual(apiDoc.info.contact?.name, "Contact Us")

// no contact email is provided
XCTAssert(apiDoc.info.contact?.email?.isEmpty ?? true)

// server is specified
XCTAssertNotNil(apiDoc.servers.first)
}

func test_successfullyParsedRoutes() {
guard let apiDoc = apiDoc else { return }

// just check for a few of the known paths
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/additionalData.{ext}"))
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/cS/{category}.{ext}"))
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/categorySearch/{query}.{ext}"))
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/geocode/{query}.{ext}"))
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/geometryFilter.{ext}"))
XCTAssert(apiDoc.paths.contains(key: "/search/{versionNumber}/geometrySearch/{query}.{ext}"))

// check for a known POST response
XCTAssertNotNil(apiDoc.paths["/search/{versionNumber}/geometrySearch/{query}.{ext}"]?.post?.responses[200 as OpenAPI.Response.StatusCode])

// and a known GET response
XCTAssertNotNil(apiDoc.paths["/search/{versionNumber}/geometrySearch/{query}.{ext}"]?.get?.responses[200 as OpenAPI.Response.StatusCode])

// check for parameters
XCTAssertFalse(apiDoc.paths["/search/{versionNumber}/geometrySearch/{query}.{ext}"]?.get?.parameters.isEmpty ?? true)
}

func test_successfullyParsedComponents() {
guard let apiDoc = apiDoc else { return }

// check for a known parameter
XCTAssertNotNil(apiDoc.components.parameters["btmRight"])
XCTAssertTrue(apiDoc.components.parameters["btmRight"]?.parameterLocation.inQuery ?? false)

// check for known response
XCTAssertNotNil(apiDoc.components.responses["200"])

// check for known security scheme
XCTAssertNotNil(apiDoc.components.securitySchemes["api_key"])
}
}
Loading

0 comments on commit 02bf3f4

Please sign in to comment.