var XmlDocument = require("../").XmlDocument; var t = require("tap"); t.test("verify sax global in browser", function (t) { // "un-require" the xmldoc module that we loaded up top delete require.cache[require.resolve("../")]; // also un-require the actual xmldoc module pulled in by index.js ('../') delete require.cache[require.resolve("../lib/xmldoc.js")]; // this signal will be picked up on by xmldoc.js global.xmldocAssumeBrowser = true; t.throws(function () { require("../"); }); // try again, but this time satisfy the sax check delete require.cache[require.resolve("../")]; delete require.cache[require.resolve("../lib/xmldoc.js")]; global.sax = {}; require("../"); t.ok(global.XmlDocument); t.end(); }); t.test("extend util", function (t) { delete require.cache[require.resolve("../")]; delete require.cache[require.resolve("../lib/xmldoc.js")]; Object.prototype.cruftyExtension = "blah"; try { require("../"); } finally { delete Object.prototype.cruftyExtension; } t.end(); }); t.test("parse xml", function (t) { var xmlString = "world"; var parsed = new XmlDocument(xmlString); t.ok(parsed); t.throws(function () { new XmlDocument(); }); t.throws(function () { new XmlDocument(" "); }); t.end(); }); t.test("cdata handling", function (t) { var xmlString = "]]>"; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, ""); t.end(); }); t.test("cdata and text handling", function (t) { var xmlString = "(]]>)"; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, "()"); t.end(); }); t.test("doctype handling", function (t) { var docWithType = new XmlDocument( "world", ); t.equal(docWithType.doctype, " HelloWorld"); var docWithoutType = new XmlDocument("world"); t.equal(docWithoutType.doctype, ""); t.throws(function () { new XmlDocument("world"); }); t.end(); }); t.test("comment handling", function (t) { var xmlString = ""; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, ""); t.end(); }); t.test("comment and text handling", function (t) { var xmlString = "()"; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, "()"); t.end(); }); t.test("text, cdata, and comment handling", function (t) { var xmlString = "Hello ]]>!"; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, "Hello !"); t.end(); }); t.test("text with elements handling", function (t) { var xmlString = "hello, !"; var parsed = new XmlDocument(xmlString); t.equal(parsed.val, "hello, !"); t.end(); }); t.test("text before root node", function (t) { var xmlString = "\n\n*"; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("text after root node", function (t) { var xmlString = "*\n\n"; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("text before root node with version", function (t) { var xmlString = '\n\n*'; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("text after root node with version", function (t) { var xmlString = '*\n\n'; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("comment before root node", function (t) { var xmlString = "*"; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("comment after root node", function (t) { var xmlString = "*"; var xml = new XmlDocument(xmlString); t.equal(xml.val, "*"); t.equal(xml.children.length, 1); t.end(); }); t.test("error handling", function (t) { var xmlString = ""; t.throws(function () { var parsed = new XmlDocument(xmlString); }); t.end(); }); t.test("tag locations", function (t) { var xmlString = ''; var books = new XmlDocument(xmlString); var book = books.children[0]; t.equal(book.attr.title, "Twilight"); t.equal(book.startTagPosition, 8); t.equal(book.line, 0); t.equal(book.column, 31); t.equal(book.position, 31); t.end(); }); t.test("eachChild", function (t) { var xmlString = ''; var books = new XmlDocument(xmlString); expectedTitles = ["Twilight", "Twister"]; books.eachChild(function (book, i, books) { t.equal(book.attr.title, expectedTitles[i]); }); called = 0; books.eachChild(function (book, i, books) { called++; return false; // test that returning false short-circuits the loop }); t.equal(called, 1); t.end(); }); t.test("eachChild with text and comments", function (t) { var xmlString = 'text!'; var books = new XmlDocument(xmlString); expectedTitles = ["Twilight", "Twister"]; var elI = 0; books.eachChild(function (book, i, books) { t.equal(book.attr.title, expectedTitles[elI++]); }); called = 0; books.eachChild(function (book, i, books) { called++; return false; // test that returning false short-circuits the loop }); t.equal(called, 1); t.end(); }); t.test("childNamed", function (t) { var xmlString = ""; var books = new XmlDocument(xmlString); var goodBook = books.childNamed("good-book"); t.equal(goodBook.name, "good-book"); var badBook = books.childNamed("bad-book"); t.equal(badBook, undefined); t.end(); }); t.test("childNamed with text", function (t) { var xmlString = "text"; var books = new XmlDocument(xmlString); var goodBook = books.childNamed("good-book"); t.equal(goodBook.name, "good-book"); var badBook = books.childNamed("bad-book"); t.equal(badBook, undefined); t.end(); }); t.test("childNamed", function (t) { var xmlString = ''; var fruits = new XmlDocument(xmlString); var apples = fruits.childrenNamed("apple"); t.equal(apples.length, 2); t.equal(apples[0].attr.sweet, "yes"); t.equal(apples[1].attr.sweet, "no"); t.end(); }); t.test("childWithAttribute", function (t) { var xmlString = ''; var fruits = new XmlDocument(xmlString); var pickedFruit = fruits.childWithAttribute("pick", "yes"); t.equal(pickedFruit.name, "apple"); t.equal(pickedFruit.attr.pick, "yes"); var rottenFruit = fruits.childWithAttribute("rotten"); t.equal(rottenFruit.name, "orange"); var peeled = fruits.childWithAttribute("peeled"); t.equal(peeled, undefined); t.end(); }); t.test("childWithAttribute with text", function (t) { var xmlString = 'text'; var fruits = new XmlDocument(xmlString); var pickedFruit = fruits.childWithAttribute("pick", "yes"); t.equal(pickedFruit.name, "apple"); t.equal(pickedFruit.attr.pick, "yes"); var rottenFruit = fruits.childWithAttribute("rotten"); t.equal(rottenFruit.name, "orange"); var peeled = fruits.childWithAttribute("peeled"); t.equal(peeled, undefined); t.end(); }); t.test("descendantsNamed", function (t) { var xmlString = ''; var navigation = new XmlDocument(xmlString); var items = navigation.descendantsNamed("item"); t.equal(items.length, 6); t.equal(items[0].attr.id, "1"); t.equal(items[1].attr.id, "2"); t.equal(items[2].attr.id, "2.1"); t.equal(items[3].attr.id, "2.2"); t.equal(items[4].attr.id, "2.2.1"); t.equal(items[5].attr.id, "3"); t.end(); }); t.test("descendantWithPath", function (t) { var xmlString = "George R.R.Martin"; var book = new XmlDocument(xmlString); var lastNameNode = book.descendantWithPath("author.last"); t.equal(lastNameNode.val, "Martin"); var middleNameNode = book.descendantWithPath("author.middle"); t.equal(middleNameNode, undefined); var publisherNameNode = book.descendantWithPath("publisher.first"); t.equal(publisherNameNode, undefined); t.end(); }); t.test("descendantWithPath with text", function (t) { var xmlString = "textGeorge R.R.Martin"; var book = new XmlDocument(xmlString); var lastNameNode = book.descendantWithPath("author.last"); t.equal(lastNameNode.val, "Martin"); var middleNameNode = book.descendantWithPath("author.middle"); t.equal(middleNameNode, undefined); var publisherNameNode = book.descendantWithPath("publisher.first"); t.equal(publisherNameNode, undefined); t.end(); }); t.test("valueWithPath", function (t) { var xmlString = 'George R.R.Martin'; var book = new XmlDocument(xmlString); var lastName = book.valueWithPath("author.last"); t.equal(lastName, "Martin"); var lastNameHyphenated = book.valueWithPath("author.last@hyphenated"); t.equal(lastNameHyphenated, "no"); var publisherName = book.valueWithPath("publisher.last@hyphenated"); t.equal(publisherName, undefined); t.end(); }); t.test("valueWithPath with text", function (t) { var xmlString = 'textGeorge R.R.Martin'; var book = new XmlDocument(xmlString); var lastName = book.valueWithPath("author.last"); t.equal(lastName, "Martin"); var lastNameHyphenated = book.valueWithPath("author.last@hyphenated"); t.equal(lastNameHyphenated, "no"); var publisherName = book.valueWithPath("publisher.last@hyphenated"); t.equal(publisherName, undefined); t.end(); }); t.test("toString", function (t) { var xmlString = ''; var doc = new XmlDocument(xmlString); t.equal(doc.toString(), '\n \n'); t.equal( doc.toString({ compressed: true }), '', ); xmlString = " world "; doc = new XmlDocument(xmlString); t.equal(doc.toString(), "world"); t.equal(doc.toString({ preserveWhitespace: true }), " world "); xmlString = "]]>"; doc = new XmlDocument(xmlString); t.equal(doc.toString(), "]]>"); xmlString = "Hello ]]>!"; doc = new XmlDocument(xmlString); t.equal( doc.toString({ preserveWhitespace: true }), "\n Hello\n \n \n ]]>\n !\n", ); xmlString = "hello, !"; doc = new XmlDocument(xmlString); t.equal(doc.toString(), "\n hello,\n \n !\n"); xmlString = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam et accumsan nisi."; doc = new XmlDocument(xmlString); t.equal(doc.toString(), xmlString); t.equal( doc.toString({ trimmed: true }), "Lorem ipsum dolor sit ame…", ); try { // test that adding stuff to the Object prototype doesn't interfere with attribute exporting Object.prototype.cruftyExtension = "You don't want this string to be exported!"; var xmlString = ''; var doc = new XmlDocument(xmlString); t.equal(doc.toString(), '\n \n'); } finally { delete Object.prototype.cruftyExtensionMethod; } xmlString = "world"; doc = new XmlDocument(xmlString); t.equal(doc.toString({ compressed: true }), xmlString); t.end(); });