import Testing
@testable import PureXML
@Suite("XInclude content negotiation, cycle detection, text+fragment")
struct XIncludeNegotiationTests {
private func roots(_ node: PureXML.Model.Node) -> [PureXML.Model.Element] {
guard case let .document(children) = node else { return [] }
return children.compactMap(\.element)
}
@Test("accept, accept-language, and encoding are surfaced to the loader")
func test_requestHints() throws {
let xml = """
"""
var seen: PureXML.XInclude.XIncludeRequest?
_ = try PureXML.XInclude.process(xml, loading: { request in
seen = request
return "loaded"
})
#expect(seen?.uri == "t.txt")
#expect(seen?.accept == "text/plain")
#expect(seen?.acceptLanguage == "fr")
#expect(seen?.encoding == "iso-8859-1")
#expect(seen?.isText == true)
}
@Test("A self-including resource is detected as a cycle")
func test_cycle() throws {
let selfInclude = """
"""
#expect(throws: PureXML.XInclude.XIncludeError.self) {
_ = try PureXML.XInclude.process(selfInclude, base: "a.xml", loadingURI: { _ in selfInclude })
}
}
@Test("A non-cyclic diamond include does not falsely trip cycle detection")
func test_diamondNotCycle() throws {
// root includes b and c; both include leaf. Same resource on two separate
// branches is not a cycle.
let leaf = ""
let xml = """
"""
let result = try PureXML.XInclude.process(xml, loadingURI: { $0 == "leaf.xml" ? leaf : nil })
#expect(roots(result).first?.children.compactMap(\.element).count == 2)
}
@Test("parse=text with an xpointer is rejected")
func test_textWithFragment() {
let xml = """
"""
#expect(throws: PureXML.XInclude.XIncludeError.textWithFragment) {
_ = try PureXML.XInclude.process(xml, loadingURI: { _ in "x" })
}
}
}