@testable import PureXML import Testing @Suite("Writer") struct WriterTests { @Test("Compact writing escapes content and round-trips through the parser") func test_compactRoundTrip() throws { var writer = PureXML.Emitting.Writer(options: .compact) writer.writeStartElement("catalog") writer.writeStartElement("book") writer.writeAttribute("id", "bk101") writer.writeString("A & B < C") writer.writeEndElement() writer.writeEndElement() let xml = writer.output #expect(xml == "A & B < C") let node = try PureXML.parse(xml) let book = node.firstElement?.children.first?.element #expect(book?.attributes.first?.value == "bk101") #expect(book?.text == "A & B < C") } @Test("Pretty writing indents element children, inlines text") func test_pretty() { var writer = PureXML.Emitting.Writer() writer.writeStartElement("book") writer.writeElement("title", text: "Guide") writer.writeEndElement() #expect(writer.output == "\n Guide\n") } @Test("An empty element self-closes") func test_emptyElement() { var writer = PureXML.Emitting.Writer(options: .compact) writer.writeStartElement("br") writer.writeEndElement() #expect(writer.output == "
") } @Test("CDATA, comments, and processing instructions are written") func test_miscNodes() { var writer = PureXML.Emitting.Writer(options: .compact) writer.writeStartElement("r") writer.writeCData("a") } @Test("Writer output matches the tree serializer for the same document") func test_parityWithSerializer() { let element = PureXML.Model.Element( "a", attributes: [.init("x", "1\n2")], children: [.element(.init("b", children: [.text("hi")]))], ) let serialized = PureXML.serialize(.element(element), options: .compact) var writer = PureXML.Emitting.Writer(options: .compact) writer.writeStartElement("a") writer.writeAttribute("x", "1\n2") writer.writeStartElement("b") writer.writeString("hi") writer.writeEndElement() writer.writeEndElement() #expect(writer.output == serialized) } @Test("Misuse is forgiving: late attribute and unbalanced close are ignored") func test_forgiving() { var writer = PureXML.Emitting.Writer(options: .compact) writer.writeStartElement("a") writer.writeString("x") writer.writeAttribute("ignored", "y") // after content: ignored writer.writeEndElement() writer.writeEndElement() // unbalanced: ignored #expect(writer.output == "x") } } private extension PureXML.Model.Node { var firstElement: PureXML.Model.Element? { guard case let .document(children) = self else { return element } for child in children where child.element != nil { return child.element } return nil } }