import Testing @testable import PureXML @Suite("Serializer") struct SerializerTests { @Test("Empty element self-closes") func test_emptyElementSelfCloses() { let node = PureXML.Model.Node.element(.init("br")) #expect(PureXML.serialize(node, options: .compact) == "
") } @Test("A ?> inside processing-instruction data is split by a space") func test_processingInstructionEscapesTerminator() { // PI data may not contain ?>; the XSLT 1.0 7.3 recovery inserts a space // (Apache Xalan output72). A trailing ? is safe and is left alone. let instruction = PureXML.Model.Node.processingInstruction(target: "p", data: "a ?> b ?") #expect(PureXML.serialize(instruction, options: .compact) == " b ??>") } @Test("Attributes and text are escaped") func test_escapesAttributesAndText() { let element = PureXML.Model.Element( "a", attributes: [.init("href", "x?b=1&c=2")], children: [.text("1 < 2")], ) let xml = PureXML.serialize(.element(element), options: .compact) #expect(xml == "1 < 2") } @Test("Attribute whitespace is escaped as numeric character references") func test_escapesAttributeWhitespace() { // libxml2 escapes tab/newline/CR in attribute values so they survive a // spec-compliant parser's attribute-value normalization. let element = PureXML.Model.Element("a", attributes: [.init("x", "1\t2\n3\r4>5")]) let xml = PureXML.serialize(.element(element), options: .compact) #expect(xml == "") } @Test("Pretty printing indents nested elements") func test_prettyPrintsNested() { let inner = PureXML.Model.Element("title", children: [.text("Guide")]) let outer = PureXML.Model.Element("book", children: [.element(inner)]) let xml = PureXML.serialize(.element(outer)) #expect(xml == "\n Guide\n\n") } @Test("Mixed content is emitted inline, not reformatted") func test_mixedContentStaysInline() { // Pretty-printing must not inject whitespace around text in mixed content. let element = PureXML.Model.Element( "p", children: [.text("hi "), .element(.init("b", children: [.text("x")])), .text(" bye")], ) let xml = PureXML.serialize(.element(element)) #expect(xml == "

hi x bye

\n") } @Test("Nested trees serialize iteratively and correctly") func test_nestedSerializesCorrectly() { // The serializer uses an explicit work stack (not recursion), so it is // not the depth bottleneck. The remaining ceiling is the recursive // Model.Node value itself, which is why the parser caps nesting depth. var node = PureXML.Model.Node.text("leaf") for _ in 0 ..< 200 { node = .element(.init("n", children: [node])) } let xml = PureXML.serialize(node, options: .compact) #expect(xml.hasPrefix("")) #expect(xml.hasSuffix("")) #expect(xml.contains("leaf")) } @Test("CDATA and comments round-trip verbatim") func test_emitsCDATAAndComments() { #expect(PureXML.serialize(.cdata("a") #expect( PureXML.serialize(.processingInstruction(target: "xml-stylesheet", data: "href=\"s.css\"")) == "", ) } }