import Testing
@testable import PureXML
/// `validate(_:schemaLoader:)` honors an instance's `xsi:schemaLocation`,
/// loading the referenced schema documents so a strict (or lax) wildcard can
/// resolve elements declared in another document (#147, XSTS particles set).
@Suite("Multi-document validation via xsi:schemaLocation")
struct SchemaMultiDocumentTests {
private let mainXSD = """
"""
private let otherXSD = """
"""
private let instance = """
5
"""
@Test("A strict wildcard resolves an element from the xsi:schemaLocation schema")
func test_resolvesAcrossDocuments() throws {
let doc = try PureXML.Schema.Document(mainXSD)
let loader: (String) -> String? = { [otherXSD] in $0 == "other.xsd" ? otherXSD : nil }
#expect(try doc.validate(instance, schemaLoader: loader).isEmpty)
}
@Test("The loaded declaration's type is still enforced")
func test_loadedTypeEnforced() throws {
let doc = try PureXML.Schema.Document(mainXSD)
let loader: (String) -> String? = { [otherXSD] in $0 == "other.xsd" ? otherXSD : nil }
let bad = instance.replacingOccurrences(of: "5", with: "notint")
#expect(try !doc.validate(bad, schemaLoader: loader).isEmpty)
}
@Test("Without the loader a strict wildcard cannot resolve the element")
func test_strictUnresolvedWithoutLoader() throws {
let doc = try PureXML.Schema.Document(mainXSD)
#expect(try !doc.validate(instance).isEmpty)
}
@Test("Streaming validation honors xsi:schemaLocation the same as the tree path")
func test_streamingResolvesAcrossDocuments() throws {
let doc = try PureXML.Schema.Document(mainXSD)
let loader: (String) -> String? = { [otherXSD] in $0 == "other.xsd" ? otherXSD : nil }
let tree = try doc.validate(instance, schemaLoader: loader).map(\.reason).sorted()
let streamed = try doc.validate(streaming: instance, schemaLoader: loader).map(\.reason).sorted()
#expect(tree == streamed)
#expect(tree.isEmpty)
}
@Test("Streaming strict wildcard fails without the loader")
func test_streamingStrictUnresolvedWithoutLoader() throws {
let doc = try PureXML.Schema.Document(mainXSD)
#expect(try !doc.validate(streaming: instance).isEmpty)
}
}