-
Notifications
You must be signed in to change notification settings - Fork 104
/
NestedAttributeChoiceTests.swift
144 lines (127 loc) · 3.83 KB
/
NestedAttributeChoiceTests.swift
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// NestedAttributeChoiceTests.swift
// XMLCoderTests
//
// Created by Benjamin Wetherfield on 7/23/19.
//
import XCTest
import XMLCoder
private struct Container: Equatable {
let paragraphs: [Paragraph]
}
private struct Paragraph: Equatable {
let entries: [Entry]
}
private enum Entry: Equatable {
case run(Run)
case properties(Properties)
case br(Break)
}
private struct Run: Codable, Equatable, DynamicNodeEncoding {
let id: Int
let text: String
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
switch key {
case CodingKeys.id:
return .attribute
default:
return .element
}
}
}
private struct Properties: Codable, Equatable, DynamicNodeEncoding {
let id: Int
let title: String
static func nodeEncoding(for key: CodingKey) -> XMLEncoder.NodeEncoding {
return .attribute
}
}
private struct Break: Codable, Equatable {}
extension Container: Codable {
enum CodingKeys: String, CodingKey {
case paragraphs = "p"
}
}
extension Paragraph: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
entries = try container.decode([Entry].self)
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(entries)
}
}
extension Entry: Codable {
private enum CodingKeys: String, XMLChoiceCodingKey {
case run, properties, br
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
self = .run(try container.decode(Run.self, forKey: .run))
} catch {
do {
self = .properties(try container.decode(Properties.self, forKey: .properties))
} catch {
self = .br(try container.decode(Break.self, forKey: .br))
}
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .run(value):
try container.encode(value, forKey: .run)
case let .properties(value):
try container.encode(value, forKey: .properties)
case let .br(value):
try container.encode(value, forKey: .br)
}
}
}
final class NestedAttributeChoiceTests: XCTestCase {
private var encoder: XMLEncoder {
let encoder = XMLEncoder()
encoder.outputFormatting = [.prettyPrinted]
return encoder
}
func testNestedEnumsEncoding() throws {
let xml = """
<container>
<p>
<br />
<run id="1518">
<text>I am answering it again.</text>
</run>
<properties id="431" title="A Word About Wake Times" />
</p>
<p>
<run id="1519">
<text>I am answering it again.</text>
</run>
<br />
</p>
</container>
"""
let value = Container(
paragraphs: [
Paragraph(
entries: [
.br(Break()),
.run(Run(id: 1518, text: "I am answering it again.")),
.properties(Properties(id: 431, title: "A Word About Wake Times")),
]
),
Paragraph(
entries: [
.run(Run(id: 1519, text: "I am answering it again.")),
.br(Break()),
]
),
]
)
let encoded = try encoder.encode(value, withRootKey: "container")
XCTAssertEqual(String(data: encoded, encoding: .utf8), xml)
}
}