1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
@testable import Grain
import XCTest
final class AnyCodableTests: GrainTestCase {
private let encoder = JSONEncoder()
private let decoder = JSONDecoder()
// MARK: - Init variants
func testInitWithString() throws {
let value = AnyCodable("hello")
let data = try encoder.encode(value)
let json = try XCTUnwrap(String(data: data, encoding: .utf8))
XCTAssertEqual(json, "\"hello\"")
}
func testInitWithInt() throws {
let value = AnyCodable(42)
let data = try encoder.encode(value)
let json = try XCTUnwrap(String(data: data, encoding: .utf8))
XCTAssertEqual(json, "42")
}
func testInitWithBool() throws {
let value = AnyCodable(true)
let data = try encoder.encode(value)
let json = try XCTUnwrap(String(data: data, encoding: .utf8))
XCTAssertEqual(json, "true")
}
func testInitWithDouble() throws {
let value = AnyCodable(3.14)
let data = try encoder.encode(value)
let decoded = try decoder.decode(AnyCodable.self, from: data)
// Round-trip through JSON, re-encode to verify
let reEncoded = try XCTUnwrap(try String(data: encoder.encode(decoded), encoding: .utf8))
XCTAssertTrue(reEncoded.contains("3.14"))
}
func testInitWithStringDict() throws {
let value = AnyCodable(["key": "value"] as [String: String])
let data = try encoder.encode(value)
let json = try XCTUnwrap(String(data: data, encoding: .utf8))
XCTAssertTrue(json.contains("\"key\""))
XCTAssertTrue(json.contains("\"value\""))
}
func testInitWithUnknownTypeFallsToNull() throws {
let value = AnyCodable(Date())
let data = try encoder.encode(value)
let json = try XCTUnwrap(String(data: data, encoding: .utf8))
XCTAssertEqual(json, "null")
}
// MARK: - Decoding from JSON
func testDecodeNull() throws {
let json = Data("null".utf8)
let value = try decoder.decode(AnyCodable.self, from: json)
// Re-encode should produce null
let reEncoded = try XCTUnwrap(try String(data: encoder.encode(value), encoding: .utf8))
XCTAssertEqual(reEncoded, "null")
}
func testDecodeString() throws {
let json = Data("\"test\"".utf8)
let value = try decoder.decode(AnyCodable.self, from: json)
let reEncoded = try XCTUnwrap(try String(data: encoder.encode(value), encoding: .utf8))
XCTAssertEqual(reEncoded, "\"test\"")
}
func testDecodeArray() throws {
let json = Data("[1,2,3]".utf8)
let value = try decoder.decode(AnyCodable.self, from: json)
let reEncoded = try XCTUnwrap(try String(data: encoder.encode(value), encoding: .utf8))
XCTAssertEqual(reEncoded, "[1,2,3]")
}
func testDecodeNestedDict() throws {
let json = Data("""
{"outer": {"inner": "value"}}
""".utf8)
let value = try decoder.decode(AnyCodable.self, from: json)
XCTAssertNotNil(value.dictValue)
XCTAssertNotNil(value.dictValue?["outer"]?.dictValue)
}
// MARK: - dictValue
func testDictValueReturnsNilForNonDict() {
let value = AnyCodable("not a dict")
XCTAssertNil(value.dictValue)
}
func testDictValueReturnsDictForDict() {
let value = AnyCodable(["key": AnyCodable("val")])
XCTAssertNotNil(value.dictValue)
XCTAssertEqual(value.dictValue?.count, 1)
}
}