import Testing @testable import PureXML /// HTML5 depth conformance, driven through the validation framework (#119, the /// zone that produced #109): the spec-fidelity cases go through the document /// parser; the lenient-model cases through the fragment parser. @Suite("Conformance corpus: HTML depth") struct ConformanceHTMLDepthTests { /// The serialized body content of a full document parse. private func documentBody(_ html: String) -> String { let full = PureXML.HTML.serialize(PureXML.HTML.parseDocument(html)) let wrapper = "" guard full.hasPrefix(wrapper), full.hasSuffix("") else { return full } return String(full.dropFirst(wrapper.count).dropLast("".count)) } private func fragment(_ html: String) -> String { PureXML.HTML.serialize(PureXML.HTML.parse(html)) } private func corpus() -> [PureXML.Validation.ConformanceCase] { var cases: [PureXML.Validation.ConformanceCase] = [] func document(_ name: String, _ input: String, _ expected: String) { cases.append(.init(name: name, actual: documentBody(input), expected: expected)) } func lenient(_ name: String, _ input: String, _ expected: String) { cases.append(.init(name: name, actual: fragment(input), expected: expected)) } // The adoption agency's furthest-block path and the deep misnesting case. document("adoption-furthest-block", "1

23

", "1

23

") document("adoption-deep-misnesting", "

12345

", "

12345

") // Foster parenting: stray table content surfaces before the table, and // the tr gets its implied tbody (both per the HTML5 algorithm). document("foster-parented-text", "x
a
", "x
a
") // template keeps its flow content nested. document("template-content-nested", "", "") // Lenient fragment model: raw-text elements, implied closes. lenient("raw-text-script", "", "") lenient("implied-dt-dd-close", "
t
d
", "
t
d
") lenient("implied-cell-close", "
ab
", "
ab
") lenient("comment-kept-in-flow", "
x
", "
x
") return cases } @Test("The HTML depth corpus passes with no located failures") func test_htmlDepthCorpusConforms() { let failures = PureXML.Validation.Conformance.failures(in: corpus()) #expect(failures.isEmpty, "\(failures.map(\.reason))") } }