component-keep-alive.spec.js 8.6 KB

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