content_spec.js 6.2 KB

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