Skip to content

Commit 8328309

Browse files
committed
Build out vendor extendable tests
1 parent 8d246b9 commit 8328309

File tree

3 files changed

+201
-3
lines changed

3 files changed

+201
-3
lines changed

Sources/OpenAPIKit/VendorExtendable.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,36 @@ protocol VendorExtendable {
4343
}
4444

4545
enum VendorExtensionDecodingError: Swift.Error {
46+
case selfIsArrayNotDict
4647
case foundNonStringKeys
48+
case foundExtensionsWithoutXPrefix
4749
}
4850

4951
extension VendorExtendable {
5052

5153
public static func extensions(from decoder: Decoder) throws -> VendorExtensions {
52-
guard let decodedAny = (try AnyCodable(from: decoder)).value as? [String: Any] else {
54+
55+
let decoded = try AnyCodable(from: decoder).value
56+
57+
guard (decoded as? [Any]) == nil else {
58+
throw VendorExtensionDecodingError.selfIsArrayNotDict
59+
}
60+
61+
guard let decodedAny = decoded as? [String: Any] else {
5362
throw VendorExtensionDecodingError.foundNonStringKeys
5463
}
5564

56-
return decodedAny.filter {
65+
let extensions = decodedAny.filter {
5766
let key = CodingKeys.key(for: $0.key)
5867

5968
return !CodingKeys.allBuiltinKeys.contains(key)
60-
}.mapValues(AnyCodable.init)
69+
}
70+
71+
guard extensions.keys.allSatisfy({ $0.lowercased().starts(with: "x-") }) else {
72+
throw VendorExtensionDecodingError.foundExtensionsWithoutXPrefix
73+
}
74+
75+
return extensions.mapValues(AnyCodable.init)
6176
}
6277

6378
public func encodeExtensions<T: KeyedEncodingContainerProtocol>(to container: inout T) throws where T.Key == Self.CodingKeys {
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
//
2+
// VendorExtendableTests.swift
3+
//
4+
//
5+
// Created by Mathew Polzin on 11/3/19.
6+
//
7+
8+
import XCTest
9+
@testable import OpenAPIKit
10+
11+
final class VendorExtendableTests: XCTestCase {
12+
func test_decode() throws {
13+
let data =
14+
"""
15+
{
16+
"x-tension": "hello",
17+
"x-two": [ "cool", "beans" ],
18+
"x-three": {
19+
"nested": 10
20+
},
21+
"one": "world",
22+
"two": "!"
23+
}
24+
""".data(using: .utf8)!
25+
26+
let test = try JSONDecoder().decode(TestStruct.self, from: data)
27+
XCTAssertEqual(test.vendorExtensions.count, 3)
28+
29+
XCTAssertEqual(test.vendorExtensions["x-tension"]?.value as? String, "hello")
30+
31+
XCTAssert((test.vendorExtensions["x-two"]?.value as? [String])!.contains("cool"))
32+
XCTAssert((test.vendorExtensions["x-two"]?.value as? [String])!.contains("beans"))
33+
XCTAssertEqual((test.vendorExtensions["x-two"]?.value as? [String])?.count, 2)
34+
35+
XCTAssertEqual((test.vendorExtensions["x-three"]?.value as? [String: Int])?.count, 1)
36+
XCTAssertEqual((test.vendorExtensions["x-three"]?.value as? [String: Int])?["nested"], 10)
37+
}
38+
39+
func test_encodeSuccess() throws {
40+
let test = TestStruct(vendorExtensions: [
41+
"x-tension": "hello",
42+
"x-two": [
43+
"cool",
44+
"beans"
45+
],
46+
"x-three": [
47+
"nested": 10
48+
]
49+
])
50+
51+
let _ = try JSONEncoder().encode(test)
52+
}
53+
54+
func test_arrayDecodeFailure() {
55+
let data =
56+
"""
57+
[
58+
"cool",
59+
"beans"
60+
]
61+
""".data(using: .utf8)!
62+
63+
XCTAssertThrowsError(try JSONDecoder().decode(TestStruct.self, from: data)) { error in
64+
XCTAssert(error as? VendorExtensionDecodingError == VendorExtensionDecodingError.selfIsArrayNotDict)
65+
}
66+
}
67+
68+
func test_nonXPrefixDecodeFailure() {
69+
let data =
70+
"""
71+
{
72+
"x-tension": "hello",
73+
"invalid": "world"
74+
}
75+
""".data(using: .utf8)!
76+
77+
XCTAssertThrowsError(try JSONDecoder().decode(TestStruct.self, from: data)) { error in
78+
XCTAssert(error as? VendorExtensionDecodingError == VendorExtensionDecodingError.foundExtensionsWithoutXPrefix)
79+
}
80+
}
81+
}
82+
83+
@available(OSX 10.13, *)
84+
extension VendorExtendableTests {
85+
func test_encode() throws {
86+
let test = TestStruct(vendorExtensions: [
87+
"x-tension": "hello",
88+
"x-two": [
89+
"cool",
90+
"beans"
91+
],
92+
"x-three": [
93+
"nested": 10
94+
]
95+
])
96+
97+
let encoded = try testStringFromEncoding(of: test)
98+
99+
XCTAssertEqual(encoded,
100+
"""
101+
{
102+
"one" : "world",
103+
"two" : "!",
104+
"x-tension" : "hello",
105+
"x-three" : {
106+
"nested" : 10
107+
},
108+
"x-two" : [
109+
"cool",
110+
"beans"
111+
]
112+
}
113+
"""
114+
)
115+
}
116+
}
117+
118+
private struct TestStruct: Codable, VendorExtendable {
119+
enum CodingKeys: ExtendableCodingKey {
120+
case one
121+
case two
122+
case other(String)
123+
124+
static let allBuiltinKeys: [Self] = [.one, .two]
125+
126+
static func extendedKey(for value: String) -> Self {
127+
return .other(value)
128+
}
129+
130+
var stringValue: String {
131+
switch self {
132+
case .one: return "one"
133+
case .two: return "two"
134+
case .other(let val): return val
135+
}
136+
}
137+
138+
init?(stringValue: String) {
139+
switch stringValue {
140+
case "one": self = .one
141+
case "two": self = .two
142+
default: return nil
143+
}
144+
}
145+
146+
var intValue: Int? { return nil }
147+
148+
init?(intValue: Int) {
149+
return nil
150+
}
151+
}
152+
153+
public let vendorExtensions: Self.VendorExtensions
154+
155+
init(vendorExtensions: Self.VendorExtensions) {
156+
self.vendorExtensions = vendorExtensions
157+
}
158+
159+
public init(from decoder: Decoder) throws {
160+
vendorExtensions = try Self.extensions(from: decoder)
161+
}
162+
163+
public func encode(to encoder: Encoder) throws {
164+
var container = encoder.container(keyedBy: CodingKeys.self)
165+
try container.encode("world", forKey: .one)
166+
try container.encode("!", forKey: .two)
167+
try encodeExtensions(to: &container)
168+
}
169+
}

Tests/OpenAPIKitTests/XCTestManifests.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,19 @@ extension TagTests {
348348
]
349349
}
350350

351+
extension VendorExtendableTests {
352+
// DO NOT MODIFY: This is autogenerated, use:
353+
// `swift test --generate-linuxmain`
354+
// to regenerate.
355+
static let __allTests__VendorExtendableTests = [
356+
("test_arrayDecodeFailure", test_arrayDecodeFailure),
357+
("test_decode", test_decode),
358+
("test_encode", test_encode),
359+
("test_encodeSuccess", test_encodeSuccess),
360+
("test_nonXPrefixDecodeFailure", test_nonXPrefixDecodeFailure),
361+
]
362+
}
363+
351364
public func __allTests() -> [XCTestCaseEntry] {
352365
return [
353366
testCase(AnyJSONCaseIterableTests.__allTests__AnyJSONCaseIterableTests),
@@ -365,6 +378,7 @@ public func __allTests() -> [XCTestCaseEntry] {
365378
testCase(ServerTests.__allTests__ServerTests),
366379
testCase(SwiftPrimitiveTypesTests.__allTests__SwiftPrimitiveTypesTests),
367380
testCase(TagTests.__allTests__TagTests),
381+
testCase(VendorExtendableTests.__allTests__VendorExtendableTests),
368382
]
369383
}
370384
#endif

0 commit comments

Comments
 (0)