component.spec.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import Vue from 'vue'
  2. describe('Component', () => {
  3. it('static', () => {
  4. const vm = new Vue({
  5. template: '<test></test>',
  6. components: {
  7. test: {
  8. data () {
  9. return { a: 123 }
  10. },
  11. template: '<span>{{a}}</span>'
  12. }
  13. }
  14. }).$mount()
  15. expect(vm.$el.tagName).toBe('SPAN')
  16. expect(vm.$el.innerHTML).toBe('123')
  17. })
  18. it('using component in restricted elements', () => {
  19. const vm = new Vue({
  20. template: '<div><table><tbody><test></test></tbody></table></div>',
  21. components: {
  22. test: {
  23. data () {
  24. return { a: 123 }
  25. },
  26. template: '<tr><td>{{a}}</td></tr>'
  27. }
  28. }
  29. }).$mount()
  30. expect(vm.$el.innerHTML).toBe('<table><tbody><tr><td>123</td></tr></tbody></table>')
  31. })
  32. it('"is" attribute', () => {
  33. const vm = new Vue({
  34. template: '<div><table><tbody><tr is="test"></tr></tbody></table></div>',
  35. components: {
  36. test: {
  37. data () {
  38. return { a: 123 }
  39. },
  40. template: '<tr><td>{{a}}</td></tr>'
  41. }
  42. }
  43. }).$mount()
  44. expect(vm.$el.innerHTML).toBe('<table><tbody><tr><td>123</td></tr></tbody></table>')
  45. })
  46. it('inline-template', () => {
  47. const vm = new Vue({
  48. template: '<div><test inline-template><span>{{a}}</span></test></div>',
  49. data: {
  50. a: 'parent'
  51. },
  52. components: {
  53. test: {
  54. data () {
  55. return { a: 'child' }
  56. }
  57. }
  58. }
  59. }).$mount()
  60. expect(vm.$el.innerHTML).toBe('<span>child</span>')
  61. })
  62. it('fragment instance warning', () => {
  63. new Vue({
  64. template: '<test></test>',
  65. components: {
  66. test: {
  67. data () {
  68. return { a: 123, b: 234 }
  69. },
  70. template: '<p>{{a}}</p><p>{{b}}</p>'
  71. }
  72. }
  73. }).$mount()
  74. expect('Component template should contain exactly one root element').toHaveBeenWarned()
  75. })
  76. it('dynamic', done => {
  77. const vm = new Vue({
  78. template: '<component :is="view" :view="view"></component>',
  79. data: {
  80. view: 'view-a'
  81. },
  82. components: {
  83. 'view-a': {
  84. template: '<div>foo</div>',
  85. data () {
  86. return { view: 'a' }
  87. }
  88. },
  89. 'view-b': {
  90. template: '<div>bar</div>',
  91. data () {
  92. return { view: 'b' }
  93. }
  94. }
  95. }
  96. }).$mount()
  97. expect(vm.$el.outerHTML).toBe('<div view="view-a">foo</div>')
  98. vm.view = 'view-b'
  99. waitForUpdate(() => {
  100. expect(vm.$el.outerHTML).toBe('<div view="view-b">bar</div>')
  101. vm.view = ''
  102. })
  103. .then(() => {
  104. expect(vm.$el.nodeType).toBe(3)
  105. expect(vm.$el.data).toBe('')
  106. }).then(done)
  107. })
  108. it(':is using raw component constructor', () => {
  109. const vm = new Vue({
  110. template:
  111. '<div>' +
  112. '<component :is="$options.components.test"></component>' +
  113. '<component :is="$options.components.async"></component>' +
  114. '</div>',
  115. components: {
  116. test: {
  117. template: '<span>foo</span>'
  118. },
  119. async: function (resolve) {
  120. resolve({
  121. template: '<span>bar</span>'
  122. })
  123. }
  124. }
  125. }).$mount()
  126. expect(vm.$el.innerHTML).toBe('<span>foo</span><span>bar</span>')
  127. })
  128. it('dynamic combined with v-for', done => {
  129. const vm = new Vue({
  130. template:
  131. '<div>' +
  132. '<component v-for="c in comps" :is="c.type"></component>' +
  133. '</div>',
  134. data: {
  135. comps: [{ type: 'one' }, { type: 'two' }]
  136. },
  137. components: {
  138. one: {
  139. template: '<span>one</span>'
  140. },
  141. two: {
  142. template: '<span>two</span>'
  143. }
  144. }
  145. }).$mount()
  146. expect(vm.$el.innerHTML).toBe('<span>one</span><span>two</span>')
  147. vm.comps[1].type = 'one'
  148. waitForUpdate(() => {
  149. expect(vm.$el.innerHTML).toBe('<span>one</span><span>one</span>')
  150. }).then(done)
  151. })
  152. it('should compile parent template directives & content in parent scope', done => {
  153. const vm = new Vue({
  154. data: {
  155. ok: false,
  156. message: 'hello'
  157. },
  158. template: '<test v-show="ok">{{message}}</test>',
  159. components: {
  160. test: {
  161. template: '<div><slot></slot> {{message}}</div>',
  162. data () {
  163. return {
  164. message: 'world'
  165. }
  166. }
  167. }
  168. }
  169. }).$mount()
  170. expect(vm.$el.style.display).toBe('none')
  171. expect(vm.$el.textContent).toBe('hello world')
  172. vm.ok = true
  173. vm.message = 'bye'
  174. waitForUpdate(() => {
  175. expect(vm.$el.style.display).toBe('')
  176. expect(vm.$el.textContent).toBe('bye world')
  177. }).then(done)
  178. })
  179. it('parent content + v-if', done => {
  180. const vm = new Vue({
  181. data: {
  182. ok: false,
  183. message: 'hello'
  184. },
  185. template: '<test v-if="ok">{{message}}</test>',
  186. components: {
  187. test: {
  188. template: '<div><slot></slot> {{message}}</div>',
  189. data () {
  190. return {
  191. message: 'world'
  192. }
  193. }
  194. }
  195. }
  196. }).$mount()
  197. expect(vm.$el.textContent).toBe('')
  198. expect(vm.$children.length).toBe(0)
  199. vm.ok = true
  200. waitForUpdate(() => {
  201. expect(vm.$children.length).toBe(1)
  202. expect(vm.$el.textContent).toBe('hello world')
  203. }).then(done)
  204. })
  205. it('props', () => {
  206. const vm = new Vue({
  207. data: {
  208. list: [{ a: 1 }, { a: 2 }]
  209. },
  210. template: '<test :collection="list"></test>',
  211. components: {
  212. test: {
  213. template: '<ul><li v-for="item in collection">{{item.a}}</li></ul>',
  214. props: ['collection']
  215. }
  216. }
  217. }).$mount()
  218. expect(vm.$el.outerHTML).toBe('<ul><li>1</li><li>2</li></ul>')
  219. })
  220. it('not found component should not throw', () => {
  221. expect(function () {
  222. new Vue({
  223. template: '<div is="non-existent"></div>'
  224. })
  225. }).not.toThrow()
  226. })
  227. })