Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 250 additions & 0 deletions Tests/XMLCoderTests/NestedChoiceTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
//
// NestedChoiceTests.swift
// XMLCoderTests
//
// Created by James Bean on 7/15/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 {
let id: Int
let text: String
}

private struct Properties: Codable, Equatable {
let id: Int
let title: String
}

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()
self.entries = try container.decode([Entry].self)
}

func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(entries)
}
}

extension Entry: XMLChoiceCodable {
private enum CodingKeys: String, CodingKey {
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 DecodingError.keyNotFound {
do {
self = .properties(try container.decode(Properties.self, forKey: .properties))
} catch DecodingError.keyNotFound {
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)
}
}
}

class NestedChoiceTests: XCTestCase {

func testBreakDecoding() throws {
let xml = "<br></br>"
let result = try XMLDecoder().decode(Break.self, from: xml.data(using: .utf8)!)
let expected = Break()
XCTAssertEqual(result, expected)
}

func testPropertiesDecoding() throws {
let xml = """
<properties>
<id>431</id>
<title>A Word About Wake Times</title>
</properties>
"""
let result = try XMLDecoder().decode(Properties.self, from: xml.data(using: .utf8)!)
let expected = Properties(id: 431, title: "A Word About Wake Times")
XCTAssertEqual(result, expected)
}

func testPropertiesAsEntryDecoding() throws {
let xml = """
<entry>
<properties>
<id>431</id>
<title>A Word About Wake Times</title>
</properties>
</entry>
"""
let result = try XMLDecoder().decode(Entry.self, from: xml.data(using: .utf8)!)
let expected: Entry = .properties(Properties(id: 431, title: "A Word About Wake Times"))
XCTAssertEqual(result, expected)
}

func testRunDecoding() throws {
let xml = """
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
"""
let result = try XMLDecoder().decode(Run.self, from: xml.data(using: .utf8)!)
let expected = Run(id: 1518, text: "I am answering it again.")
XCTAssertEqual(result, expected)
}

func testRunAsEntryDecoding() throws {
let xml = """
<entry>
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
</entry>
"""
let result = try XMLDecoder().decode(Entry.self, from: xml.data(using: .utf8)!)
let expected = Entry.run(Run(id: 1518, text: "I am answering it again."))
XCTAssertEqual(result, expected)
}

func testEntriesDecoding() throws {
let xml = """
<entries>
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
<properties>
<id>431</id>
<title>A Word About Wake Times</title>
</properties>
</entries>
"""
let result = try XMLDecoder().decode([Entry].self, from: xml.data(using: .utf8)!)
let expected: [Entry] = [
.run(Run(id: 1518, text: "I am answering it again.")),
.properties(Properties(id: 431, title: "A Word About Wake Times"))
]
XCTAssertEqual(result, expected)
}

func testParagraphDecoding() throws {
let xml = """
<p>
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
<properties>
<id>431</id>
<title>A Word About Wake Times</title>
</properties>
</p>
"""
let result = try XMLDecoder().decode(Paragraph.self, from: xml.data(using: .utf8)!)
let expected = Paragraph(
entries: [
.run(Run(id: 1518, text: "I am answering it again.")),
.properties(Properties(id: 431, title: "A Word About Wake Times"))
]
)
XCTAssertEqual(result, expected)
}

func testNestedEnums() throws {
let xml = """
<container>
<p>
<run>
<id>1518</id>
<text>I am answering it again.</text>
</run>
<properties>
<id>431</id>
<title>A Word About Wake Times</title>
</properties>
</p>
<p>
<run>
<id>1519</id>
<text>I am answering it again.</text>
</run>
</p>
</container>
"""
let result = try XMLDecoder().decode(Container.self, from: xml.data(using: .utf8)!)
let expected = Container(
paragraphs: [
Paragraph(
entries: [
.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.")),
]
)
]
)
XCTAssertEqual(result, expected)
}

func testNestedEnumsRoundTrip() throws {
let original = Container(
paragraphs: [
Paragraph(
entries: [
.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.")),
]
)
]
)
let encoded = try XMLEncoder().encode(original, withRootKey: "container")
let decoded = try XMLDecoder().decode(Container.self, from: encoded)
XCTAssertEqual(decoded, original)
}
}
4 changes: 4 additions & 0 deletions XMLCoder.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
1482D5A222DD2D9400AE2D6E /* SimpleChoiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1482D5A122DD2D9400AE2D6E /* SimpleChoiceTests.swift */; };
1482D5A422DD2F4D00AE2D6E /* CompositeChoiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1482D5A322DD2F4D00AE2D6E /* CompositeChoiceTests.swift */; };
1482D5A822DD6AEE00AE2D6E /* SingleElementBox.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1482D5A722DD6AED00AE2D6E /* SingleElementBox.swift */; };
1482D5AA22DD961E00AE2D6E /* NestedChoiceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1482D5A922DD961E00AE2D6E /* NestedChoiceTests.swift */; };
A61DCCD821DF9CA200C0A19D /* ClassTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61DCCD621DF8DB300C0A19D /* ClassTests.swift */; };
A61FE03921E4D60B0015D993 /* UnkeyedIntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61FE03721E4D4F10015D993 /* UnkeyedIntTests.swift */; };
A61FE03C21E4EAB10015D993 /* KeyedIntTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A61FE03A21E4EA8B0015D993 /* KeyedIntTests.swift */; };
Expand Down Expand Up @@ -155,6 +156,7 @@
1482D5A122DD2D9400AE2D6E /* SimpleChoiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleChoiceTests.swift; sourceTree = "<group>"; };
1482D5A322DD2F4D00AE2D6E /* CompositeChoiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompositeChoiceTests.swift; sourceTree = "<group>"; };
1482D5A722DD6AED00AE2D6E /* SingleElementBox.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SingleElementBox.swift; sourceTree = "<group>"; };
1482D5A922DD961E00AE2D6E /* NestedChoiceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NestedChoiceTests.swift; sourceTree = "<group>"; };
A61DCCD621DF8DB300C0A19D /* ClassTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClassTests.swift; sourceTree = "<group>"; };
A61FE03721E4D4F10015D993 /* UnkeyedIntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnkeyedIntTests.swift; sourceTree = "<group>"; };
A61FE03A21E4EA8B0015D993 /* KeyedIntTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyedIntTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -414,6 +416,7 @@
BF63EF1D21CEC99A001D38C5 /* BenchmarkTests.swift */,
1482D5A122DD2D9400AE2D6E /* SimpleChoiceTests.swift */,
1482D5A322DD2F4D00AE2D6E /* CompositeChoiceTests.swift */,
1482D5A922DD961E00AE2D6E /* NestedChoiceTests.swift */,
OBJ_28 /* BooksTest.swift */,
D1B6A2C02297EF5A005B8A6E /* BorderTest.swift */,
OBJ_29 /* BreakfastTest.swift */,
Expand Down Expand Up @@ -724,6 +727,7 @@
BF63EF0821CD7AF8001D38C5 /* URLBoxTests.swift in Sources */,
BF9457DD21CBB62C005ACFDE /* DateBoxTests.swift in Sources */,
A61DCCD821DF9CA200C0A19D /* ClassTests.swift in Sources */,
1482D5AA22DD961E00AE2D6E /* NestedChoiceTests.swift in Sources */,
BF9457CD21CBB516005ACFDE /* FloatBoxTests.swift in Sources */,
BF9457F621CBB6BC005ACFDE /* KeyedTests.swift in Sources */,
BF9457C821CBB516005ACFDE /* BoolBoxTests.swift in Sources */,
Expand Down