test.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. var assert = require('assert');
  2. var serialize = require('../');
  3. describe('node-serialize', function () {
  4. var node;
  5. afterEach(function () {
  6. if (node) {
  7. // clean up...
  8. if (node.parentNode) {
  9. node.parentNode.removeChild(node);
  10. }
  11. node = null;
  12. }
  13. });
  14. it('should return an empty string on invalid input', function () {
  15. assert.strictEqual('', serialize(null));
  16. });
  17. it('should serialize a SPAN element', function () {
  18. node = document.createElement('span');
  19. assert.equal('<span></span>', serialize(node));
  20. });
  21. it('should serialize a BR element', function () {
  22. node = document.createElement('br');
  23. assert.equal('<br>', serialize(node));
  24. });
  25. it('should serialize a text node', function () {
  26. node = document.createTextNode('test');
  27. assert.equal('test', serialize(node));
  28. });
  29. it('should serialize a text node with special HTML characters', function () {
  30. node = document.createTextNode('<>\'"&');
  31. assert.equal('&lt;&gt;\'"&amp;', serialize(node));
  32. });
  33. it('should serialize a DIV element with child nodes', function () {
  34. node = document.createElement('div');
  35. node.appendChild(document.createTextNode('hello '));
  36. var b = document.createElement('b');
  37. b.appendChild(document.createTextNode('world'));
  38. node.appendChild(b);
  39. node.appendChild(document.createTextNode('!'));
  40. node.appendChild(document.createElement('br'));
  41. assert.equal('<div>hello <b>world</b>!<br></div>', serialize(node));
  42. });
  43. it('should serialize a DIV element with attributes', function () {
  44. node = document.createElement('div');
  45. node.setAttribute('foo', 'bar');
  46. node.setAttribute('escape', '<>&"\'');
  47. assert.equal('<div foo="bar" escape="&lt;&gt;&amp;&quot;&apos;"></div>', serialize(node));
  48. });
  49. it('should serialize an Attribute node', function () {
  50. var div = document.createElement('div');
  51. div.setAttribute('foo', 'bar');
  52. node = div.attributes[0];
  53. assert.equal('foo="bar"', serialize(node));
  54. });
  55. it('should serialize a Comment node', function () {
  56. node = document.createComment('test');
  57. assert.equal('<!--test-->', serialize(node));
  58. });
  59. it('should serialize a Document node', function () {
  60. node = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null);
  61. assert.equal('<html></html>', serialize(node));
  62. });
  63. it('should serialize a Doctype node', function () {
  64. node = document.implementation.createDocumentType(
  65. 'html',
  66. '-//W3C//DTD XHTML 1.0 Strict//EN',
  67. 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'
  68. );
  69. // Some older browsers require the DOCTYPE to be within a Document,
  70. // otherwise the "serialize" custom event is considered "cancelled".
  71. // See: https://travis-ci.org/webmodules/dom-serialize/builds/47307749
  72. var doc = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', node);
  73. assert.equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">', serialize(node));
  74. assert.equal('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html></html>', serialize(doc));
  75. });
  76. it('should serialize a Doctype node with systemId', function () {
  77. node = document.implementation.createDocumentType(
  78. 'root-element',
  79. '',
  80. 'http://www.w3.org/1999/xhtml'
  81. );
  82. document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'root-element', node);
  83. assert.equal('<!DOCTYPE root-element SYSTEM "http://www.w3.org/1999/xhtml">', serialize(node));
  84. });
  85. it('should serialize an HTML5 Doctype node', function () {
  86. node = document.implementation.createDocumentType(
  87. 'html',
  88. '',
  89. ''
  90. );
  91. document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'node', node);
  92. assert.equal('<!DOCTYPE html>', serialize(node));
  93. });
  94. it('should serialize a DocumentFragment node', function () {
  95. node = document.createDocumentFragment();
  96. node.appendChild(document.createElement('b'));
  97. node.appendChild(document.createElement('i'));
  98. node.lastChild.appendChild(document.createTextNode('foo'));
  99. assert.equal('<b></b><i>foo</i>', serialize(node));
  100. });
  101. it('should serialize an Array of nodes', function () {
  102. var array = [];
  103. array.push(document.createTextNode('foo'));
  104. array.push(document.createElement('div'));
  105. array[1].appendChild(document.createTextNode('bar'));
  106. assert.equal('foo<div>bar</div>', serialize(array));
  107. });
  108. describe('serializeText()', function () {
  109. it('should serialize an Attribute node', function () {
  110. var d = document.createElement('div');
  111. d.setAttribute('foo', '<>"&');
  112. assert.equal('foo="&lt;&gt;&quot;&amp;"', serialize.serializeAttribute(d.attributes[0]));
  113. });
  114. it('should allow an "options" object to be passed in', function () {
  115. var d = document.createElement('div');
  116. d.setAttribute('foo', '<>"&');
  117. assert.equal('foo="&#60;&#62;&#34;&#38;"', serialize.serializeAttribute(d.attributes[0], { named: false }));
  118. });
  119. });
  120. describe('serializeText()', function () {
  121. it('should serialize a TextNode instance', function () {
  122. node = document.createTextNode('<b>&');
  123. assert.equal('&lt;b&gt;&amp;', serialize.serializeText(node));
  124. });
  125. it('should allow an "options" object to be passed in', function () {
  126. node = document.createTextNode('<b>&');
  127. assert.equal('&#60;b&#62;&#38;', serialize.serializeText(node, { named: false }));
  128. });
  129. });
  130. describe('"serialize" event', function () {
  131. it('should emit a "serialize" event on a DIV node', function () {
  132. node = document.createElement('div');
  133. var count = 0;
  134. node.addEventListener('serialize', function (e) {
  135. count++;
  136. e.detail.serialize = 'MEOW';
  137. });
  138. assert.equal(0, count);
  139. assert.equal('MEOW', serialize(node));
  140. assert.equal(1, count);
  141. });
  142. it('should emit a "serialize" event on a Text node', function () {
  143. node = document.createTextNode('whaaaaa!!!!!!');
  144. var count = 0;
  145. node.addEventListener('serialize', function (e) {
  146. count++;
  147. e.detail.serialize = 'MEOW';
  148. });
  149. assert.equal(0, count);
  150. assert.equal('MEOW', serialize(node));
  151. assert.equal(1, count);
  152. });
  153. it('should output an empty string when event is cancelled', function () {
  154. node = document.createElement('div');
  155. node.appendChild(document.createTextNode('!'));
  156. var count = 0;
  157. node.firstChild.addEventListener('serialize', function (e) {
  158. count++;
  159. e.preventDefault();
  160. });
  161. assert.equal(0, count);
  162. assert.equal('<div></div>', serialize(node));
  163. assert.equal(1, count);
  164. });
  165. it('should render a Number when set as `e.detail.serialize`', function () {
  166. node = document.createTextNode('whaaaaa!!!!!!');
  167. var count = 0;
  168. node.addEventListener('serialize', function (e) {
  169. count++;
  170. e.detail.serialize = 123;
  171. });
  172. assert.equal(0, count);
  173. assert.equal('123', serialize(node));
  174. assert.equal(1, count);
  175. });
  176. it('should render a Node when set as `e.detail.serialize`', function () {
  177. node = document.createTextNode('whaaaaa!!!!!!');
  178. var count = 0;
  179. node.addEventListener('serialize', function (e) {
  180. count++;
  181. if (count === 1) {
  182. e.detail.serialize = document.createTextNode('foo');
  183. }
  184. });
  185. assert.equal(0, count);
  186. assert.equal('foo', serialize(node));
  187. assert.equal(2, count);
  188. });
  189. it('should render a Node when set as `e.detail.serialize` and event is cancelled', function () {
  190. node = document.createTextNode('whaaaaa!!!!!!');
  191. var count = 0;
  192. node.addEventListener('serialize', function (e) {
  193. count++;
  194. if (count === 1) {
  195. e.preventDefault();
  196. e.detail.serialize = document.createTextNode('foo');
  197. }
  198. });
  199. assert.equal(0, count);
  200. assert.equal('foo', serialize(node));
  201. assert.equal(2, count);
  202. });
  203. it('should have `context` set on the event', function () {
  204. node = document.createTextNode('');
  205. var count = 0;
  206. node.addEventListener('serialize', function (e) {
  207. count++;
  208. e.detail.serialize = e.detail.context;
  209. });
  210. assert.equal(0, count);
  211. assert.equal('foo', serialize(node, 'foo'));
  212. assert.equal(1, count);
  213. assert.equal('bar', serialize(node, 'bar'));
  214. assert.equal(2, count);
  215. assert.equal('baz', serialize(node, 'baz'));
  216. assert.equal(3, count);
  217. });
  218. it('should bubble', function () {
  219. node = document.createElement('div');
  220. node.appendChild(document.createTextNode('foo'));
  221. node.appendChild(document.createTextNode(' '));
  222. node.appendChild(document.createTextNode('bar'));
  223. // `node` must be inside the DOM for the "serialize" event to bubble
  224. document.body.appendChild(node);
  225. var count = 0;
  226. node.addEventListener('serialize', function (e) {
  227. count++;
  228. assert.equal('foo', e.detail.context);
  229. if (e.serializeTarget === node)
  230. return;
  231. else if (e.serializeTarget.nodeValue === 'foo')
  232. e.detail.serialize = '…';
  233. else
  234. e.preventDefault();
  235. }, false);
  236. assert.equal(0, count);
  237. assert.equal('<div>…</div>', serialize(node, 'foo'));
  238. assert.equal(4, count);
  239. });
  240. it('should support one-time callback function on Elements', function () {
  241. node = document.createElement('div');
  242. var count = 0;
  243. function callback (e) {
  244. count++;
  245. e.detail.serialize = count;
  246. }
  247. assert.equal(0, count);
  248. assert.equal('1', serialize(node, callback));
  249. assert.equal(1, count);
  250. assert.equal('<div></div>', serialize(node));
  251. assert.equal(1, count);
  252. });
  253. it('should support one-time callback function on NodeLists', function () {
  254. node = document.createElement('div');
  255. node.appendChild(document.createElement('strong'));
  256. node.appendChild(document.createTextNode('foo'));
  257. node.appendChild(document.createElement('em'));
  258. node.appendChild(document.createTextNode('bar'));
  259. var count = 0;
  260. function callback (e) {
  261. count++;
  262. e.detail.serialize = count;
  263. }
  264. assert.equal(0, count);
  265. assert.equal('1234', serialize(node.childNodes, callback));
  266. assert.equal(4, count);
  267. assert.equal('<strong></strong>foo<em></em>bar', serialize(node.childNodes));
  268. assert.equal(4, count);
  269. });
  270. it('should support one-time callback function on Nodes set in `e.detail.serialize`', function () {
  271. node = document.createElement('div');
  272. node.appendChild(document.createTextNode('foo'));
  273. // `node` must be inside the DOM for the "serialize" event to bubble
  274. document.body.appendChild(node);
  275. var count = 0;
  276. function callback (e) {
  277. count++;
  278. if (2 === count) {
  279. assert.equal('foo', e.serializeTarget.nodeValue);
  280. var text = document.createTextNode('bar');
  281. e.detail.serialize = text;
  282. } else if (3 === count) {
  283. assert.equal('bar', e.serializeTarget.nodeValue);
  284. var text = document.createTextNode('baz');
  285. e.detail.serialize = text;
  286. }
  287. }
  288. assert.equal(0, count);
  289. assert.equal('<div>baz</div>', serialize(node, callback));
  290. assert.equal(4, count);
  291. });
  292. it('should support one-time callback function on complex Nodes set in `e.detail.serialize`', function () {
  293. node = document.createElement('div');
  294. node.appendChild(document.createTextNode('foo'));
  295. // `node` must be inside the DOM for the "serialize" event to bubble
  296. document.body.appendChild(node);
  297. var count = 0;
  298. function callback (e) {
  299. count++;
  300. if (e.serializeTarget.nodeValue === 'foo') {
  301. var el = document.createElement('p');
  302. el.appendChild(document.createTextNode('x '));
  303. el.appendChild(document.createElement('i'));
  304. el.lastChild.appendChild(document.createTextNode('bar'));
  305. e.detail.serialize = el;
  306. }
  307. }
  308. assert.equal(0, count);
  309. assert.equal('<div><p>x <i>bar</i></p></div>', serialize(node, callback));
  310. assert.equal(6, count);
  311. });
  312. });
  313. });