component_spec.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // patch inDoc
  2. require('../../lib/indoc_patch')
  3. var _ = require('../../../../src/util')
  4. var Vue = require('../../../../src/vue')
  5. if (_.inBrowser) {
  6. describe('v-component', function () {
  7. var el
  8. beforeEach(function () {
  9. el = document.createElement('div')
  10. document.body.appendChild(el)
  11. spyOn(_, 'warn')
  12. })
  13. afterEach(function () {
  14. document.body.removeChild(el)
  15. })
  16. it('static', function () {
  17. var vm = new Vue({
  18. el: el,
  19. template: '<div v-component="test"></div>',
  20. components: {
  21. test: {
  22. data: function () {
  23. return { a: 123 }
  24. },
  25. template: '{{a}}'
  26. }
  27. }
  28. })
  29. expect(el.innerHTML).toBe('<div>123</div><!--v-component-->')
  30. })
  31. it('replace', function () {
  32. var vm = new Vue({
  33. el: el,
  34. template: '<div v-component="test"></div>',
  35. components: {
  36. test: {
  37. replace: true,
  38. data: function () {
  39. return { a: 123 }
  40. },
  41. template: '<p>{{a}}</p>'
  42. }
  43. }
  44. })
  45. expect(el.innerHTML).toBe('<p>123</p><!--v-component-->')
  46. })
  47. it('inline-template', function () {
  48. var vm = new Vue({
  49. el: el,
  50. template: '<div v-component="test" inline-template>{{a}}</div>',
  51. data: {
  52. a: 'parent'
  53. },
  54. components: {
  55. test: {
  56. data: function () {
  57. return { a: 'child' }
  58. },
  59. template: 'child option template'
  60. }
  61. }
  62. })
  63. expect(el.innerHTML).toBe('<div>child</div><!--v-component-->')
  64. })
  65. it('block replace', function () {
  66. var vm = new Vue({
  67. el: el,
  68. template: '<div v-component="test"></div>',
  69. components: {
  70. test: {
  71. replace: true,
  72. data: function () {
  73. return { a: 123, b: 234 }
  74. },
  75. template: '<p>{{a}}</p><p>{{b}}</p>'
  76. }
  77. }
  78. })
  79. expect(el.innerHTML).toBe('<!--v-start--><p>123</p><p>234</p><!--v-end--><!--v-component-->')
  80. })
  81. it('dynamic', function (done) {
  82. var vm = new Vue({
  83. el: el,
  84. template: '<div v-component="{{view}}" v-attr="view:view"></div>',
  85. data: {
  86. view: 'a'
  87. },
  88. components: {
  89. a: {
  90. template: 'AAA',
  91. data: function () {
  92. return { view: 'a' }
  93. }
  94. },
  95. b: {
  96. template: 'BBB',
  97. data: function () {
  98. return { view: 'b' }
  99. }
  100. }
  101. }
  102. })
  103. expect(el.innerHTML).toBe('<div view="a">AAA</div><!--v-component-->')
  104. vm.view = 'b'
  105. _.nextTick(function () {
  106. expect(el.innerHTML).toBe('<div view="b">BBB</div><!--v-component-->')
  107. vm.view = ''
  108. _.nextTick(function () {
  109. expect(el.innerHTML).toBe('<!--v-component-->')
  110. done()
  111. })
  112. })
  113. })
  114. it('keep-alive', function (done) {
  115. var spyA = jasmine.createSpy()
  116. var spyB = jasmine.createSpy()
  117. var vm = new Vue({
  118. el: el,
  119. template: '<div v-component="{{view}}" keep-alive></div>',
  120. data: {
  121. view: 'a'
  122. },
  123. components: {
  124. a: {
  125. created: spyA,
  126. template: 'AAA'
  127. },
  128. b: {
  129. created: spyB,
  130. template: 'BBB'
  131. }
  132. }
  133. })
  134. expect(el.innerHTML).toBe('<div>AAA</div><!--v-component-->')
  135. expect(spyA.calls.count()).toBe(1)
  136. expect(spyB.calls.count()).toBe(0)
  137. vm.view = 'b'
  138. _.nextTick(function () {
  139. expect(el.innerHTML).toBe('<div>BBB</div><!--v-component-->')
  140. expect(spyA.calls.count()).toBe(1)
  141. expect(spyB.calls.count()).toBe(1)
  142. vm.view = 'a'
  143. _.nextTick(function () {
  144. expect(el.innerHTML).toBe('<div>AAA</div><!--v-component-->')
  145. expect(spyA.calls.count()).toBe(1)
  146. expect(spyB.calls.count()).toBe(1)
  147. vm.view = 'b'
  148. _.nextTick(function () {
  149. expect(el.innerHTML).toBe('<div>BBB</div><!--v-component-->')
  150. expect(spyA.calls.count()).toBe(1)
  151. expect(spyB.calls.count()).toBe(1)
  152. done()
  153. })
  154. })
  155. })
  156. })
  157. it('should compile parent template directives & content in parent scope', function (done) {
  158. var vm = new Vue({
  159. el: el,
  160. data: {
  161. ok: false,
  162. message: 'hello'
  163. },
  164. template: '<div v-component="test" v-show="ok">{{message}}</div>',
  165. components: {
  166. test: {
  167. template: '<div><content></content> {{message}}</div>',
  168. replace: true,
  169. data: function () {
  170. return {
  171. message: 'world'
  172. }
  173. }
  174. }
  175. }
  176. })
  177. expect(el.firstChild.style.display).toBe('none')
  178. expect(el.firstChild.textContent).toBe('hello world')
  179. vm.ok = true
  180. vm.message = 'bye'
  181. _.nextTick(function () {
  182. expect(el.firstChild.style.display).toBe('')
  183. expect(el.firstChild.textContent).toBe('bye world')
  184. done()
  185. })
  186. })
  187. it('parent content + v-if', function (done) {
  188. var vm = new Vue({
  189. el: el,
  190. data: {
  191. ok: false,
  192. message: 'hello'
  193. },
  194. template: '<div v-component="test" v-if="ok">{{message}}</div>',
  195. components: {
  196. test: {
  197. template: '<content></content> {{message}}',
  198. data: function () {
  199. return {
  200. message: 'world'
  201. }
  202. }
  203. }
  204. }
  205. })
  206. expect(el.textContent).toBe('')
  207. expect(vm._children.length).toBe(0)
  208. expect(vm._directives.length).toBe(1) // v-if
  209. vm.ok = true
  210. _.nextTick(function () {
  211. expect(vm._children.length).toBe(1)
  212. expect(vm._directives.length).toBe(3) // v-if, v-component, v-text
  213. expect(el.textContent).toBe('hello world')
  214. done()
  215. })
  216. })
  217. it('paramAttributes', function () {
  218. var vm = new Vue({
  219. el: el,
  220. data: {
  221. list: [{a:1}, {a:2}]
  222. },
  223. template: '<ul v-component="test" collection="{{list}}"></ul>',
  224. components: {
  225. test: {
  226. template: '<li v-repeat="collection">{{a}}</li>',
  227. paramAttributes: ['collection']
  228. }
  229. }
  230. })
  231. expect(el.innerHTML).toBe('<ul><li>1</li><li>2</li><!--v-repeat--></ul><!--v-component-->')
  232. })
  233. it('wait-for', function (done) {
  234. var vm = new Vue({
  235. el: el,
  236. data: {
  237. view: 'a'
  238. },
  239. template: '<div v-component="{{view}}" wait-for="ok"></div>',
  240. components: {
  241. a: {
  242. template: 'AAA'
  243. },
  244. b: {
  245. template: 'BBB'
  246. }
  247. }
  248. })
  249. vm._children[0].$emit('ok')
  250. vm.view = 'b'
  251. _.nextTick(function () {
  252. expect(el.textContent).toBe('AAA')
  253. // old vm is already removed, this is the new vm
  254. vm._children[0].$emit('ok')
  255. expect(el.textContent).toBe('BBB')
  256. done()
  257. })
  258. })
  259. it('transition-mode: in-out', function (done) {
  260. var spy1 = jasmine.createSpy('enter')
  261. var spy2 = jasmine.createSpy('leave')
  262. var next
  263. var vm = new Vue({
  264. el: el,
  265. data: {
  266. view: 'a'
  267. },
  268. template: '<div v-component="{{view}}" v-transition="test" transition-mode="in-out"></div>',
  269. components: {
  270. a: { template: 'AAA' },
  271. b: { template: 'BBB' }
  272. },
  273. transitions: {
  274. test: {
  275. enter: function (el, done) {
  276. spy1()
  277. next = done
  278. },
  279. leave: function (el, done) {
  280. spy2()
  281. done()
  282. }
  283. }
  284. }
  285. })
  286. expect(el.textContent).toBe('AAA')
  287. vm.view = 'b'
  288. _.nextTick(function () {
  289. expect(spy1).toHaveBeenCalled()
  290. expect(spy2).not.toHaveBeenCalled()
  291. expect(el.textContent).toBe('AAABBB')
  292. next()
  293. expect(spy2).toHaveBeenCalled()
  294. expect(el.textContent).toBe('BBB')
  295. done()
  296. })
  297. })
  298. it('transition-mode: out-in', function (done) {
  299. var spy1 = jasmine.createSpy('enter')
  300. var spy2 = jasmine.createSpy('leave')
  301. var next
  302. var vm = new Vue({
  303. el: el,
  304. data: {
  305. view: 'a'
  306. },
  307. template: '<div v-component="{{view}}" v-transition="test" transition-mode="out-in"></div>',
  308. components: {
  309. a: { template: 'AAA' },
  310. b: { template: 'BBB' }
  311. },
  312. transitions: {
  313. test: {
  314. enter: function (el, done) {
  315. spy2()
  316. done()
  317. },
  318. leave: function (el, done) {
  319. spy1()
  320. next = done
  321. }
  322. }
  323. }
  324. })
  325. expect(el.textContent).toBe('AAA')
  326. vm.view = 'b'
  327. _.nextTick(function () {
  328. expect(spy1).toHaveBeenCalled()
  329. expect(spy2).not.toHaveBeenCalled()
  330. expect(el.textContent).toBe('AAA')
  331. next()
  332. expect(spy2).toHaveBeenCalled()
  333. expect(el.textContent).toBe('BBB')
  334. done()
  335. })
  336. })
  337. it('teardown', function (done) {
  338. var vm = new Vue({
  339. el: el,
  340. template: '<div v-component="{{view}}" keep-alive></div>',
  341. data: {
  342. view: 'test'
  343. },
  344. components: {
  345. test: {},
  346. test2: {}
  347. }
  348. })
  349. vm.view = 'test2'
  350. _.nextTick(function () {
  351. expect(vm._children.length).toBe(2)
  352. var child = vm._children[0]
  353. var child2 = vm._children[1]
  354. vm._directives[0].unbind()
  355. expect(vm._directives[0].cache).toBeNull()
  356. expect(vm._children.length).toBe(0)
  357. expect(child._isDestroyed).toBe(true)
  358. expect(child2._isDestroyed).toBe(true)
  359. done()
  360. })
  361. })
  362. it('already mounted warn', function () {
  363. el.setAttribute('v-component', 'test')
  364. var vm = new Vue({
  365. el: el
  366. })
  367. expect(_.warn).toHaveBeenCalled()
  368. })
  369. })
  370. }