test-document.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. var test = require("tape")
  2. module.exports = testDocument
  3. function testDocument(document) {
  4. var cleanup = require('./cleanup')(document)
  5. var Event = require('../event');
  6. test("document is a Document", function (assert) {
  7. assert.equal(typeof document.createTextNode, "function")
  8. assert.equal(typeof document.createElement, "function")
  9. assert.equal(typeof document.createDocumentFragment, "function")
  10. assert.end()
  11. })
  12. test("document has a head property", function(assert) {
  13. assert.equal(document.head.tagName, "HEAD")
  14. assert.end()
  15. })
  16. test("document has nodeType 9", function (assert) {
  17. assert.equal(document.nodeType, 9)
  18. assert.end()
  19. })
  20. test("can do stuff", function (assert) {
  21. var div = document.createElement("div")
  22. div.className = "foo bar"
  23. var span = document.createElement("span")
  24. div.appendChild(span)
  25. span.textContent = "Hello! <&>"
  26. var html = String(div.outerHTML || div)
  27. assert.equal(html, "<div class=\"foo bar\">" +
  28. "<span>Hello! &lt;&amp;&gt;</span></div>")
  29. cleanup()
  30. assert.end()
  31. })
  32. test("can createDocumentFragment", function (assert) {
  33. var frag = document.createDocumentFragment()
  34. assert.equal(frag.nodeType, 11)
  35. var h1 = document.createElement("h1")
  36. var h2 = document.createElement("h2")
  37. assert.equal(h1.nodeType, 1)
  38. assert.equal(h1.nodeType, 1)
  39. frag.appendChild(h1)
  40. assert.equal(fragString(frag), "<h1></h1>")
  41. frag.appendChild(h2)
  42. assert.equal(fragString(frag), "<h1></h1><h2></h2>")
  43. frag.removeChild(h1)
  44. assert.equal(fragString(frag), "<h2></h2>")
  45. frag.replaceChild(h1, h2)
  46. assert.equal(fragString(frag), "<h1></h1>")
  47. cleanup()
  48. assert.end()
  49. })
  50. test("can getElementById", function (assert) {
  51. function append_div(id, parent) {
  52. var div = document.createElement("div")
  53. div.id = id
  54. parent.appendChild(div)
  55. return div
  56. }
  57. var div1 = append_div(1, document.body)
  58. var div2 = append_div(2, document.body)
  59. var div3 = append_div(3, document.body)
  60. var div11 = append_div(11, div1)
  61. var div12 = append_div(12, div1)
  62. var div21 = append_div(21, div2)
  63. var div22 = append_div(22, div2)
  64. var div221 = append_div(221, div22)
  65. var div222 = append_div(222, div22)
  66. assert.equal(document.getElementById(1), div1)
  67. assert.equal(document.getElementById("2"), div2)
  68. assert.equal(document.getElementById(3), div3)
  69. assert.equal(document.getElementById(11), div11)
  70. assert.equal(document.getElementById(12), div12)
  71. assert.equal(document.getElementById(21), div21)
  72. assert.equal(document.getElementById(22), div22)
  73. assert.equal(document.getElementById(221), div221)
  74. assert.equal(document.getElementById(222), div222)
  75. cleanup()
  76. assert.end()
  77. })
  78. test("can getElementsByClassName for a single class", function(assert) {
  79. function append_div(className, parent) {
  80. var div = document.createElement("div")
  81. div.className = className
  82. parent.appendChild(div)
  83. return div
  84. }
  85. function assertSingleMatch(className, expectedElement) {
  86. var result = document.getElementsByClassName(className)
  87. assert.equal(result.length, 1)
  88. assert.equal(result[0], expectedElement)
  89. }
  90. var divA = append_div("A", document.body)
  91. var divB = append_div("B", document.body)
  92. var divC = append_div("C", document.body)
  93. var divA1 = append_div("A1", divA)
  94. var divA2 = append_div("A2", divA)
  95. var divB1 = append_div("B1", divB)
  96. var divB2 = append_div("B2", divB)
  97. var divB2a = append_div("B2a", divB2)
  98. var divB2b = append_div("B2b", divB2)
  99. assertSingleMatch("A", divA)
  100. assertSingleMatch("B", divB)
  101. assertSingleMatch("C", divC)
  102. assertSingleMatch("A1", divA1)
  103. assertSingleMatch("A2", divA2)
  104. assertSingleMatch("B1", divB1)
  105. assertSingleMatch("B2", divB2)
  106. assertSingleMatch("B2a", divB2a)
  107. assertSingleMatch("B2b", divB2b)
  108. cleanup()
  109. assert.end()
  110. })
  111. test("can getElementsByClassName for many elements", function (assert) {
  112. function h(className) {
  113. var div = document.createElement("div")
  114. div.className = className
  115. return div
  116. }
  117. document.body.appendChild(h("multi-class-bar"))
  118. document.body.appendChild(h("multi-class-bar"))
  119. var elems = document.getElementsByClassName("multi-class-bar")
  120. assert.equal(elems.length, 2)
  121. cleanup()
  122. assert.end()
  123. })
  124. test("can getElementsByClassName for many classes", function(assert) {
  125. function append_div(classNames, parent) {
  126. var div = document.createElement("div")
  127. div.className = classNames
  128. parent.appendChild(div)
  129. return div
  130. }
  131. function assertMatch(classNames, expectedElements) {
  132. var result = document.getElementsByClassName(classNames)
  133. assert.equal(result.length, expectedElements.length)
  134. for (var i = 0; i < expectedElements.length; i++) {
  135. assert.notEqual(expectedElements.indexOf(result[i]), -1)
  136. }
  137. }
  138. var divXYZ = append_div("X Y Z", document.body)
  139. var divYZ = append_div("Y Z", document.body)
  140. var divZX = append_div("Z X", document.body)
  141. var divX1X2 = append_div("X1 X2", divXYZ)
  142. var divX1X2Y1 = append_div("X1 X2 Y1", divXYZ)
  143. assertMatch("X", [divXYZ, divZX])
  144. assertMatch("Y Z", [divXYZ, divYZ])
  145. assertMatch("X Y Z", [divXYZ])
  146. assertMatch("X1 X2", [divX1X2, divX1X2Y1])
  147. cleanup()
  148. assert.end()
  149. })
  150. test("can create/manipulate textnodes", function (assert) {
  151. var textnode = document.createTextNode("hello")
  152. assert.equal(textnode.nodeType, 3)
  153. assert.equal(textnode.data, "hello")
  154. assert.equal(typeof textnode.replaceData, "function")
  155. textnode.replaceData(0, 7, "nightly")
  156. assert.equal(textnode.nodeType, 3)
  157. assert.equal(textnode.data, "nightly")
  158. assert.equal(typeof textnode.replaceData, "function")
  159. textnode.replaceData(1, 1, "ou")
  160. assert.equal(textnode.nodeType, 3)
  161. assert.equal(textnode.data, "noughtly")
  162. assert.end()
  163. })
  164. test("owner document is set", function (assert) {
  165. var textnode = document.createTextNode("hello")
  166. var domnode = document.createElement("div")
  167. var fragment = document.createDocumentFragment()
  168. assert.equal(textnode.ownerDocument, document)
  169. assert.equal(domnode.ownerDocument, document)
  170. assert.equal(fragment.ownerDocument, document)
  171. assert.end()
  172. })
  173. test("Create namespaced nodes", function (assert) {
  174. var svgURI = "http://www.w3.org/2000/svg"
  175. var htmlURI = "http://www.w3.org/1999/xhtml"
  176. var noNS = document.createElement("div")
  177. var svgNS = document.createElementNS(svgURI, "svg")
  178. var emptyNS = document.createElementNS("", "div")
  179. var nullNS = document.createElementNS(null, "div")
  180. var undefNS = document.createElementNS(undefined, "div")
  181. var caseNS = document.createElementNS("Oops", "AbC")
  182. var htmlNS = document.createElement("div")
  183. assert.equal(noNS.tagName, "DIV")
  184. assert.equal(noNS.namespaceURI, htmlURI)
  185. assert.equal(elemString(noNS), "<div></div>")
  186. assert.equal(svgNS.tagName, "svg")
  187. assert.equal(svgNS.namespaceURI, svgURI)
  188. assert.equal(elemString(svgNS), "<svg></svg>")
  189. assert.equal(emptyNS.tagName, "div")
  190. assert.equal(emptyNS.namespaceURI, null)
  191. assert.equal(elemString(emptyNS), "<div></div>")
  192. assert.equal(nullNS.tagName, "div")
  193. assert.equal(nullNS.namespaceURI, null)
  194. assert.equal(elemString(nullNS), "<div></div>")
  195. assert.equal(undefNS.tagName, "div")
  196. assert.equal(undefNS.namespaceURI, "undefined")
  197. assert.equal(elemString(undefNS), "<div></div>")
  198. assert.equal(caseNS.tagName, "AbC")
  199. assert.equal(caseNS.namespaceURI, "Oops")
  200. assert.equal(elemString(caseNS), "<AbC></AbC>")
  201. assert.equal(htmlNS.tagName, "DIV")
  202. assert.equal(htmlNS.namespaceURI, htmlURI)
  203. assert.equal(elemString(htmlNS), "<div></div>")
  204. assert.end()
  205. })
  206. test("Can insert before", function (assert) {
  207. var rootNode = document.createElement("div")
  208. var child = document.createElement("div")
  209. var newElement = document.createElement("div")
  210. rootNode.appendChild(child)
  211. var el = rootNode.insertBefore(newElement, child)
  212. assert.equal(el, newElement)
  213. assert.equal(rootNode.childNodes.length, 2)
  214. assert.equal(rootNode.childNodes[0], newElement)
  215. assert.equal(rootNode.childNodes[1], child)
  216. cleanup()
  217. assert.end()
  218. })
  219. test("Insert before null appends to end", function (assert) {
  220. var rootNode = document.createElement("div")
  221. var child = document.createElement("div")
  222. var newElement = document.createElement("div")
  223. rootNode.appendChild(child)
  224. var el = rootNode.insertBefore(newElement, null)
  225. assert.equal(el, newElement)
  226. assert.equal(rootNode.childNodes.length, 2)
  227. assert.equal(rootNode.childNodes[0], child)
  228. assert.equal(rootNode.childNodes[1], newElement)
  229. cleanup()
  230. assert.end()
  231. })
  232. test("Node insertions remove node from parent", function (assert) {
  233. var parent = document.createElement("div")
  234. var c1 = document.createElement("div")
  235. var c2 = document.createElement("div")
  236. var c3 = document.createElement("div")
  237. parent.appendChild(c1)
  238. parent.appendChild(c2)
  239. parent.appendChild(c3)
  240. var rootNode = document.createElement("div")
  241. var node1 = rootNode.appendChild(c1)
  242. assert.equal(node1, c1)
  243. assert.equal(parent.childNodes.length, 2)
  244. assert.equal(c1.parentNode, rootNode)
  245. var node2 = rootNode.insertBefore(c2, c1)
  246. assert.equal(node2, c2)
  247. assert.equal(parent.childNodes.length, 1)
  248. assert.equal(c2.parentNode, rootNode)
  249. var node3 = rootNode.replaceChild(c3, c2)
  250. assert.equal(node3, c2)
  251. assert.equal(parent.childNodes.length, 0)
  252. assert.equal(c3.parentNode, rootNode)
  253. assert.equal(c2.parentNode, null)
  254. cleanup()
  255. assert.end()
  256. })
  257. test("input has type=text by default", function (assert) {
  258. var elem = document.createElement("input")
  259. assert.equal(elem.getAttribute("type"), "text");
  260. assert.equal(elemString(elem), "<input type=\"text\" />")
  261. assert.end()
  262. })
  263. test("input type=text can be overridden", function (assert) {
  264. var elem = document.createElement("input")
  265. elem.setAttribute("type", "hidden")
  266. assert.equal(elem.getAttribute("type"), "hidden");
  267. assert.equal(elemString(elem), "<input type=\"hidden\" />")
  268. assert.end()
  269. })
  270. test("can set and get attributes", function (assert) {
  271. var elem = document.createElement("div")
  272. assert.equal(elem.getAttribute("foo"), null)
  273. assert.equal(elemString(elem), "<div></div>")
  274. assert.notOk(elem.hasAttribute('foo'))
  275. elem.setAttribute("foo", "bar")
  276. assert.equal(elem.getAttribute("foo"), "bar")
  277. assert.equal(elemString(elem), "<div foo=\"bar\"></div>")
  278. assert.ok(elem.hasAttribute('foo'))
  279. elem.removeAttribute("foo")
  280. assert.equal(elem.getAttribute("foo"), null)
  281. assert.equal(elemString(elem), "<div></div>")
  282. assert.notOk(elem.hasAttribute('foo'))
  283. assert.end()
  284. })
  285. test("can set and set style properties", function(assert) {
  286. var elem = document.createElement("div")
  287. assert.equal(elemString(elem), "<div></div>")
  288. elem.style.color = "red";
  289. assert.equal(elem.style.color, "red")
  290. assert.equal(elemString(elem), "<div style=\"color:red;\"></div>")
  291. elem.style.background = "blue";
  292. assert.equal(elem.style.color, "red")
  293. assert.equal(elem.style.background, "blue")
  294. assert.equal(elemString(elem),
  295. "<div style=\"color:red;background:blue;\"></div>")
  296. assert.end()
  297. })
  298. test("can set and get namespaced attributes", function(assert) {
  299. var elem = document.createElement("div")
  300. var ns = "http://ns.com/my"
  301. assert.equal(elem.getAttributeNS(ns, "myattr"), blankAttributeNS())
  302. elem.setAttributeNS(ns, "myns:myattr", "the value")
  303. assert.equal(elem.getAttributeNS(ns, "myattr"), "the value")
  304. assert.equal(elemString(elem), '<div myns:myattr="the value"></div>')
  305. elem.removeAttributeNS(ns, "myattr")
  306. assert.equal(elem.getAttributeNS(ns, "myattr"), blankAttributeNS())
  307. // Should work much like get/setAttribute when namespace is null.
  308. assert.equal(elem.getAttributeNS(null, "foo"), blankAttributeNS())
  309. assert.equal(elem.getAttribute("foo"), null)
  310. elem.setAttributeNS(null, "foo", "bar")
  311. assert.equal(elem.getAttributeNS(null, "foo"), "bar")
  312. assert.equal(elem.getAttribute("foo"), "bar")
  313. elem.removeAttributeNS(null, "foo")
  314. assert.equal(elem.getAttributeNS(null, "foo"), blankAttributeNS())
  315. assert.equal(elem.getAttribute("foo"), null)
  316. assert.end()
  317. })
  318. test("can getElementsByTagName", function(assert) {
  319. var parent = document.createElement("div")
  320. var child1 = document.createElement("span")
  321. var child2 = document.createElement("span")
  322. child1.id = "foo"
  323. child2.id = "bar"
  324. child1.appendChild(child2)
  325. parent.appendChild(child1)
  326. document.body.appendChild(parent)
  327. var elems = document.getElementsByTagName("SPAN")
  328. assert.equal(elems.length, 2)
  329. assert.equal(elems[0].id, "foo")
  330. assert.equal(elems[1].id, "bar")
  331. cleanup()
  332. assert.end()
  333. })
  334. test("can getElementsByTagName with *", function(assert) {
  335. document.body.appendChild(document.createElement("div"))
  336. var elems = document.getElementsByTagName("*")
  337. assert.equal(elems.length, 4)
  338. assert.equal(elems[0].tagName, "HTML")
  339. assert.equal(elems[1].tagName, "HEAD")
  340. assert.equal(elems[2].tagName, "BODY")
  341. assert.equal(elems[3].tagName, "DIV")
  342. cleanup()
  343. assert.end()
  344. })
  345. test("getElement* methods search outside the body", function(assert) {
  346. var html = document.documentElement;
  347. assert.equal(document.getElementsByTagName("html")[0], html)
  348. html.id = "foo"
  349. assert.equal(document.getElementById("foo"), html)
  350. html.className = "bar"
  351. assert.equal(document.getElementsByClassName("bar")[0], html)
  352. // cleanup
  353. html.id = ""
  354. html.className = ""
  355. cleanup()
  356. assert.end()
  357. })
  358. test("getElement* methods can be passed to map()", function(assert) {
  359. var e1 = document.createElement("div")
  360. var e2 = document.createElement("span")
  361. document.body.appendChild(e1)
  362. document.body.appendChild(e2)
  363. assert.deepEqual(
  364. ["div", "span"].map(document.getElementsByTagName.bind(document)),
  365. [[e1], [e2]]
  366. )
  367. e1.id = "1"
  368. e2.id = "2"
  369. assert.deepEqual(
  370. ["1", "2"].map(document.getElementById.bind(document)),
  371. [e1, e2]
  372. )
  373. e1.className = "foo"
  374. e2.className = "bar"
  375. assert.deepEqual(
  376. ["foo", "bar"].map(document.getElementsByClassName.bind(document)),
  377. [[e1], [e2]]
  378. )
  379. cleanup()
  380. assert.end()
  381. })
  382. test("can check if it contains an element", function(assert) {
  383. var el = document.createElement("div")
  384. document.body.appendChild(el)
  385. assert.equals(document.contains(document.body), true)
  386. assert.equals(document.contains(el), true)
  387. cleanup()
  388. assert.end()
  389. })
  390. test("can do events", function (assert) {
  391. var x = 1
  392. function incx() { x++ }
  393. var ev = new Event();
  394. ev.initEvent("click");
  395. document.addEventListener("click", incx)
  396. document.dispatchEvent(ev)
  397. assert.equal(x, 2)
  398. document.removeEventListener("click", incx)
  399. document.dispatchEvent(ev)
  400. assert.equal(x, 2)
  401. assert.end()
  402. })
  403. function blankAttributeNS() {
  404. // Most browsers conform to the latest version of the DOM spec,
  405. // which requires `getAttributeNS` to return `null` when the attribute
  406. // doesn't exist, but some browsers (including phantomjs) implement the
  407. // old version of the spec and return an empty string instead, see:
  408. // https://developer.mozilla.org/en-US/docs/Web/API/element.getAttributeNS#Return_value
  409. var div = document.createElement("div")
  410. var blank = div.getAttributeNS(null, "foo")
  411. if (!(blank === null || blank === "")) {
  412. throw "Expected blank attribute to be either null or empty string"
  413. }
  414. return blank;
  415. }
  416. function elemString(element) {
  417. var html = String(element) || "[]"
  418. if (html.charAt(0) === "[") {
  419. html = element.outerHTML
  420. if (!html && !element.parentNode) {
  421. var div = document.createElement("div")
  422. div.appendChild(element)
  423. html = div.innerHTML
  424. div.removeChild(element)
  425. }
  426. }
  427. return html
  428. }
  429. function fragString(fragment) {
  430. var html = String(fragment)
  431. if (html === "[object DocumentFragment]") {
  432. var innerHTML = []
  433. for (var i = 0; i < fragment.childNodes.length; i++) {
  434. var node = fragment.childNodes[i]
  435. innerHTML.push(String(node.outerHTML || node))
  436. }
  437. html = innerHTML.join("")
  438. }
  439. return html
  440. }
  441. }