import { expect, it } from "vitest"; import { parseXmlDocument } from "./xmlDocument.js"; it.each([ '😀 � & �', "", '\r\n �\rtext', "�", ']>�', ])("preserves legal Unicode and source-located DOM nodes: %j", (source) => { const parsed = parseXmlDocument(source, { doctype: "allow", lineEndings: "preserve", }); if (!parsed.ok) throw parsed.error; expect(parsed.value.documentElement?.tagName).toBe("root"); expect(parsed.value.documentElement?.lineNumber).toBeDefined(); expect(parsed.value.documentElement?.textContent).toContain("�"); }); it.each([ "�", '', '', "�", "� & unknown", "� &missing;", "�\u0000", "��", "�\uFFFF", "�]]>", "", "�", "�", "]>�", "�", ])("rejects malformed XML without warning-message matching: %j", (source) => { const parsed = parseXmlDocument(source, { doctype: "allow", lineEndings: "preserve", }); expect(parsed.ok).toBe(false); if (parsed.ok) throw new Error("Expected refusal"); expect(parsed.error.reason).toBe("malformed"); expect(parsed.error.cause).toBeDefined(); }); it("keeps literal line endings and character-reference values distinct", () => { const parsed = parseXmlDocument("\r\n \r�", { doctype: "allow", lineEndings: "preserve", }); if (!parsed.ok) throw parsed.error; expect(parsed.value.documentElement?.textContent).toBe("\r\n\r\r�"); }); it("applies the consumer's explicit DTD policy", () => { const parsed = parseXmlDocument( ']>', { doctype: "reject", lineEndings: "preserve" }, ); expect(parsed.ok).toBe(false); if (parsed.ok) throw new Error("Expected unsupported DTD"); expect(parsed.error.reason).toBe("doctype"); }); it("applies XML line-ending normalization only when the consumer selects it", () => { const parsed = parseXmlDocument('\r\nx', { doctype: "allow", lineEndings: "normalize", }); if (!parsed.ok) throw parsed.error; expect(parsed.value.documentElement?.getAttribute("attr")).toBe("a b"); expect(parsed.value.documentElement?.textContent).toBe("\nx"); }); it("preserves Unicode separators under XML 1.0 normalization", () => { const parsed = parseXmlDocument( 'a\r\u0085b\r\u2028c\r\n d\u2029', { doctype: "allow", lineEndings: "normalize" }, ); if (!parsed.ok) throw parsed.error; expect(parsed.value.documentElement?.getAttribute("attr")).toBe( "a\u0085b\u2028c\u2029d", ); expect(parsed.value.documentElement?.textContent).toBe( "a\n\u0085b\n\u2028c\n\rd\u2029", ); });