@testable import PureXML import Testing @Suite("HTML tokenizer: references, NUL, RCDATA") struct HTMLTokenizerTests { /// The concatenated text content of the first parsed element. private func text(_ html: String) -> String { guard case let .document(children) = PureXML.HTML.parse(html), case let .element(element) = children.first else { return "" } return element.children.compactMap { if case let .text(value) = $0 { value } else { nil } }.joined() } @Test("A numeric reference to zero, a surrogate, or an out-of-range value yields U+FFFD") func test_numericInvalid() { #expect(text("

�

") == "\u{FFFD}") #expect(text("

�

") == "\u{FFFD}") #expect(text("

�

") == "\u{FFFD}") } @Test("A numeric reference in the C1 range is mapped to its Windows-1252 character") func test_numericC1() { #expect(text("

€

") == "\u{20AC}") // euro #expect(text("

™

") == "\u{2122}") // trade mark } @Test("A valid numeric reference resolves to its code point") func test_numericValid() { #expect(text("

AB

") == "AB") } @Test("A literal NUL byte becomes U+FFFD") func test_nullReplacement() { #expect(text("

a\u{0}b

") == "a\u{FFFD}b") } @Test("A named reference without a trailing semicolon is still decoded") func test_semicolonless() { #expect(text("

&

") == "&") #expect(text("

©

") == "\u{A9}") } @Test("RCDATA content (title, textarea) decodes references; raw text (style) does not") func test_rcdataDecoding() { #expect(text("a & b") == "a & b") #expect(text("") == "") #expect(text("") == "a & b") } @Test("A single leading newline after ") == "hello") #expect(text("") == "\nhello") } }