import Testing
@testable import PureXML
@Suite("Push parser")
struct PushParserTests {
/// Feeds the chunks through a push parser and returns a flat list of event
/// descriptions.
private func collect(_ chunks: [String]) throws -> [String] {
var events: [String] = []
let handler = PureXML.Parsing.SAXHandler(
startElement: { name, attributes in
let attrs = attributes.map { " \($0.name.description)=\($0.value)" }.joined()
events.append("start:\(name.description)\(attrs)")
},
endElement: { events.append("end:\($0.description)") },
characters: { events.append("text:\($0)") },
cdata: { events.append("cdata:\($0)") },
comment: { events.append("comment:\($0)") },
processingInstruction: { events.append("pi:\($0):\($1)") },
)
var parser = PureXML.Parsing.PushParser(sax: handler)
for chunk in chunks {
try parser.feed(chunk)
}
try parser.finish()
return events
}
private let document = ""
+ "hi & byetail"
@Test("A whole document produces the expected events")
func test_whole() throws {
#expect(try collect([document]) == [
"start:root a=1 xmlns:n=urn:x",
"start:n:b",
"text:hi & bye",
"end:n:b",
"comment: c ",
"cdata:x",
"",
"",
"",
"a < b",
]
for fragment in cases {
let whole = try collect([fragment])
let mid = fragment.index(fragment.startIndex, offsetBy: fragment.count / 2)
let parts = [String(fragment[..", "- a
", "- b
", ""]
let stream = AsyncStream { continuation in
for chunk in chunks {
continuation.yield(chunk)
}
continuation.finish()
}
var names: [String] = []
for try await event in PureXML.events(feeding: stream) {
if case let .startElement(name, _) = event { names.append(name.description) }
}
#expect(names == ["doc", "item", "item"])
}
}