component-keep-alive.spec.js 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. import Vue from 'vue'
  2. import injectStyles from '../transition/inject-styles'
  3. import { isIE9 } from 'web/util/index'
  4. import { nextFrame } from 'web/runtime/modules/transition'
  5. describe('Component keep-alive', () => {
  6. const duration = injectStyles()
  7. let components, one, two, el
  8. beforeEach(() => {
  9. one = {
  10. template: '<div>one</div>',
  11. created: jasmine.createSpy('one created'),
  12. mounted: jasmine.createSpy('one mounted'),
  13. activated: jasmine.createSpy('one activated'),
  14. deactivated: jasmine.createSpy('one deactivated')
  15. }
  16. two = {
  17. template: '<div>two</div>',
  18. created: jasmine.createSpy('two created'),
  19. mounted: jasmine.createSpy('two mounted'),
  20. activated: jasmine.createSpy('two activated'),
  21. deactivated: jasmine.createSpy('two deactivated')
  22. }
  23. components = {
  24. one,
  25. two
  26. }
  27. el = document.createElement('div')
  28. document.body.appendChild(el)
  29. })
  30. function assertHookCalls (component, callCounts) {
  31. expect([
  32. component.created.calls.count(),
  33. component.mounted.calls.count(),
  34. component.activated.calls.count(),
  35. component.deactivated.calls.count()
  36. ]).toEqual(callCounts)
  37. }
  38. it('should work', done => {
  39. const vm = new Vue({
  40. template: '<div><component :is="view" keep-alive></component></div>',
  41. data: {
  42. view: 'one'
  43. },
  44. components
  45. }).$mount()
  46. expect(vm.$el.textContent).toBe('one')
  47. assertHookCalls(one, [1, 1, 1, 0])
  48. assertHookCalls(two, [0, 0, 0, 0])
  49. vm.view = 'two'
  50. waitForUpdate(() => {
  51. expect(vm.$el.textContent).toBe('two')
  52. assertHookCalls(one, [1, 1, 1, 1])
  53. assertHookCalls(two, [1, 1, 1, 0])
  54. vm.view = 'one'
  55. }).then(() => {
  56. expect(vm.$el.textContent).toBe('one')
  57. assertHookCalls(one, [1, 1, 2, 1])
  58. assertHookCalls(two, [1, 1, 1, 1])
  59. vm.view = 'two'
  60. }).then(() => {
  61. expect(vm.$el.textContent).toBe('two')
  62. assertHookCalls(one, [1, 1, 2, 2])
  63. assertHookCalls(two, [1, 1, 2, 1])
  64. }).then(done)
  65. })
  66. if (!isIE9) {
  67. it('with transition-mode out-in', done => {
  68. let next
  69. const vm = new Vue({
  70. template: `<div>
  71. <component
  72. :is="view"
  73. class="test"
  74. keep-alive
  75. transition="test"
  76. transition-mode="out-in">
  77. </component>
  78. </div>`,
  79. data: {
  80. view: 'one'
  81. },
  82. components,
  83. transitions: {
  84. test: {
  85. afterLeave () {
  86. next()
  87. }
  88. }
  89. }
  90. }).$mount(el)
  91. expect(vm.$el.textContent).toBe('one')
  92. assertHookCalls(one, [1, 1, 1, 0])
  93. assertHookCalls(two, [0, 0, 0, 0])
  94. vm.view = 'two'
  95. waitForUpdate(() => {
  96. expect(vm.$el.innerHTML).toBe(
  97. '<div class="test test-leave">one</div>'
  98. )
  99. assertHookCalls(one, [1, 1, 1, 1])
  100. assertHookCalls(two, [0, 0, 0, 0])
  101. }).thenWaitFor(nextFrame).then(() => {
  102. expect(vm.$el.innerHTML).toBe(
  103. '<div class="test test-leave-active">one</div>'
  104. )
  105. }).thenWaitFor(_next => { next = _next }).then(() => {
  106. expect(vm.$el.innerHTML).toBe('')
  107. }).thenWaitFor(nextFrame).then(() => {
  108. expect(vm.$el.innerHTML).toBe(
  109. '<div class="test test-enter">two</div>'
  110. )
  111. assertHookCalls(one, [1, 1, 1, 1])
  112. assertHookCalls(two, [1, 1, 1, 0])
  113. }).thenWaitFor(nextFrame).then(() => {
  114. expect(vm.$el.innerHTML).toBe(
  115. '<div class="test test-enter-active">two</div>'
  116. )
  117. }).thenWaitFor(duration + 10).then(() => {
  118. expect(vm.$el.innerHTML).toBe(
  119. '<div class="test">two</div>'
  120. )
  121. assertHookCalls(one, [1, 1, 1, 1])
  122. assertHookCalls(two, [1, 1, 1, 0])
  123. }).then(() => {
  124. vm.view = 'one'
  125. }).then(() => {
  126. expect(vm.$el.innerHTML).toBe(
  127. '<div class="test test-leave">two</div>'
  128. )
  129. assertHookCalls(one, [1, 1, 1, 1])
  130. assertHookCalls(two, [1, 1, 1, 1])
  131. }).thenWaitFor(nextFrame).then(() => {
  132. expect(vm.$el.innerHTML).toBe(
  133. '<div class="test test-leave-active">two</div>'
  134. )
  135. }).thenWaitFor(_next => { next = _next }).then(() => {
  136. expect(vm.$el.innerHTML).toBe('')
  137. }).thenWaitFor(nextFrame).then(() => {
  138. expect(vm.$el.innerHTML).toBe(
  139. '<div class="test test-enter">one</div>'
  140. )
  141. assertHookCalls(one, [1, 1, 2, 1])
  142. assertHookCalls(two, [1, 1, 1, 1])
  143. }).thenWaitFor(nextFrame).then(() => {
  144. expect(vm.$el.innerHTML).toBe(
  145. '<div class="test test-enter-active">one</div>'
  146. )
  147. }).thenWaitFor(duration + 10).then(() => {
  148. expect(vm.$el.innerHTML).toBe(
  149. '<div class="test">one</div>'
  150. )
  151. assertHookCalls(one, [1, 1, 2, 1])
  152. assertHookCalls(two, [1, 1, 1, 1])
  153. }).then(done)
  154. })
  155. it('with transition-mode in-out', done => {
  156. let next
  157. const vm = new Vue({
  158. template: `<div>
  159. <component
  160. :is="view"
  161. class="test"
  162. keep-alive
  163. transition="test"
  164. transition-mode="in-out">
  165. </component>
  166. </div>`,
  167. data: {
  168. view: 'one'
  169. },
  170. components,
  171. transitions: {
  172. test: {
  173. afterEnter () {
  174. next()
  175. }
  176. }
  177. }
  178. }).$mount(el)
  179. expect(vm.$el.textContent).toBe('one')
  180. assertHookCalls(one, [1, 1, 1, 0])
  181. assertHookCalls(two, [0, 0, 0, 0])
  182. vm.view = 'two'
  183. waitForUpdate(() => {
  184. expect(vm.$el.innerHTML).toBe(
  185. '<div class="test">one</div>' +
  186. '<div class="test test-enter">two</div>'
  187. )
  188. assertHookCalls(one, [1, 1, 1, 1])
  189. assertHookCalls(two, [1, 1, 1, 0])
  190. }).thenWaitFor(nextFrame).then(() => {
  191. expect(vm.$el.innerHTML).toBe(
  192. '<div class="test">one</div>' +
  193. '<div class="test test-enter-active">two</div>'
  194. )
  195. }).thenWaitFor(_next => { next = _next }).then(() => {
  196. expect(vm.$el.innerHTML).toBe(
  197. '<div class="test">one</div>' +
  198. '<div class="test">two</div>'
  199. )
  200. }).then(() => {
  201. expect(vm.$el.innerHTML).toBe(
  202. '<div class="test test-leave">one</div>' +
  203. '<div class="test">two</div>'
  204. )
  205. }).thenWaitFor(nextFrame).then(() => {
  206. expect(vm.$el.innerHTML).toBe(
  207. '<div class="test test-leave-active">one</div>' +
  208. '<div class="test">two</div>'
  209. )
  210. }).thenWaitFor(duration + 10).then(() => {
  211. expect(vm.$el.innerHTML).toBe(
  212. '<div class="test">two</div>'
  213. )
  214. assertHookCalls(one, [1, 1, 1, 1])
  215. assertHookCalls(two, [1, 1, 1, 0])
  216. }).then(() => {
  217. vm.view = 'one'
  218. }).then(() => {
  219. expect(vm.$el.innerHTML).toBe(
  220. '<div class="test">two</div>' +
  221. '<div class="test test-enter">one</div>'
  222. )
  223. assertHookCalls(one, [1, 1, 2, 1])
  224. assertHookCalls(two, [1, 1, 1, 1])
  225. }).thenWaitFor(nextFrame).then(() => {
  226. expect(vm.$el.innerHTML).toBe(
  227. '<div class="test">two</div>' +
  228. '<div class="test test-enter-active">one</div>'
  229. )
  230. }).thenWaitFor(_next => { next = _next }).then(() => {
  231. expect(vm.$el.innerHTML).toBe(
  232. '<div class="test">two</div>' +
  233. '<div class="test">one</div>'
  234. )
  235. }).then(() => {
  236. expect(vm.$el.innerHTML).toBe(
  237. '<div class="test test-leave">two</div>' +
  238. '<div class="test">one</div>'
  239. )
  240. }).thenWaitFor(nextFrame).then(() => {
  241. expect(vm.$el.innerHTML).toBe(
  242. '<div class="test test-leave-active">two</div>' +
  243. '<div class="test">one</div>'
  244. )
  245. }).thenWaitFor(duration + 10).then(() => {
  246. expect(vm.$el.innerHTML).toBe(
  247. '<div class="test">one</div>'
  248. )
  249. assertHookCalls(one, [1, 1, 2, 1])
  250. assertHookCalls(two, [1, 1, 1, 1])
  251. }).then(done)
  252. })
  253. }
  254. })