Skip to content

Commit b9019d9

Browse files
rboyceczechboy0
andauthored
Additional unit tests for OpenAPIObjectContainer (#24)
### Motivation Trying to encode an `OpenAPIValueContainer` would previously throw an `EncodingError` if the untyped container contained nested dictionary or array structures. (e.g. `{"dict": {"foo": "bar"}}`) Data could be decoded into this format, but it could not be re-encoded successfully. ### Modifications When encoding the value of a nested JSON array or object in `OpenAPIValueContainer`, we now handle arrays and dicts by wrapping the inner value in `OpenAPIValueContainer` before passing it to the encoder. (note: Based on the rest of the `encode()` implementation, it seems that this may have been expected to happen previously during decoding. Let me know if making changes on the decode side of things is preferable.) ### Result Additional unit tests added to validate that encoder generates correct output for nested data structures in `OpenAPIValueContainer`, and that these data structures can be decoded and successfully re-endcoded afterward. ### Test Plan Run `Test_CodableExtensions` tests, see all tests pass. Co-authored-by: Honza Dvorsky <[email protected]>
1 parent 08c12e1 commit b9019d9

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

Tests/OpenAPIRuntimeTests/Base/Test_OpenAPIValue.swift

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,4 +193,96 @@ final class Test_OpenAPIValue: Test_Runtime {
193193
XCTAssertEqual(value[0] as? String, "one")
194194
XCTAssertEqual(value[1] as? [String: Int], ["two": 2])
195195
}
196+
197+
func testEncoding_objectNested_success() throws {
198+
199+
struct Foo: Encodable {
200+
var bar: String
201+
var dict: OpenAPIObjectContainer = .init()
202+
}
203+
204+
do {
205+
let value = Foo(
206+
bar: "hi",
207+
dict: try .init(unvalidatedValue: [
208+
"baz": "bar",
209+
"number": 1,
210+
"nestedArray": [
211+
1,
212+
[
213+
"k": "v"
214+
],
215+
] as [(any Sendable)?],
216+
"nestedDict": [
217+
"nested": 2
218+
],
219+
])
220+
)
221+
let encoder: JSONEncoder = .init()
222+
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
223+
let data = try encoder.encode(value)
224+
XCTAssertEqual(
225+
String(decoding: data, as: UTF8.self),
226+
#"""
227+
{
228+
"bar" : "hi",
229+
"dict" : {
230+
"baz" : "bar",
231+
"nestedArray" : [
232+
1,
233+
{
234+
"k" : "v"
235+
}
236+
],
237+
"nestedDict" : {
238+
"nested" : 2
239+
},
240+
"number" : 1
241+
}
242+
}
243+
"""#
244+
)
245+
}
246+
}
247+
248+
func testDecodeEncodeRoundTrip_objectNested_success() throws {
249+
250+
struct Foo: Codable {
251+
var bar: String
252+
var dict: OpenAPIObjectContainer = .init()
253+
}
254+
255+
do {
256+
let data = Data(
257+
#"""
258+
{
259+
"bar" : "hi",
260+
"dict" : {
261+
"baz" : "bar",
262+
"nestedArray" : [
263+
1,
264+
{
265+
"k" : "v"
266+
}
267+
],
268+
"nestedDict" : {
269+
"nested" : 2
270+
},
271+
"number" : 1
272+
}
273+
}
274+
"""#
275+
.utf8
276+
)
277+
let decoded = try JSONDecoder().decode(Foo.self, from: data)
278+
let nestedDict = try XCTUnwrap(decoded.dict.value["nestedDict"] as? [String: Any?])
279+
let nestedValue = try XCTUnwrap(nestedDict["nested"] as? Int)
280+
XCTAssertEqual(nestedValue, 2)
281+
282+
let encoder: JSONEncoder = .init()
283+
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
284+
let encodedData = try encoder.encode(decoded)
285+
XCTAssertEqual(encodedData, data)
286+
}
287+
}
196288
}

0 commit comments

Comments
 (0)