template_spec.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. var templateParser = require('src/parsers/template')
  2. var parse = templateParser.parseTemplate
  3. var testString = '<div>hello</div><p class="test">world</p>'
  4. describe('Template Parser', function () {
  5. it('should return same if argument is already a fragment', function () {
  6. var frag = document.createDocumentFragment()
  7. var res = parse(frag)
  8. expect(res).toBe(frag)
  9. })
  10. it('should return content if argument is a valid template node', function () {
  11. var templateNode = document.createElement('template')
  12. if (!templateNode.content) {
  13. // mock the content
  14. templateNode.content = document.createDocumentFragment()
  15. }
  16. var res = parse(templateNode)
  17. expect(res).toBe(templateNode.content)
  18. })
  19. it('should parse if argument is a template string', function () {
  20. var res = parse(testString)
  21. expect(res instanceof DocumentFragment).toBeTruthy()
  22. expect(res.childNodes.length).toBe(2)
  23. expect(res.querySelector('.test').textContent).toBe('world')
  24. })
  25. it('should work if the template string doesn\'t contain tags', function () {
  26. var res = parse('hello!')
  27. expect(res instanceof DocumentFragment).toBeTruthy()
  28. expect(res.childNodes.length).toBe(1)
  29. expect(res.firstChild.nodeType).toBe(3) // Text node
  30. })
  31. it('should handle string that contains html entities', function () {
  32. var res = parse('hi&lt;hi')
  33. expect(res instanceof DocumentFragment).toBeTruthy()
  34. expect(res.childNodes.length).toBe(1)
  35. expect(res.firstChild.nodeValue).toBe('hi<hi')
  36. // #1330
  37. res = parse('hello &#x2F; hello')
  38. expect(res instanceof DocumentFragment).toBeTruthy()
  39. expect(res.childNodes.length).toBe(1)
  40. expect(res.firstChild.nodeValue).toBe('hello / hello')
  41. // #2021
  42. res = parse('&#xe604;')
  43. expect(res instanceof DocumentFragment).toBeTruthy()
  44. expect(res.childNodes.length).toBe(1)
  45. expect(res.firstChild.nodeValue).toBe('')
  46. })
  47. it('should parse textContent if argument is a script node', function () {
  48. var node = document.createElement('script')
  49. node.textContent = testString
  50. var res = parse(node)
  51. expect(res instanceof DocumentFragment).toBeTruthy()
  52. expect(res.childNodes.length).toBe(2)
  53. expect(res.querySelector('.test').textContent).toBe('world')
  54. })
  55. it('should parse innerHTML if argument is a normal node', function () {
  56. var node = document.createElement('div')
  57. node.innerHTML = testString
  58. var res = parse(node)
  59. expect(res instanceof DocumentFragment).toBeTruthy()
  60. expect(res.childNodes.length).toBe(2)
  61. expect(res.querySelector('.test').textContent).toBe('world')
  62. })
  63. it('should retrieve and parse if argument is an id selector', function () {
  64. var node = document.createElement('script')
  65. node.setAttribute('id', 'template-test')
  66. node.setAttribute('type', 'x/template')
  67. node.textContent = testString
  68. document.head.appendChild(node)
  69. var res = parse('#template-test')
  70. expect(res instanceof DocumentFragment).toBeTruthy()
  71. expect(res.childNodes.length).toBe(2)
  72. expect(res.querySelector('.test').textContent).toBe('world')
  73. document.head.removeChild(node)
  74. })
  75. it('should work for table elements', function () {
  76. var res = parse('<td>hello</td>')
  77. expect(res instanceof DocumentFragment).toBeTruthy()
  78. expect(res.childNodes.length).toBe(1)
  79. expect(res.firstChild.tagName).toBe('TD')
  80. expect(res.firstChild.textContent).toBe('hello')
  81. })
  82. it('should work for option elements', function () {
  83. var res = parse('<option>hello</option>')
  84. expect(res instanceof DocumentFragment).toBeTruthy()
  85. expect(res.childNodes.length).toBe(1)
  86. expect(res.firstChild.tagName).toBe('OPTION')
  87. expect(res.firstChild.textContent).toBe('hello')
  88. })
  89. it('should work for svg elements', function () {
  90. var res = parse('<circle></circle>')
  91. expect(res instanceof DocumentFragment).toBeTruthy()
  92. expect(res.childNodes.length).toBe(1)
  93. // SVG tagNames should be lowercase because they are XML nodes not HTML
  94. expect(res.firstChild.tagName).toBe('circle')
  95. expect(res.firstChild.namespaceURI).toBe('http://www.w3.org/2000/svg')
  96. })
  97. it('should cache template strings', function () {
  98. var res1 = parse(testString)
  99. var res2 = parse(testString)
  100. expect(res1).toBe(res2)
  101. })
  102. it('should clone', function () {
  103. var res1 = parse(testString, true)
  104. var res2 = parse(testString, true)
  105. expect(res1).not.toBe(res2)
  106. })
  107. it('should cache id selectors', function () {
  108. var node = document.createElement('script')
  109. node.setAttribute('id', 'template-test')
  110. node.setAttribute('type', 'x/template')
  111. node.textContent = '<div>never seen before content</div>'
  112. document.head.appendChild(node)
  113. var res1 = parse('#template-test')
  114. var res2 = parse('#template-test')
  115. expect(res1).toBe(res2)
  116. document.head.removeChild(node)
  117. })
  118. it('should be able to not use id selectors', function () {
  119. var res = parse('#hi', false, true)
  120. expect(res instanceof DocumentFragment).toBeTruthy()
  121. expect(res.firstChild.nodeValue).toBe('#hi')
  122. })
  123. it('should deal with Safari template clone bug', function () {
  124. var a = document.createElement('div')
  125. a.innerHTML = '<template>1</template>'
  126. var c = templateParser.cloneNode(a)
  127. expect(c.firstChild.innerHTML).toBe('1')
  128. })
  129. it('should deal with Safari template clone bug even when nested', function () {
  130. var a = document.createElement('div')
  131. a.innerHTML = '<template><div>1</div><template>2</template></template>'
  132. var c = templateParser.cloneNode(a)
  133. expect(c.firstChild.innerHTML).toBe('<div>1</div><template>2</template>')
  134. })
  135. it('should deal with IE textarea clone bug', function () {
  136. var t = document.createElement('textarea')
  137. t.placeholder = 't'
  138. var c = templateParser.cloneNode(t)
  139. expect(c.value).toBe('')
  140. })
  141. it('should trim empty text nodes and comments', function () {
  142. // string
  143. var res = parse(' <p>test</p> ')
  144. expect(res.childNodes.length).toBe(1)
  145. expect(res.firstChild.tagName).toBe('P')
  146. // nodes
  147. var el = document.createElement('div')
  148. el.innerHTML = '<template> <p>test</p> </template>'
  149. res = parse(el.children[0])
  150. expect(res.childNodes.length).toBe(1)
  151. expect(res.firstChild.tagName).toBe('P')
  152. // comments
  153. res = parse(' <!-- yo --> <p>test</p> <!-- yo --> ')
  154. expect(res.childNodes.length).toBe(1)
  155. expect(res.firstChild.tagName).toBe('P')
  156. })
  157. it('should reuse fragment from cache for the same string template', function () {
  158. var stringTemplate = ' <p>test</p> '
  159. // When parsing a template, adds the created fragment to a cache
  160. var res = parse(stringTemplate)
  161. var newRes = parse(stringTemplate)
  162. expect(newRes).toBe(res)
  163. })
  164. })