content_spec.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. var Vue = require('../../../../src/vue')
  2. var _ = require('../../../../src/util')
  3. describe('Content Transclusion', function () {
  4. var el, vm, options
  5. beforeEach(function () {
  6. el = document.createElement('div')
  7. options = {
  8. el: el
  9. }
  10. })
  11. function mount () {
  12. vm = new Vue(options)
  13. }
  14. it('no content', function () {
  15. options.template = '<div><content></content></div>'
  16. mount()
  17. expect(el.firstChild.childNodes.length).toBe(0)
  18. })
  19. it('default content', function () {
  20. el.innerHTML = '<p>hi</p>'
  21. options.template = '<div><content></content></div>'
  22. mount()
  23. expect(el.firstChild.tagName).toBe('DIV')
  24. expect(el.firstChild.firstChild.tagName).toBe('P')
  25. expect(el.firstChild.firstChild.textContent).toBe('hi')
  26. })
  27. it('fallback content', function () {
  28. options.template = '<content><p>fallback</p></content>'
  29. mount()
  30. expect(el.firstChild.tagName).toBe('P')
  31. expect(el.firstChild.textContent).toBe('fallback')
  32. })
  33. it('fallback content with multiple select', function () {
  34. el.innerHTML = '<p class="b">select b</p>'
  35. options.template = '<content select=".a"><p>fallback a</p></content><content select=".b">fallback b</content>'
  36. mount()
  37. expect(el.childNodes.length).toBe(2)
  38. expect(el.firstChild.textContent).toBe('fallback a')
  39. expect(el.lastChild.textContent).toBe('select b')
  40. })
  41. it('content transclusion with replace', function () {
  42. el.innerHTML = '<p>hi</p>'
  43. options.template = '<div><div><content></content></div></div>'
  44. options.replace = true
  45. mount()
  46. var res = vm.$el
  47. expect(res).not.toBe(el)
  48. expect(res.firstChild.tagName).toBe('DIV')
  49. expect(res.firstChild.firstChild.tagName).toBe('P')
  50. expect(res.firstChild.firstChild.textContent).toBe('hi')
  51. })
  52. it('block instance content transclusion', function () {
  53. el.innerHTML = '<p>hi</p><span>ho</span>'
  54. options.template = '<div></div><content select="p"></content><content select="span"></content>'
  55. options.replace = true
  56. mount()
  57. expect(getChild(1).tagName).toBe('DIV')
  58. expect(getChild(2).tagName).toBe('P')
  59. expect(getChild(3).tagName).toBe('SPAN')
  60. function getChild (n) {
  61. var el = vm._blockStart
  62. while (n--) {
  63. el = el.nextSibling
  64. }
  65. return el
  66. }
  67. })
  68. it('select should only match children', function () {
  69. el.innerHTML = '<p class="b">select b</p><span><p class="b">nested b</p></span><span><p class="c">nested c</p></span>'
  70. options.template = '<content select=".a"><p>fallback a</p></content><content select=".b">fallback b</content><content select=".c">fallback c</content>'
  71. mount()
  72. expect(el.childNodes.length).toBe(3)
  73. expect(el.firstChild.textContent).toBe('fallback a')
  74. expect(el.childNodes[1].textContent).toBe('select b')
  75. expect(el.lastChild.textContent).toBe('fallback c')
  76. })
  77. it('should accept expressions in selectors', function () {
  78. el.innerHTML = '<p>one</p><p>two</p>'
  79. options.template = '<content select="p:nth-child({{i}})"></content>'
  80. options.data = {
  81. i: 2
  82. }
  83. mount()
  84. expect(el.innerHTML).toBe('<p>two</p>')
  85. })
  86. it('content should be dynamic and compiled in parent scope', function (done) {
  87. var vm = new Vue({
  88. el: el,
  89. data: {
  90. msg: 'hello'
  91. },
  92. template: '<test>{{msg}}</test>',
  93. components: {
  94. test: {
  95. template: '<content></content>'
  96. }
  97. }
  98. })
  99. expect(el.innerHTML).toBe('<test>hello</test>')
  100. vm.msg = 'what'
  101. _.nextTick(function () {
  102. expect(el.innerHTML).toBe('<test>what</test>')
  103. done()
  104. })
  105. })
  106. it('v-if with content transclusion', function (done) {
  107. var vm = new Vue({
  108. el: el,
  109. data: {
  110. a: 1,
  111. show: true
  112. },
  113. template: '<test show="{{show}}">{{a}}</test>',
  114. components: {
  115. test: {
  116. props: ['show'],
  117. template: '<div v-if="show"><content></cotent></div>'
  118. }
  119. }
  120. })
  121. expect(el.textContent).toBe('1')
  122. vm.a = 2
  123. _.nextTick(function () {
  124. expect(el.textContent).toBe('2')
  125. vm.show = false
  126. _.nextTick(function () {
  127. expect(el.textContent).toBe('')
  128. vm.show = true
  129. vm.a = 3
  130. _.nextTick(function () {
  131. expect(el.textContent).toBe('3')
  132. done()
  133. })
  134. })
  135. })
  136. })
  137. it('inline v-repeat', function () {
  138. el.innerHTML = '<p>1</p><p>2</p><p>3</p>'
  139. var vm = new Vue({
  140. el: el,
  141. template: '<div v-repeat="list"><content select="p:nth-child({{$index + 1}})"></content></div>',
  142. data: {
  143. list: 0
  144. },
  145. beforeCompile: function () {
  146. this.list = this.$options._content.querySelectorAll('p').length
  147. }
  148. })
  149. expect(el.innerHTML).toBe('<div><p>1</p></div><div><p>2</p></div><div><p>3</p></div>')
  150. })
  151. it('v-repeat + component + parent directive + transclusion', function (done) {
  152. var vm = new Vue({
  153. el: el,
  154. template: '<test v-repeat="list" v-class="cls">{{msg}}</test>',
  155. data: {
  156. cls: 'parent',
  157. msg: 'hi',
  158. list: [{a:1},{a:2},{a:3}]
  159. },
  160. components: {
  161. test: {
  162. replace: true,
  163. template: '<div class="child">{{a}} <content></content></div>'
  164. }
  165. }
  166. })
  167. var markup = vm.list.map(function (item) {
  168. return '<div class="child parent">' + item.a + ' hi</div>'
  169. }).join('')
  170. expect(el.innerHTML).toBe(markup)
  171. vm.msg = 'ho'
  172. markup = vm.list.map(function (item) {
  173. return '<div class="child parent">' + item.a + ' ho</div>'
  174. }).join('')
  175. _.nextTick(function () {
  176. expect(el.innerHTML).toBe(markup)
  177. done()
  178. })
  179. })
  180. it('nested transclusions', function (done) {
  181. vm = new Vue({
  182. el: el,
  183. template:
  184. '<testa>' +
  185. '<testb>' +
  186. '<div v-repeat="list">{{$value}}</div>' +
  187. '</testb>' +
  188. '</testa>',
  189. data: {
  190. list: [1,2]
  191. },
  192. components: {
  193. testa: { template: '<content></content>' },
  194. testb: { template: '<content></content>' }
  195. }
  196. })
  197. expect(el.innerHTML).toBe(
  198. '<testa><testb>' +
  199. '<div>1</div><div>2</div>' +
  200. '</testb></testa>'
  201. )
  202. vm.list.push(3)
  203. _.nextTick(function () {
  204. expect(el.innerHTML).toBe(
  205. '<testa><testb>' +
  206. '<div>1</div><div>2</div><div>3</div>' +
  207. '</testb></testa>'
  208. )
  209. done()
  210. })
  211. })
  212. })