import { test } from "node:test"; import assert from "node:assert/strict"; import { parseXml, findElementAt } from "../out/language/xmlParser.js"; test("parses elements, attributes and positions", () => { const text = `\n\t\n`; const doc = parseXml(text); assert.equal(doc.errors.length, 0); assert.equal(doc.root.name, "AssetDeclaration"); const go = doc.root.children[0]; assert.equal(go.name, "GameObject"); assert.equal(go.selfClosing, true); assert.equal(go.attrs.length, 2); assert.equal(go.attrs[0].name, "id"); assert.equal(go.attrs[0].value, "X"); assert.equal(go.attrs[1].value, "A B"); const idAttr = go.attrs[0]; assert.equal(text.slice(idAttr.valueStart, idAttr.valueEnd), "X"); }); test("detects mismatched and unclosed tags", () => { const doc = parseXml(""); assert.ok(doc.errors.length >= 1); assert.match(doc.errors[0].message, /Mismatched|never closed/); }); test("handles CRLF and comments", () => { const text = "\r\n\r\n\r\n\r\n"; const doc = parseXml(text); assert.equal(doc.errors.length, 0); assert.equal(doc.root.name, "AssetDeclaration"); }); test("findElementAt returns innermost element", () => { const text = ``; const doc = parseXml(text); const c = doc.elements.find((e) => e.name === "C"); const at = findElementAt(doc, c.start + 1); assert.equal(at.name, "C"); }); test("tolerates partial input while typing", () => { const text = `\n\t= 1); // unclosed assert.equal(doc.elements.length, 2); }); test("recovers from an unterminated attribute value at end of line", () => { // Typing an attribute value quote without its closing quote makes the tag // malformed; the parser must stop the broken start tag at the line break so // the rest of the document (and completion for it) keeps working. const text = `\n e.name), ["AssetDeclaration", "A", "B"]); const a = doc.elements.find((e) => e.name === "A"); const y = a.attrs.find((at) => at.name === "y"); assert.equal(y.quoteEnd, -1); assert.equal(text.slice(y.valueStart, y.valueEnd), "abc"); const b = doc.elements.find((e) => e.name === "B"); assert.ok(b.start > a.start); }); test("reports an unterminated attribute value at EOF", () => { const text = `