dom_test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. // Copyright 2008 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.testing.domTest');
  15. goog.setTestOnly('goog.testing.domTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.dom.TagName');
  18. goog.require('goog.testing.TestCase');
  19. goog.require('goog.testing.dom');
  20. goog.require('goog.testing.jsunit');
  21. goog.require('goog.userAgent');
  22. var root;
  23. function setUpPage() {
  24. // TODO(b/25875505): Fix unreported assertions (go/failonunreportedasserts).
  25. goog.testing.TestCase.getActiveTestCase().failOnUnreportedAsserts = false;
  26. root = goog.dom.getElement('root');
  27. }
  28. function setUp() {
  29. goog.dom.removeChildren(root);
  30. }
  31. function testFindNode() {
  32. // Test the easiest case.
  33. root.innerHTML = 'a<br>b';
  34. assertEquals(goog.testing.dom.findTextNode('a', root), root.firstChild);
  35. assertEquals(goog.testing.dom.findTextNode('b', root), root.lastChild);
  36. assertNull(goog.testing.dom.findTextNode('c', root));
  37. }
  38. function testFindNodeDuplicate() {
  39. // Test duplicate.
  40. root.innerHTML = 'c<br>c';
  41. assertEquals(
  42. 'Should return first duplicate', goog.testing.dom.findTextNode('c', root),
  43. root.firstChild);
  44. }
  45. function findNodeWithHierarchy() {
  46. // Test a more complicated hierarchy.
  47. root.innerHTML = '<div>a<p>b<span>c</span>d</p>e</div>';
  48. assertEquals(
  49. String(goog.dom.TagName.DIV),
  50. goog.testing.dom.findTextNode('a', root).parentNode.tagName);
  51. assertEquals(
  52. String(goog.dom.TagName.P),
  53. goog.testing.dom.findTextNode('b', root).parentNode.tagName);
  54. assertEquals(
  55. String(goog.dom.TagName.SPAN),
  56. goog.testing.dom.findTextNode('c', root).parentNode.tagName);
  57. assertEquals(
  58. String(goog.dom.TagName.P),
  59. goog.testing.dom.findTextNode('d', root).parentNode.tagName);
  60. assertEquals(
  61. String(goog.dom.TagName.DIV),
  62. goog.testing.dom.findTextNode('e', root).parentNode.tagName);
  63. }
  64. function setUpAssertHtmlMatches() {
  65. var tag1, tag2;
  66. if (goog.userAgent.EDGE_OR_IE) {
  67. tag1 = goog.dom.TagName.DIV;
  68. } else if (goog.userAgent.WEBKIT) {
  69. tag1 = goog.dom.TagName.P;
  70. tag2 = goog.dom.TagName.BR;
  71. } else if (goog.userAgent.GECKO) {
  72. tag1 = goog.dom.TagName.SPAN;
  73. tag2 = goog.dom.TagName.BR;
  74. }
  75. var parent = goog.dom.createDom(goog.dom.TagName.DIV);
  76. root.appendChild(parent);
  77. parent.style.fontSize = '2em';
  78. parent.style.display = 'none';
  79. if (!goog.userAgent.WEBKIT) {
  80. parent.appendChild(goog.dom.createTextNode('NonWebKitText'));
  81. }
  82. if (tag1) {
  83. var e1 = goog.dom.createDom(tag1);
  84. parent.appendChild(e1);
  85. parent = e1;
  86. }
  87. if (tag2) {
  88. parent.appendChild(goog.dom.createDom(tag2));
  89. }
  90. parent.appendChild(goog.dom.createTextNode('Text'));
  91. if (goog.userAgent.WEBKIT) {
  92. root.firstChild.appendChild(goog.dom.createTextNode('WebKitText'));
  93. }
  94. }
  95. function testAssertHtmlContentsMatch() {
  96. setUpAssertHtmlMatches();
  97. goog.testing.dom.assertHtmlContentsMatch(
  98. '<div style="display: none; font-size: 2em">' +
  99. '[[!WEBKIT]]NonWebKitText<div class="IE EDGE"><p class="WEBKIT">' +
  100. '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
  101. '</div>[[WEBKIT]]WebKitText',
  102. root);
  103. }
  104. function testAssertHtmlMismatchText() {
  105. setUpAssertHtmlMatches();
  106. var e = assertThrows('Should fail due to mismatched text', function() {
  107. goog.testing.dom.assertHtmlContentsMatch(
  108. '<div style="display: none; font-size: 2em">' +
  109. '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
  110. '<span class="GECKO"><br class="GECKO WEBKIT">Bad</span></p></div>' +
  111. '</div>[[WEBKIT]]Extra',
  112. root);
  113. });
  114. assertContains('Text should match', e.message);
  115. }
  116. function testAssertHtmlMismatchTag() {
  117. setUpAssertHtmlMatches();
  118. var e = assertThrows('Should fail due to mismatched tag', function() {
  119. goog.testing.dom.assertHtmlContentsMatch(
  120. '<span style="display: none; font-size: 2em">' +
  121. '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
  122. '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
  123. '</span>[[WEBKIT]]Extra',
  124. root);
  125. });
  126. assertContains('Tag names should match', e.message);
  127. }
  128. function testAssertHtmlMismatchStyle() {
  129. setUpAssertHtmlMatches();
  130. var e = assertThrows('Should fail due to mismatched style', function() {
  131. goog.testing.dom.assertHtmlContentsMatch(
  132. '<div style="display: none; font-size: 3em">' +
  133. '[[IE GECKO]]NonWebKitText<div class="IE"><p class="WEBKIT">' +
  134. '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
  135. '</div>[[WEBKIT]]Extra',
  136. root);
  137. });
  138. assertContains('Should have same styles', e.message);
  139. }
  140. function testAssertHtmlMismatchOptionalText() {
  141. setUpAssertHtmlMatches();
  142. var e = assertThrows('Should fail due to mismatched text', function() {
  143. goog.testing.dom.assertHtmlContentsMatch(
  144. '<div style="display: none; font-size: 2em">' +
  145. '[[IE GECKO]]Bad<div class="IE"><p class="WEBKIT">' +
  146. '<span class="GECKO"><br class="GECKO WEBKIT">Text</span></p></div>' +
  147. '</div>[[WEBKIT]]Bad',
  148. root);
  149. });
  150. assertContains('Text should match', e.message);
  151. }
  152. function testAssertHtmlMismatchExtraActualAfterText() {
  153. root.innerHTML = '<div>abc</div>def';
  154. var e = assertThrows('Should fail due to extra actual nodes', function() {
  155. goog.testing.dom.assertHtmlContentsMatch('<div>abc</div>', root);
  156. });
  157. assertContains('Finished expected HTML before', e.message);
  158. }
  159. function testAssertHtmlMismatchExtraActualAfterElement() {
  160. root.innerHTML = '<br>def';
  161. var e = assertThrows('Should fail due to extra actual nodes', function() {
  162. goog.testing.dom.assertHtmlContentsMatch('<br>', root);
  163. });
  164. assertContains('Finished expected HTML before', e.message);
  165. }
  166. function testAssertHtmlMatchesWithSplitTextNodes() {
  167. root.appendChild(goog.dom.createTextNode('1'));
  168. root.appendChild(goog.dom.createTextNode('2'));
  169. root.appendChild(goog.dom.createTextNode('3'));
  170. goog.testing.dom.assertHtmlContentsMatch('123', root);
  171. }
  172. function testAssertHtmlMatchesWithDifferentlyOrderedAttributes() {
  173. root.innerHTML = '<div foo="a" bar="b" class="className"></div>';
  174. goog.testing.dom.assertHtmlContentsMatch(
  175. '<div bar="b" class="className" foo="a"></div>', root, true);
  176. }
  177. function testAssertHtmlMismatchWithDifferentNumberOfAttributes() {
  178. root.innerHTML = '<div foo="a" bar="b"></div>';
  179. var e = assertThrows(function() {
  180. goog.testing.dom.assertHtmlContentsMatch('<div foo="a"></div>', root, true);
  181. });
  182. assertContains('Unexpected attribute with name bar in element', e.message);
  183. }
  184. function testAssertHtmlMismatchWithDifferentAttributeNames() {
  185. root.innerHTML = '<div foo="a" bar="b"></div>';
  186. var e = assertThrows(function() {
  187. goog.testing.dom.assertHtmlContentsMatch(
  188. '<div foo="a" baz="b"></div>', root, true);
  189. });
  190. assertContains('Expected to find attribute with name baz', e.message);
  191. }
  192. function testAssertHtmlMismatchWithDifferentClassNames() {
  193. root.innerHTML = '<div class="className1"></div>';
  194. var e = assertThrows(function() {
  195. goog.testing.dom.assertHtmlContentsMatch(
  196. '<div class="className2"></div>', root, true);
  197. });
  198. assertContains(
  199. 'Expected class was: className2, but actual class was: className1',
  200. e.message);
  201. }
  202. function testAssertHtmlMatchesWithClassNameAndUserAgentSpecified() {
  203. root.innerHTML = '<div>' +
  204. (goog.userAgent.GECKO ? '<div class="foo"></div>' : '') + '</div>';
  205. goog.testing.dom.assertHtmlContentsMatch(
  206. '<div><div class="foo GECKO"></div></div>', root, true);
  207. }
  208. function testAssertHtmlMatchesWithClassesInDifferentOrder() {
  209. root.innerHTML = '<div class="class1 class2"></div>';
  210. goog.testing.dom.assertHtmlContentsMatch(
  211. '<div class="class2 class1"></div>', root, true);
  212. }
  213. function testAssertHtmlMismatchWithDifferentAttributeValues() {
  214. root.innerHTML = '<div foo="b" bar="a"></div>';
  215. var e = assertThrows(function() {
  216. goog.testing.dom.assertHtmlContentsMatch(
  217. '<div foo="a" bar="a"></div>', root, true);
  218. });
  219. assertContains('Expected attribute foo has a different value', e.message);
  220. }
  221. function testAssertHtmlMatchesWhenStrictAttributesIsFalse() {
  222. root.innerHTML = '<div foo="a" bar="b"></div>';
  223. goog.testing.dom.assertHtmlContentsMatch('<div foo="a"></div>', root);
  224. }
  225. function testAssertHtmlMatchesForMethodsAttribute() {
  226. root.innerHTML = '<a methods="get"></a>';
  227. goog.testing.dom.assertHtmlContentsMatch('<a></a>', root);
  228. goog.testing.dom.assertHtmlContentsMatch('<a methods="get"></a>', root);
  229. goog.testing.dom.assertHtmlContentsMatch('<a methods="get"></a>', root, true);
  230. }
  231. function testAssertHtmlMatchesForMethodsAttribute() {
  232. root.innerHTML = '<input></input>';
  233. goog.testing.dom.assertHtmlContentsMatch('<input></input>', root);
  234. goog.testing.dom.assertHtmlContentsMatch('<input></input>', root, true);
  235. }
  236. function testAssertHtmlMatchesForIdAttribute() {
  237. root.innerHTML = '<div id="foo"></div>';
  238. goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
  239. goog.testing.dom.assertHtmlContentsMatch('<div id="foo"></div>', root);
  240. goog.testing.dom.assertHtmlContentsMatch('<div id="foo"></div>', root, true);
  241. }
  242. function testAssertHtmlMatchesWhenIdIsNotSpecified() {
  243. root.innerHTML = '<div id="someId"></div>';
  244. goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
  245. }
  246. function testAssertHtmlMismatchWhenIdIsNotSpecified() {
  247. root.innerHTML = '<div id="someId"></div>';
  248. var e = assertThrows(function() {
  249. goog.testing.dom.assertHtmlContentsMatch('<div></div>', root, true);
  250. });
  251. assertContains('Unexpected attribute with name id in element', e.message);
  252. }
  253. function testAssertHtmlMismatchWhenIdIsSpecified() {
  254. root.innerHTML = '<div></div>';
  255. var e = assertThrows(function() {
  256. goog.testing.dom.assertHtmlContentsMatch('<div id="someId"></div>', root);
  257. });
  258. assertContains(
  259. 'Expected to find attribute with name id, in element', e.message);
  260. e = assertThrows(function() {
  261. goog.testing.dom.assertHtmlContentsMatch(
  262. '<div id="someId"></div>', root, true);
  263. });
  264. assertContains(
  265. 'Expected to find attribute with name id, in element', e.message);
  266. }
  267. function testAssertHtmlMatchesWhenIdIsEmpty() {
  268. root.innerHTML = '<div></div>';
  269. goog.testing.dom.assertHtmlContentsMatch('<div></div>', root);
  270. goog.testing.dom.assertHtmlContentsMatch('<div></div>', root, true);
  271. }
  272. function testAssertHtmlMatchesWithDisabledAttribute() {
  273. var disabledShortest = '<input disabled="disabled">';
  274. var disabledShort = '<input disabled="">';
  275. var disabledLong = '<input disabled="disabled">';
  276. var enabled = '<input>';
  277. root.innerHTML = disabledLong;
  278. goog.testing.dom.assertHtmlContentsMatch(disabledShortest, root, true);
  279. goog.testing.dom.assertHtmlContentsMatch(disabledShort, root, true);
  280. goog.testing.dom.assertHtmlContentsMatch(disabledLong, root, true);
  281. var e = assertThrows('Should fail due to mismatched text', function() {
  282. goog.testing.dom.assertHtmlContentsMatch(enabled, root, true);
  283. });
  284. // Attribute value mismatch in IE.
  285. // Unexpected attribute error in other browsers.
  286. assertContains('disabled', e.message);
  287. }
  288. function testAssertHtmlMatchesWithCheckedAttribute() {
  289. var checkedShortest = '<input type="radio" name="x" checked="checked">';
  290. var checkedShort = '<input type="radio" name="x" checked="">';
  291. var checkedLong = '<input type="radio" name="x" checked="checked">';
  292. var unchecked = '<input type="radio" name="x">';
  293. root.innerHTML = checkedLong;
  294. goog.testing.dom.assertHtmlContentsMatch(checkedShortest, root, true);
  295. goog.testing.dom.assertHtmlContentsMatch(checkedShort, root, true);
  296. goog.testing.dom.assertHtmlContentsMatch(checkedLong, root, true);
  297. if (!goog.userAgent.IE) {
  298. // CHECKED attribute is ignored because it's among BAD_IE_ATTRIBUTES_.
  299. var e = assertThrows('Should fail due to mismatched text', function() {
  300. goog.testing.dom.assertHtmlContentsMatch(unchecked, root, true);
  301. });
  302. assertContains('Unexpected attribute with name checked', e.message);
  303. }
  304. }
  305. function testAssertHtmlMatchesWithWhitespace() {
  306. goog.dom.removeChildren(root);
  307. root.appendChild(goog.dom.createTextNode(' A '));
  308. goog.testing.dom.assertHtmlContentsMatch(' A ', root);
  309. goog.dom.removeChildren(root);
  310. root.appendChild(goog.dom.createTextNode(' A '));
  311. root.appendChild(goog.dom.createDom(goog.dom.TagName.SPAN, null, ' B '));
  312. root.appendChild(goog.dom.createTextNode(' C '));
  313. goog.testing.dom.assertHtmlContentsMatch(
  314. ' A <span> B </span> C ', root);
  315. goog.dom.removeChildren(root);
  316. root.appendChild(goog.dom.createTextNode(' A'));
  317. root.appendChild(goog.dom.createDom(goog.dom.TagName.SPAN, null, ' B'));
  318. root.appendChild(goog.dom.createTextNode(' C'));
  319. goog.testing.dom.assertHtmlContentsMatch(' A<span> B</span> C', root);
  320. }
  321. function testAssertHtmlMatchesWithWhitespaceAndNesting() {
  322. goog.dom.removeChildren(root);
  323. root.appendChild(
  324. goog.dom.createDom(
  325. goog.dom.TagName.DIV, null,
  326. goog.dom.createDom(goog.dom.TagName.B, null, ' A '),
  327. goog.dom.createDom(goog.dom.TagName.B, null, ' B ')));
  328. root.appendChild(
  329. goog.dom.createDom(
  330. goog.dom.TagName.DIV, null,
  331. goog.dom.createDom(goog.dom.TagName.B, null, ' C '),
  332. goog.dom.createDom(goog.dom.TagName.B, null, ' D ')));
  333. goog.testing.dom.assertHtmlContentsMatch(
  334. '<div><b> A </b><b> B </b></div>' +
  335. '<div><b> C </b><b> D </b></div>',
  336. root);
  337. goog.dom.removeChildren(root);
  338. root.appendChild(
  339. goog.dom.createDom(
  340. goog.dom.TagName.B, null,
  341. goog.dom.createDom(
  342. goog.dom.TagName.B, null,
  343. goog.dom.createDom(goog.dom.TagName.B, null, ' A '))));
  344. root.appendChild(goog.dom.createDom(goog.dom.TagName.B, null, ' B '));
  345. goog.testing.dom.assertHtmlContentsMatch(
  346. '<b><b><b> A </b></b></b><b> B </b>', root);
  347. goog.dom.removeChildren(root);
  348. root.appendChild(
  349. goog.dom.createDom(
  350. goog.dom.TagName.DIV, null,
  351. goog.dom.createDom(
  352. goog.dom.TagName.B, null,
  353. goog.dom.createDom(goog.dom.TagName.B, null, ' A '))));
  354. root.appendChild(goog.dom.createDom(goog.dom.TagName.B, null, ' B '));
  355. goog.testing.dom.assertHtmlContentsMatch(
  356. '<div><b><b> A </b></b></div><b> B </b>', root);
  357. root.innerHTML = '&nbsp;';
  358. goog.testing.dom.assertHtmlContentsMatch('&nbsp;', root);
  359. }
  360. function testAssertHtmlMatches() {
  361. // Since assertHtmlMatches is based on assertHtmlContentsMatch, we leave the
  362. // majority of edge case testing to the above. Here we just do a sanity
  363. // check.
  364. goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abc</div>');
  365. goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abc</div> ');
  366. goog.testing.dom.assertHtmlMatches(
  367. '<div style="font-size: 1px; color: red">abc</div>',
  368. '<div style="color: red; font-size: 1px;;">abc</div>');
  369. var e = assertThrows('Should fail due to mismatched text', function() {
  370. goog.testing.dom.assertHtmlMatches('<div>abc</div>', '<div>abd</div>');
  371. });
  372. assertContains('Text should match', e.message);
  373. }
  374. function testAssertHtmlMatchesWithSvgAttributes() {
  375. goog.testing.dom.assertHtmlMatches(
  376. '<svg height="10px"></svg>', '<svg height="10px"></svg>');
  377. }
  378. function testAssertHtmlMatchesWithScriptWithNewLines() {
  379. goog.testing.dom.assertHtmlMatches(
  380. '<script>var a;\nvar b;</script>', '<script>var a;\nvar b;</script>');
  381. }