diff --git a/Tests/RelaxNGIncludeTests.swift b/Tests/RelaxNGIncludeTests.swift
new file mode 100644
index 0000000..70ab140
--- /dev/null
+++ b/Tests/RelaxNGIncludeTests.swift
@@ -0,0 +1,63 @@
+import Testing
+@testable import PureXML
+
+/// RELAX NG `include` and `externalRef` resolution (Sources/Schema/RelaxNGParserIncludes.swift),
+/// which a loader supplies. This path was under-covered; these exercise a plain
+/// include, an include with a `define` override, and an externalRef.
+@Suite("RELAX NG include / externalRef")
+struct RelaxNGIncludeTests {
+ private let namespace = "xmlns='http://relaxng.org/ns/structure/1.0'"
+
+ @Test("a plain include merges the loaded grammar's defines")
+ func test_plainInclude() throws {
+ let main = """
+
+
+
+
+ """
+ let lib = """
+
+
+
+ """
+ let schema = try PureXML.Schema.RelaxNG(main, schemaLoader: { $0 == "lib.rng" ? lib : nil })
+ #expect(try schema.validate("hi"))
+ #expect(try !schema.validate(""))
+ }
+
+ @Test("an include override replaces the included define")
+ func test_includeOverride() throws {
+ // The includer redefines `body`; the loaded grammar's `body` (which allows
+ // text) is dropped in favor of the override (which allows only empty content).
+ let main = """
+
+
+
+
+
+
+ """
+ let lib = """
+
+
+
+ """
+ let schema = try PureXML.Schema.RelaxNG(main, schemaLoader: { $0 == "lib.rng" ? lib : nil })
+ #expect(try schema.validate("")) // override: empty content allowed
+ #expect(try !schema.validate("text")) // override removed the text pattern
+ }
+
+ @Test("an externalRef pulls a pattern from another document")
+ func test_externalRef() throws {
+ let main = """
+
+
+
+ """
+ let frag = ""
+ let schema = try PureXML.Schema.RelaxNG(main, schemaLoader: { $0 == "frag.rng" ? frag : nil })
+ #expect(try schema.validate("x"))
+ #expect(try !schema.validate(""))
+ }
+}