PureXML/Tests/LineEndingTests.swift
Mihaela Mihaljevic 380160cc2b refactor(validation): decompose XSD instance validation into composable rules
The two monolithic XSD content/identity rules only satisfied the OpenAPIKit
validation idiom at the wrong granularity: no per-constraint removability,
no isolable failing/near-miss tests. Split them into 32 named rules, each
finding tagged at its origin and cached per XSDContext so the walk still
runs once per document (the #101 decision against duplicating XSD's
recursive type resolution still holds). Wired the streaming path's ID/IDREF
and identity checks through the same framework instead of calling the
validators imperatively, and added the unwrapAndLookup combinator the rule
already named as required.

Also includes the mandated repo-wide swiftformat/swiftlint pass.
2026-07-12 14:12:17 +02:00

53 lines
1.7 KiB
Swift

import Testing
@testable import PureXML
@Suite("Line-ending normalization and XML 1.1")
struct LineEndingTests {
private func rootText(_ xml: String) throws -> String {
let node = try PureXML.parse(xml)
guard case let .document(children) = node, let root = children.compactMap(\.element).first else {
return ""
}
return root.children.reduce(into: "") { result, child in
if case let .text(text) = child {
result += text
}
}
}
@Test("CRLF is normalized to a single line feed")
func test_crlf() throws {
#expect(try rootText("<a>x\r\ny</a>") == "x\ny")
}
@Test("A lone carriage return is normalized to a line feed")
func test_loneCR() throws {
#expect(try rootText("<a>x\ry</a>") == "x\ny")
}
@Test("In XML 1.0, NEL is preserved as data")
func test_nel10() throws {
#expect(try rootText("<a>x\u{85}y</a>") == "x\u{85}y")
}
@Test("In XML 1.1, NEL is normalized to a line feed")
func test_nel11() throws {
#expect(try rootText("<?xml version=\"1.1\"?><a>x\u{85}y</a>") == "x\ny")
}
@Test("In XML 1.1, LINE SEPARATOR is normalized to a line feed")
func test_lineSeparator11() throws {
#expect(try rootText("<?xml version=\"1.1\"?><a>x\u{2028}y</a>") == "x\ny")
}
@Test("In XML 1.1, CR followed by NEL collapses to one line feed")
func test_crNel11() throws {
#expect(try rootText("<?xml version=\"1.1\"?><a>x\r\u{85}y</a>") == "x\ny")
}
@Test("In XML 1.0, LINE SEPARATOR is preserved as data")
func test_lineSeparator10() throws {
#expect(try rootText("<a>x\u{2028}y</a>") == "x\u{2028}y")
}
}