basic.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. var XmlDocument = require('../').XmlDocument
  2. var t = require('tap')
  3. t.test('verify sax global in browser', function (t) {
  4. // "un-require" the xmldoc module that we loaded up top
  5. delete require.cache[require.resolve('../')];
  6. // also un-require the actual xmldoc module pulled in by index.js ('../')
  7. delete require.cache[require.resolve('../lib/xmldoc.js')];
  8. // this signal will be picked up on by xmldoc.js
  9. global.xmldocAssumeBrowser = true;
  10. t.throws(function() {
  11. require('../');
  12. });
  13. // try again, but this time satisfy the sax check
  14. delete require.cache[require.resolve('../')];
  15. delete require.cache[require.resolve('../lib/xmldoc.js')];
  16. global.sax = {};
  17. require('../');
  18. t.ok(global.XmlDocument);
  19. t.end();
  20. })
  21. t.test('extend util', function(t) {
  22. delete require.cache[require.resolve('../')];
  23. delete require.cache[require.resolve('../lib/xmldoc.js')];
  24. Object.prototype.cruftyExtension = "blah";
  25. try {
  26. require('../');
  27. }
  28. finally {
  29. delete Object.prototype.cruftyExtension;
  30. }
  31. t.end();
  32. })
  33. t.test('parse xml', function (t) {
  34. var xmlString = '<hello>world</hello>';
  35. var parsed = new XmlDocument(xmlString);
  36. t.ok(parsed);
  37. t.throws(function() { new XmlDocument(); });
  38. t.throws(function() { new XmlDocument(" "); });
  39. t.end();
  40. })
  41. t.test('cdata handling', function (t) {
  42. var xmlString = '<hello><![CDATA[<world>]]></hello>';
  43. var parsed = new XmlDocument(xmlString);
  44. t.equal(parsed.val, "<world>");
  45. t.end();
  46. })
  47. t.test('cdata and text handling', function (t) {
  48. var xmlString = '<hello>(<![CDATA[<world>]]>)</hello>';
  49. var parsed = new XmlDocument(xmlString);
  50. t.equal(parsed.val, "(<world>)");
  51. t.end();
  52. })
  53. t.test('doctype handling', function (t) {
  54. var docWithType = new XmlDocument('<!DOCTYPE HelloWorld><hello>world</hello>');
  55. t.equal(docWithType.doctype, " HelloWorld");
  56. var docWithoutType = new XmlDocument('<hello>world</hello>');
  57. t.equal(docWithoutType.doctype, "");
  58. t.throws(function() {
  59. new XmlDocument('<hello><!DOCTYPE HelloWorld>world</hello>');
  60. });
  61. t.end();
  62. })
  63. t.test('comment handling', function (t) {
  64. var xmlString = '<hello><!-- World --></hello>';
  65. var parsed = new XmlDocument(xmlString);
  66. t.equal(parsed.val, "");
  67. t.end();
  68. })
  69. t.test('comment and text handling', function (t) {
  70. var xmlString = '<hello>(<!-- World -->)</hello>';
  71. var parsed = new XmlDocument(xmlString);
  72. t.equal(parsed.val, "()");
  73. t.end();
  74. })
  75. t.test('text, cdata, and comment handling', function (t) {
  76. var xmlString = '<hello>Hello<!-- , --> <![CDATA[<world>]]>!</hello>';
  77. var parsed = new XmlDocument(xmlString);
  78. t.equal(parsed.val, "Hello <world>!");
  79. t.end();
  80. })
  81. t.test('text with elements handling', function (t) {
  82. var xmlString = '<hello>hello, <world/>!</hello>';
  83. var parsed = new XmlDocument(xmlString);
  84. t.equal(parsed.val, "hello, !");
  85. t.end();
  86. })
  87. t.test('text before root node', function (t) {
  88. var xmlString = '\n\n<hello>*</hello>';
  89. var xml = new XmlDocument(xmlString);
  90. t.equal(xml.val, '*');
  91. t.equal(xml.children.length, 1);
  92. t.end();
  93. })
  94. t.test('text after root node', function (t) {
  95. var xmlString = '<hello>*</hello>\n\n';
  96. var xml = new XmlDocument(xmlString);
  97. t.equal(xml.val, '*');
  98. t.equal(xml.children.length, 1);
  99. t.end();
  100. })
  101. t.test('text before root node with version', function (t) {
  102. var xmlString = '<?xml version="1.0"?>\n\n<hello>*</hello>';
  103. var xml = new XmlDocument(xmlString);
  104. t.equal(xml.val, '*');
  105. t.equal(xml.children.length, 1);
  106. t.end();
  107. })
  108. t.test('text after root node with version', function (t) {
  109. var xmlString = '<?xml version="1.0"?><hello>*</hello>\n\n';
  110. var xml = new XmlDocument(xmlString);
  111. t.equal(xml.val, '*');
  112. t.equal(xml.children.length, 1);
  113. t.end();
  114. })
  115. t.test('comment before root node', function (t) {
  116. var xmlString = '<!-- hello --><world>*</world>';
  117. var xml = new XmlDocument(xmlString);
  118. t.equal(xml.val, '*');
  119. t.equal(xml.children.length, 1);
  120. t.end();
  121. })
  122. t.test('comment after root node', function (t) {
  123. var xmlString = '<hello>*</hello><!-- world -->';
  124. var xml = new XmlDocument(xmlString);
  125. t.equal(xml.val, '*');
  126. t.equal(xml.children.length, 1);
  127. t.end();
  128. })
  129. t.test('error handling', function (t) {
  130. var xmlString = '<hello><unclosed-tag></hello>';
  131. t.throws(function() {
  132. var parsed = new XmlDocument(xmlString);
  133. });
  134. t.end();
  135. })
  136. t.test('tag locations', function (t) {
  137. var xmlString = '<books><book title="Twilight"/></books>';
  138. var books = new XmlDocument(xmlString);
  139. var book = books.children[0];
  140. t.equal(book.attr.title, "Twilight");
  141. t.equal(book.startTagPosition, 8);
  142. t.equal(book.line, 0);
  143. t.equal(book.column, 31);
  144. t.equal(book.position, 31);
  145. t.end();
  146. })
  147. t.test('eachChild', function (t) {
  148. var xmlString = '<books><book title="Twilight"/><book title="Twister"/></books>';
  149. var books = new XmlDocument(xmlString);
  150. expectedTitles = ["Twilight", "Twister"];
  151. books.eachChild(function(book, i, books) {
  152. t.equal(book.attr.title, expectedTitles[i]);
  153. });
  154. called = 0;
  155. books.eachChild(function(book, i, books) {
  156. called++;
  157. return false; // test that returning false short-circuits the loop
  158. });
  159. t.equal(called, 1);
  160. t.end();
  161. })
  162. t.test('eachChild with text and comments', function (t) {
  163. var xmlString = '<books><book title="Twilight"/>text!<book title="Twister"/><!--comment!--></books>';
  164. var books = new XmlDocument(xmlString);
  165. expectedTitles = ["Twilight", "Twister"];
  166. var elI = 0;
  167. books.eachChild(function(book, i, books) {
  168. t.equal(book.attr.title, expectedTitles[elI++]);
  169. });
  170. called = 0;
  171. books.eachChild(function(book, i, books) {
  172. called++;
  173. return false; // test that returning false short-circuits the loop
  174. });
  175. t.equal(called, 1);
  176. t.end();
  177. })
  178. t.test('childNamed', function (t) {
  179. var xmlString = '<books><book/><good-book/></books>';
  180. var books = new XmlDocument(xmlString);
  181. var goodBook = books.childNamed('good-book');
  182. t.equal(goodBook.name, 'good-book');
  183. var badBook = books.childNamed('bad-book');
  184. t.equal(badBook, undefined);
  185. t.end();
  186. })
  187. t.test('childNamed with text', function (t) {
  188. var xmlString = '<books><book/>text<good-book/></books>';
  189. var books = new XmlDocument(xmlString);
  190. var goodBook = books.childNamed('good-book');
  191. t.equal(goodBook.name, 'good-book');
  192. var badBook = books.childNamed('bad-book');
  193. t.equal(badBook, undefined);
  194. t.end();
  195. })
  196. t.test('childNamed', function (t) {
  197. var xmlString = '<fruits><apple sweet="yes"/><orange/><apple sweet="no"/><banana/></fruits>';
  198. var fruits = new XmlDocument(xmlString);
  199. var apples = fruits.childrenNamed('apple');
  200. t.equal(apples.length, 2);
  201. t.equal(apples[0].attr.sweet, 'yes');
  202. t.equal(apples[1].attr.sweet, 'no');
  203. t.end();
  204. })
  205. t.test('childWithAttribute', function (t) {
  206. var xmlString = '<fruits><apple pick="no"/><orange rotten="yes"/><apple pick="yes"/><banana/></fruits>';
  207. var fruits = new XmlDocument(xmlString);
  208. var pickedFruit = fruits.childWithAttribute('pick', 'yes');
  209. t.equal(pickedFruit.name, 'apple');
  210. t.equal(pickedFruit.attr.pick, 'yes');
  211. var rottenFruit = fruits.childWithAttribute('rotten');
  212. t.equal(rottenFruit.name, 'orange');
  213. var peeled = fruits.childWithAttribute('peeled');
  214. t.equal(peeled, undefined);
  215. t.end();
  216. })
  217. t.test('childWithAttribute with text', function (t) {
  218. var xmlString = '<fruits><apple pick="no"/><orange rotten="yes"/>text<apple pick="yes"/><banana/></fruits>';
  219. var fruits = new XmlDocument(xmlString);
  220. var pickedFruit = fruits.childWithAttribute('pick', 'yes');
  221. t.equal(pickedFruit.name, 'apple');
  222. t.equal(pickedFruit.attr.pick, 'yes');
  223. var rottenFruit = fruits.childWithAttribute('rotten');
  224. t.equal(rottenFruit.name, 'orange');
  225. var peeled = fruits.childWithAttribute('peeled');
  226. t.equal(peeled, undefined);
  227. t.end();
  228. })
  229. t.test('descendantsNamed', function (t) {
  230. var xmlString = '<navigation><item id="1"/><divider/><item id="2"><item id="2.1"/><item id="2.2"><item id="2.2.1"/></item><divider/><item id="3"/></item></navigation>';
  231. var navigation = new XmlDocument(xmlString);
  232. var items = navigation.descendantsNamed('item');
  233. t.equal(items.length, 6);
  234. t.equal(items[0].attr.id, '1');
  235. t.equal(items[1].attr.id, '2');
  236. t.equal(items[2].attr.id, '2.1');
  237. t.equal(items[3].attr.id, '2.2');
  238. t.equal(items[4].attr.id, '2.2.1');
  239. t.equal(items[5].attr.id, '3');
  240. t.end();
  241. })
  242. t.test('descendantWithPath', function (t) {
  243. var xmlString = '<book><author><first>George R.R.</first><last>Martin</last></author></book>';
  244. var book = new XmlDocument(xmlString);
  245. var lastNameNode = book.descendantWithPath('author.last');
  246. t.equal(lastNameNode.val, 'Martin');
  247. var middleNameNode = book.descendantWithPath('author.middle');
  248. t.equal(middleNameNode, undefined);
  249. var publisherNameNode = book.descendantWithPath('publisher.first');
  250. t.equal(publisherNameNode, undefined);
  251. t.end();
  252. })
  253. t.test('descendantWithPath with text', function (t) {
  254. var xmlString = '<book><author>text<first>George R.R.</first><last>Martin</last></author></book>';
  255. var book = new XmlDocument(xmlString);
  256. var lastNameNode = book.descendantWithPath('author.last');
  257. t.equal(lastNameNode.val, 'Martin');
  258. var middleNameNode = book.descendantWithPath('author.middle');
  259. t.equal(middleNameNode, undefined);
  260. var publisherNameNode = book.descendantWithPath('publisher.first');
  261. t.equal(publisherNameNode, undefined);
  262. t.end();
  263. })
  264. t.test('valueWithPath', function (t) {
  265. var xmlString = '<book><author><first>George R.R.</first><last hyphenated="no">Martin</last></author></book>';
  266. var book = new XmlDocument(xmlString);
  267. var lastName = book.valueWithPath('author.last');
  268. t.equal(lastName, 'Martin');
  269. var lastNameHyphenated = book.valueWithPath('author.last@hyphenated');
  270. t.equal(lastNameHyphenated, "no");
  271. var publisherName = book.valueWithPath('publisher.last@hyphenated');
  272. t.equal(publisherName, undefined);
  273. t.end();
  274. })
  275. t.test('valueWithPath with text', function (t) {
  276. var xmlString = '<book><author>text<first>George R.R.</first><last hyphenated="no">Martin</last></author></book>';
  277. var book = new XmlDocument(xmlString);
  278. var lastName = book.valueWithPath('author.last');
  279. t.equal(lastName, 'Martin');
  280. var lastNameHyphenated = book.valueWithPath('author.last@hyphenated');
  281. t.equal(lastNameHyphenated, "no");
  282. var publisherName = book.valueWithPath('publisher.last@hyphenated');
  283. t.equal(publisherName, undefined);
  284. t.end();
  285. })
  286. t.test('toString', function (t) {
  287. var xmlString = '<books><book title="Twilight"/></books>';
  288. var doc = new XmlDocument(xmlString);
  289. t.equal(doc.toString(), '<books>\n <book title="Twilight"/>\n</books>');
  290. t.equal(doc.toString({compressed:true}), '<books><book title="Twilight"/></books>');
  291. xmlString = '<hello> world </hello>';
  292. doc = new XmlDocument(xmlString);
  293. t.equal(doc.toString(), '<hello>world</hello>');
  294. t.equal(doc.toString({preserveWhitespace:true}), '<hello> world </hello>');
  295. xmlString = '<hello><![CDATA[<world>]]></hello>';
  296. doc = new XmlDocument(xmlString);
  297. t.equal(doc.toString(), '<hello><![CDATA[<world>]]></hello>');
  298. xmlString = '<hello>Hello<!-- , --> <![CDATA[<world>]]>!</hello>';
  299. doc = new XmlDocument(xmlString);
  300. t.equal(doc.toString({preserveWhitespace:true}), '<hello>\n Hello\n <!-- , -->\n \n <![CDATA[<world>]]>\n !\n</hello>');
  301. xmlString = '<hello>hello, <world/>!</hello>';
  302. doc = new XmlDocument(xmlString);
  303. t.equal(doc.toString(), '<hello>\n hello,\n <world/>\n !\n</hello>');
  304. xmlString = '<hello>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam et accumsan nisi.</hello>';
  305. doc = new XmlDocument(xmlString);
  306. t.equal(doc.toString(), xmlString);
  307. t.equal(doc.toString({trimmed:true}), '<hello>Lorem ipsum dolor sit ame…</hello>')
  308. try {
  309. // test that adding stuff to the Object prototype doesn't interfere with attribute exporting
  310. Object.prototype.cruftyExtension = "You don't want this string to be exported!";
  311. var xmlString = '<books><book title="Twilight"/></books>';
  312. var doc = new XmlDocument(xmlString);
  313. t.equal(doc.toString(), '<books>\n <book title="Twilight"/>\n</books>');
  314. }
  315. finally {
  316. delete Object.prototype.cruftyExtensionMethod;
  317. }
  318. xmlString = '<hello>world<earth/><moon/></hello>';
  319. doc = new XmlDocument(xmlString);
  320. t.equal(doc.toString({compressed:true}), xmlString);
  321. t.end();
  322. })