transition.spec.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171
  1. import Vue from 'vue'
  2. import injectStyles from './inject-styles'
  3. import { isIE9 } from 'core/util/env'
  4. import { nextFrame } from 'web/runtime/transition-util'
  5. if (!isIE9) {
  6. describe('Transition basic', () => {
  7. const { duration, buffer } = injectStyles()
  8. const explicitDuration = duration * 2
  9. let el
  10. beforeEach(() => {
  11. el = document.createElement('div')
  12. document.body.appendChild(el)
  13. })
  14. it('basic transition', done => {
  15. const vm = new Vue({
  16. template: '<div><transition><div v-if="ok" class="test">foo</div></transition></div>',
  17. data: { ok: true }
  18. }).$mount(el)
  19. // should not apply transition on initial render by default
  20. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  21. vm.ok = false
  22. waitForUpdate(() => {
  23. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  24. }).thenWaitFor(nextFrame).then(() => {
  25. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  26. }).thenWaitFor(duration + buffer).then(() => {
  27. expect(vm.$el.children.length).toBe(0)
  28. vm.ok = true
  29. }).then(() => {
  30. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  31. }).thenWaitFor(nextFrame).then(() => {
  32. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  33. }).thenWaitFor(duration + buffer).then(() => {
  34. expect(vm.$el.children[0].className).toBe('test')
  35. }).then(done)
  36. })
  37. it('named transition', done => {
  38. const vm = new Vue({
  39. template: '<div><transition name="test"><div v-if="ok" class="test">foo</div></transition></div>',
  40. data: { ok: true }
  41. }).$mount(el)
  42. // should not apply transition on initial render by default
  43. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  44. vm.ok = false
  45. waitForUpdate(() => {
  46. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  47. }).thenWaitFor(nextFrame).then(() => {
  48. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  49. }).thenWaitFor(duration + buffer).then(() => {
  50. expect(vm.$el.children.length).toBe(0)
  51. vm.ok = true
  52. }).then(() => {
  53. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  54. }).thenWaitFor(nextFrame).then(() => {
  55. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  56. }).thenWaitFor(duration + buffer).then(() => {
  57. expect(vm.$el.children[0].className).toBe('test')
  58. }).then(done)
  59. })
  60. it('custom transition classes', done => {
  61. const vm = new Vue({
  62. template: `
  63. <div>
  64. <transition
  65. enter-class="hello"
  66. enter-active-class="hello-active"
  67. enter-to-class="hello-to"
  68. leave-class="bye"
  69. leave-to-class="bye-to"
  70. leave-active-class="byebye active more ">
  71. <div v-if="ok" class="test">foo</div>
  72. </transition>
  73. </div>
  74. `,
  75. data: { ok: true }
  76. }).$mount(el)
  77. // should not apply transition on initial render by default
  78. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  79. vm.ok = false
  80. waitForUpdate(() => {
  81. expect(vm.$el.children[0].className).toBe('test bye byebye active more')
  82. }).thenWaitFor(nextFrame).then(() => {
  83. expect(vm.$el.children[0].className).toBe('test byebye active more bye-to')
  84. }).thenWaitFor(duration + buffer).then(() => {
  85. expect(vm.$el.children.length).toBe(0)
  86. vm.ok = true
  87. }).then(() => {
  88. expect(vm.$el.children[0].className).toBe('test hello hello-active')
  89. }).thenWaitFor(nextFrame).then(() => {
  90. expect(vm.$el.children[0].className).toBe('test hello-active hello-to')
  91. }).thenWaitFor(duration + buffer).then(() => {
  92. expect(vm.$el.children[0].className).toBe('test')
  93. }).then(done)
  94. })
  95. it('dynamic transition', done => {
  96. const vm = new Vue({
  97. template: `
  98. <div>
  99. <transition :name="trans">
  100. <div v-if="ok" class="test">foo</div>
  101. </transition>
  102. </div>
  103. `,
  104. data: {
  105. ok: true,
  106. trans: 'test'
  107. }
  108. }).$mount(el)
  109. // should not apply transition on initial render by default
  110. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  111. vm.ok = false
  112. waitForUpdate(() => {
  113. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  114. }).thenWaitFor(nextFrame).then(() => {
  115. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  116. }).thenWaitFor(duration + buffer).then(() => {
  117. expect(vm.$el.children.length).toBe(0)
  118. vm.ok = true
  119. vm.trans = 'changed'
  120. }).then(() => {
  121. expect(vm.$el.children[0].className).toBe('test changed-enter changed-enter-active')
  122. }).thenWaitFor(nextFrame).then(() => {
  123. expect(vm.$el.children[0].className).toBe('test changed-enter-active changed-enter-to')
  124. }).thenWaitFor(duration + buffer).then(() => {
  125. expect(vm.$el.children[0].className).toBe('test')
  126. }).then(done)
  127. })
  128. it('inline transition object', done => {
  129. const enter = jasmine.createSpy('enter')
  130. const leave = jasmine.createSpy('leave')
  131. const vm = new Vue({
  132. render (h) {
  133. return h('div', null, [
  134. h('transition', {
  135. props: {
  136. name: 'inline',
  137. enterClass: 'hello',
  138. enterToClass: 'hello-to',
  139. enterActiveClass: 'hello-active',
  140. leaveClass: 'bye',
  141. leaveToClass: 'bye-to',
  142. leaveActiveClass: 'byebye active'
  143. },
  144. on: {
  145. enter,
  146. leave
  147. }
  148. }, this.ok ? [h('div', { class: 'test' }, 'foo')] : undefined)
  149. ])
  150. },
  151. data: { ok: true }
  152. }).$mount(el)
  153. // should not apply transition on initial render by default
  154. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  155. vm.ok = false
  156. waitForUpdate(() => {
  157. expect(vm.$el.children[0].className).toBe('test bye byebye active')
  158. expect(leave).toHaveBeenCalled()
  159. }).thenWaitFor(nextFrame).then(() => {
  160. expect(vm.$el.children[0].className).toBe('test byebye active bye-to')
  161. }).thenWaitFor(duration + buffer).then(() => {
  162. expect(vm.$el.children.length).toBe(0)
  163. vm.ok = true
  164. }).then(() => {
  165. expect(vm.$el.children[0].className).toBe('test hello hello-active')
  166. expect(enter).toHaveBeenCalled()
  167. }).thenWaitFor(nextFrame).then(() => {
  168. expect(vm.$el.children[0].className).toBe('test hello-active hello-to')
  169. }).thenWaitFor(duration + buffer).then(() => {
  170. expect(vm.$el.children[0].className).toBe('test')
  171. }).then(done)
  172. })
  173. it('transition events', done => {
  174. const onLeaveSpy = jasmine.createSpy('leave')
  175. const onEnterSpy = jasmine.createSpy('enter')
  176. const beforeLeaveSpy = jasmine.createSpy('beforeLeave')
  177. const beforeEnterSpy = jasmine.createSpy('beforeEnter')
  178. const afterLeaveSpy = jasmine.createSpy('afterLeave')
  179. const afterEnterSpy = jasmine.createSpy('afterEnter')
  180. const vm = new Vue({
  181. template: `
  182. <div>
  183. <transition
  184. name="test"
  185. @before-enter="beforeEnter"
  186. @enter="enter"
  187. @after-enter="afterEnter"
  188. @before-leave="beforeLeave"
  189. @leave="leave"
  190. @after-leave="afterLeave">
  191. <div v-if="ok" class="test">foo</div>
  192. </transition>
  193. </div>
  194. `,
  195. data: { ok: true },
  196. methods: {
  197. beforeLeave: (el) => {
  198. expect(el).toBe(vm.$el.children[0])
  199. expect(el.className).toBe('test')
  200. beforeLeaveSpy(el)
  201. },
  202. leave: (el) => onLeaveSpy(el),
  203. afterLeave: (el) => afterLeaveSpy(el),
  204. beforeEnter: (el) => {
  205. expect(vm.$el.contains(el)).toBe(false)
  206. expect(el.className).toBe('test')
  207. beforeEnterSpy(el)
  208. },
  209. enter: (el) => {
  210. expect(vm.$el.contains(el)).toBe(true)
  211. onEnterSpy(el)
  212. },
  213. afterEnter: (el) => afterEnterSpy(el)
  214. }
  215. }).$mount(el)
  216. // should not apply transition on initial render by default
  217. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  218. let _el = vm.$el.children[0]
  219. vm.ok = false
  220. waitForUpdate(() => {
  221. expect(beforeLeaveSpy).toHaveBeenCalledWith(_el)
  222. expect(onLeaveSpy).toHaveBeenCalledWith(_el)
  223. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  224. }).thenWaitFor(nextFrame).then(() => {
  225. expect(afterLeaveSpy).not.toHaveBeenCalled()
  226. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  227. }).thenWaitFor(duration + buffer).then(() => {
  228. expect(afterLeaveSpy).toHaveBeenCalledWith(_el)
  229. expect(vm.$el.children.length).toBe(0)
  230. vm.ok = true
  231. }).then(() => {
  232. _el = vm.$el.children[0]
  233. expect(beforeEnterSpy).toHaveBeenCalledWith(_el)
  234. expect(onEnterSpy).toHaveBeenCalledWith(_el)
  235. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  236. }).thenWaitFor(nextFrame).then(() => {
  237. expect(afterEnterSpy).not.toHaveBeenCalled()
  238. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  239. }).thenWaitFor(duration + buffer).then(() => {
  240. expect(afterEnterSpy).toHaveBeenCalledWith(_el)
  241. expect(vm.$el.children[0].className).toBe('test')
  242. }).then(done)
  243. })
  244. it('transition events (v-show)', done => {
  245. const onLeaveSpy = jasmine.createSpy('leave')
  246. const onEnterSpy = jasmine.createSpy('enter')
  247. const beforeLeaveSpy = jasmine.createSpy('beforeLeave')
  248. const beforeEnterSpy = jasmine.createSpy('beforeEnter')
  249. const afterLeaveSpy = jasmine.createSpy('afterLeave')
  250. const afterEnterSpy = jasmine.createSpy('afterEnter')
  251. const vm = new Vue({
  252. template: `
  253. <div>
  254. <transition
  255. name="test"
  256. @before-enter="beforeEnter"
  257. @enter="enter"
  258. @after-enter="afterEnter"
  259. @before-leave="beforeLeave"
  260. @leave="leave"
  261. @after-leave="afterLeave">
  262. <div v-show="ok" class="test">foo</div>
  263. </transition>
  264. </div>
  265. `,
  266. data: { ok: true },
  267. methods: {
  268. beforeLeave: (el) => {
  269. expect(el.style.display).toBe('')
  270. expect(el).toBe(vm.$el.children[0])
  271. expect(el.className).toBe('test')
  272. beforeLeaveSpy(el)
  273. },
  274. leave: (el) => {
  275. expect(el.style.display).toBe('')
  276. onLeaveSpy(el)
  277. },
  278. afterLeave: (el) => {
  279. expect(el.style.display).toBe('none')
  280. afterLeaveSpy(el)
  281. },
  282. beforeEnter: (el) => {
  283. expect(el.className).toBe('test')
  284. expect(el.style.display).toBe('none')
  285. beforeEnterSpy(el)
  286. },
  287. enter: (el) => {
  288. expect(el.style.display).toBe('')
  289. onEnterSpy(el)
  290. },
  291. afterEnter: (el) => {
  292. expect(el.style.display).toBe('')
  293. afterEnterSpy(el)
  294. }
  295. }
  296. }).$mount(el)
  297. // should not apply transition on initial render by default
  298. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  299. let _el = vm.$el.children[0]
  300. vm.ok = false
  301. waitForUpdate(() => {
  302. expect(beforeLeaveSpy).toHaveBeenCalledWith(_el)
  303. expect(onLeaveSpy).toHaveBeenCalledWith(_el)
  304. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  305. }).thenWaitFor(nextFrame).then(() => {
  306. expect(afterLeaveSpy).not.toHaveBeenCalled()
  307. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  308. }).thenWaitFor(duration + buffer).then(() => {
  309. expect(afterLeaveSpy).toHaveBeenCalledWith(_el)
  310. expect(vm.$el.children[0].style.display).toBe('none')
  311. vm.ok = true
  312. }).then(() => {
  313. _el = vm.$el.children[0]
  314. expect(beforeEnterSpy).toHaveBeenCalledWith(_el)
  315. expect(onEnterSpy).toHaveBeenCalledWith(_el)
  316. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  317. }).thenWaitFor(nextFrame).then(() => {
  318. expect(afterEnterSpy).not.toHaveBeenCalled()
  319. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  320. }).thenWaitFor(duration + buffer).then(() => {
  321. expect(afterEnterSpy).toHaveBeenCalledWith(_el)
  322. expect(vm.$el.children[0].className).toBe('test')
  323. }).then(done)
  324. })
  325. it('explicit user callback in JavaScript hooks', done => {
  326. let next
  327. const vm = new Vue({
  328. template: `<div>
  329. <transition name="test" @enter="enter" @leave="leave">
  330. <div v-if="ok" class="test">foo</div>
  331. </transition>
  332. </div>`,
  333. data: { ok: true },
  334. methods: {
  335. enter: (el, cb) => {
  336. next = cb
  337. },
  338. leave: (el, cb) => {
  339. next = cb
  340. }
  341. }
  342. }).$mount(el)
  343. vm.ok = false
  344. waitForUpdate(() => {
  345. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  346. }).thenWaitFor(nextFrame).then(() => {
  347. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  348. }).thenWaitFor(duration + buffer).then(() => {
  349. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  350. expect(next).toBeTruthy()
  351. next()
  352. expect(vm.$el.children.length).toBe(0)
  353. }).then(() => {
  354. vm.ok = true
  355. }).then(() => {
  356. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  357. }).thenWaitFor(nextFrame).then(() => {
  358. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  359. }).thenWaitFor(duration + buffer).then(() => {
  360. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  361. expect(next).toBeTruthy()
  362. next()
  363. expect(vm.$el.children[0].className).toBe('test')
  364. }).then(done)
  365. })
  366. it('css: false', done => {
  367. const enterSpy = jasmine.createSpy('enter')
  368. const leaveSpy = jasmine.createSpy('leave')
  369. const vm = new Vue({
  370. template: `
  371. <div>
  372. <transition :css="false" name="test" @enter="enter" @leave="leave">
  373. <div v-if="ok" class="test">foo</div>
  374. </transition>
  375. </div>
  376. `,
  377. data: { ok: true },
  378. methods: {
  379. enter: enterSpy,
  380. leave: leaveSpy
  381. }
  382. }).$mount(el)
  383. vm.ok = false
  384. waitForUpdate(() => {
  385. expect(leaveSpy).toHaveBeenCalled()
  386. expect(vm.$el.innerHTML).toBe('<!---->')
  387. vm.ok = true
  388. }).then(() => {
  389. expect(enterSpy).toHaveBeenCalled()
  390. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  391. }).then(done)
  392. })
  393. it('no transition detected', done => {
  394. const enterSpy = jasmine.createSpy('enter')
  395. const leaveSpy = jasmine.createSpy('leave')
  396. const vm = new Vue({
  397. template: '<div><transition name="nope" @enter="enter" @leave="leave"><div v-if="ok">foo</div></transition></div>',
  398. data: { ok: true },
  399. methods: {
  400. enter: enterSpy,
  401. leave: leaveSpy
  402. }
  403. }).$mount(el)
  404. vm.ok = false
  405. waitForUpdate(() => {
  406. expect(leaveSpy).toHaveBeenCalled()
  407. expect(vm.$el.innerHTML).toBe('<div class="nope-leave nope-leave-active">foo</div><!---->')
  408. }).thenWaitFor(nextFrame).then(() => {
  409. expect(vm.$el.innerHTML).toBe('<!---->')
  410. vm.ok = true
  411. }).then(() => {
  412. expect(enterSpy).toHaveBeenCalled()
  413. expect(vm.$el.innerHTML).toBe('<div class="nope-enter nope-enter-active">foo</div>')
  414. }).thenWaitFor(nextFrame).then(() => {
  415. expect(vm.$el.innerHTML).toBe('<div>foo</div>')
  416. }).then(done)
  417. })
  418. it('enterCancelled', done => {
  419. const spy = jasmine.createSpy('enterCancelled')
  420. const vm = new Vue({
  421. template: `
  422. <div>
  423. <transition name="test" @enter-cancelled="enterCancelled">
  424. <div v-if="ok" class="test">foo</div>
  425. </transition>
  426. </div>
  427. `,
  428. data: { ok: false },
  429. methods: {
  430. enterCancelled: spy
  431. }
  432. }).$mount(el)
  433. expect(vm.$el.innerHTML).toBe('<!---->')
  434. vm.ok = true
  435. waitForUpdate(() => {
  436. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  437. }).thenWaitFor(nextFrame).then(() => {
  438. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  439. }).thenWaitFor(duration / 2).then(() => {
  440. vm.ok = false
  441. }).then(() => {
  442. expect(spy).toHaveBeenCalled()
  443. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  444. }).thenWaitFor(nextFrame).then(() => {
  445. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  446. }).thenWaitFor(duration + buffer).then(() => {
  447. expect(vm.$el.children.length).toBe(0)
  448. }).then(done)
  449. })
  450. it('should remove stale leaving elements', done => {
  451. const spy = jasmine.createSpy('afterLeave')
  452. const vm = new Vue({
  453. template: `
  454. <div>
  455. <transition name="test" @after-leave="afterLeave">
  456. <div v-if="ok" class="test">foo</div>
  457. </transition>
  458. </div>
  459. `,
  460. data: { ok: true },
  461. methods: {
  462. afterLeave: spy
  463. }
  464. }).$mount(el)
  465. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  466. vm.ok = false
  467. waitForUpdate(() => {
  468. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  469. }).thenWaitFor(duration / 2).then(() => {
  470. vm.ok = true
  471. }).then(() => {
  472. expect(spy).toHaveBeenCalled()
  473. expect(vm.$el.children.length).toBe(1) // should have removed leaving element
  474. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  475. }).thenWaitFor(nextFrame).then(() => {
  476. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  477. }).thenWaitFor(duration + buffer).then(() => {
  478. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  479. }).then(done)
  480. })
  481. it('transition with v-show', done => {
  482. const vm = new Vue({
  483. template: `
  484. <div>
  485. <transition name="test">
  486. <div v-show="ok" class="test">foo</div>
  487. </transition>
  488. </div>
  489. `,
  490. data: { ok: true }
  491. }).$mount(el)
  492. // should not apply transition on initial render by default
  493. expect(vm.$el.textContent).toBe('foo')
  494. expect(vm.$el.children[0].style.display).toBe('')
  495. expect(vm.$el.children[0].className).toBe('test')
  496. vm.ok = false
  497. waitForUpdate(() => {
  498. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  499. }).thenWaitFor(nextFrame).then(() => {
  500. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  501. }).thenWaitFor(duration + buffer).then(() => {
  502. expect(vm.$el.children[0].style.display).toBe('none')
  503. vm.ok = true
  504. }).then(() => {
  505. expect(vm.$el.children[0].style.display).toBe('')
  506. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  507. }).thenWaitFor(nextFrame).then(() => {
  508. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  509. }).thenWaitFor(duration + buffer).then(() => {
  510. expect(vm.$el.children[0].className).toBe('test')
  511. }).then(done)
  512. })
  513. it('transition with v-show, inside child component', done => {
  514. const vm = new Vue({
  515. template: `
  516. <div>
  517. <test v-show="ok"></test>
  518. </div>
  519. `,
  520. data: { ok: true },
  521. components: {
  522. test: {
  523. template: `<transition name="test"><div class="test">foo</div></transition>`
  524. }
  525. }
  526. }).$mount(el)
  527. // should not apply transition on initial render by default
  528. expect(vm.$el.textContent).toBe('foo')
  529. expect(vm.$el.children[0].style.display).toBe('')
  530. vm.ok = false
  531. waitForUpdate(() => {
  532. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  533. }).thenWaitFor(nextFrame).then(() => {
  534. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  535. }).thenWaitFor(duration + buffer).then(() => {
  536. expect(vm.$el.children[0].style.display).toBe('none')
  537. vm.ok = true
  538. }).then(() => {
  539. expect(vm.$el.children[0].style.display).toBe('')
  540. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  541. }).thenWaitFor(nextFrame).then(() => {
  542. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  543. }).thenWaitFor(duration + buffer).then(() => {
  544. expect(vm.$el.children[0].className).toBe('test')
  545. }).then(done)
  546. })
  547. it('leaveCancelled (v-show only)', done => {
  548. const spy = jasmine.createSpy('leaveCancelled')
  549. const vm = new Vue({
  550. template: `
  551. <div>
  552. <transition name="test" @leave-cancelled="leaveCancelled">
  553. <div v-show="ok" class="test">foo</div>
  554. </transition>
  555. </div>
  556. `,
  557. data: { ok: true },
  558. methods: {
  559. leaveCancelled: spy
  560. }
  561. }).$mount(el)
  562. expect(vm.$el.children[0].style.display).toBe('')
  563. vm.ok = false
  564. waitForUpdate(() => {
  565. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  566. }).thenWaitFor(nextFrame).then(() => {
  567. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  568. }).thenWaitFor(10).then(() => {
  569. vm.ok = true
  570. }).then(() => {
  571. expect(spy).toHaveBeenCalled()
  572. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  573. }).thenWaitFor(nextFrame).then(() => {
  574. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  575. }).thenWaitFor(duration + buffer).then(() => {
  576. expect(vm.$el.children[0].style.display).toBe('')
  577. }).then(done)
  578. })
  579. it('leave transition with v-show: cancelled on next frame', done => {
  580. const vm = new Vue({
  581. template: `
  582. <div>
  583. <transition name="test">
  584. <div v-show="ok" class="test">foo</div>
  585. </transition>
  586. </div>
  587. `,
  588. data: { ok: true }
  589. }).$mount(el)
  590. vm.ok = false
  591. waitForUpdate(() => {
  592. vm.ok = true
  593. }).thenWaitFor(nextFrame).then(() => {
  594. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  595. }).thenWaitFor(duration + buffer).then(() => {
  596. expect(vm.$el.children[0].className).toBe('test')
  597. }).then(done)
  598. })
  599. it('enter transition with v-show: cancelled on next frame', done => {
  600. const vm = new Vue({
  601. template: `
  602. <div>
  603. <transition name="test">
  604. <div v-show="ok" class="test">foo</div>
  605. </transition>
  606. </div>
  607. `,
  608. data: { ok: false }
  609. }).$mount(el)
  610. vm.ok = true
  611. waitForUpdate(() => {
  612. vm.ok = false
  613. }).thenWaitFor(nextFrame).then(() => {
  614. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  615. }).thenWaitFor(duration + buffer).then(() => {
  616. expect(vm.$el.children[0].className).toBe('test')
  617. }).then(done)
  618. })
  619. it('animations', done => {
  620. const vm = new Vue({
  621. template: `
  622. <div>
  623. <transition name="test-anim">
  624. <div v-if="ok">foo</div>
  625. </transition>
  626. </div>
  627. `,
  628. data: { ok: true }
  629. }).$mount(el)
  630. // should not apply transition on initial render by default
  631. expect(vm.$el.innerHTML).toBe('<div>foo</div>')
  632. vm.ok = false
  633. waitForUpdate(() => {
  634. expect(vm.$el.children[0].className).toBe('test-anim-leave test-anim-leave-active')
  635. }).thenWaitFor(nextFrame).then(() => {
  636. expect(vm.$el.children[0].className).toBe('test-anim-leave-active test-anim-leave-to')
  637. }).thenWaitFor(duration + buffer).then(() => {
  638. expect(vm.$el.children.length).toBe(0)
  639. vm.ok = true
  640. }).then(() => {
  641. expect(vm.$el.children[0].className).toBe('test-anim-enter test-anim-enter-active')
  642. }).thenWaitFor(nextFrame).then(() => {
  643. expect(vm.$el.children[0].className).toBe('test-anim-enter-active test-anim-enter-to')
  644. }).thenWaitFor(duration + buffer).then(() => {
  645. expect(vm.$el.children[0].className).toBe('')
  646. }).then(done)
  647. })
  648. it('explicit transition type', done => {
  649. const vm = new Vue({
  650. template: `
  651. <div>
  652. <transition name="test-anim-long" type="animation">
  653. <div v-if="ok" class="test">foo</div>
  654. </transition>
  655. </div>
  656. `,
  657. data: { ok: true }
  658. }).$mount(el)
  659. // should not apply transition on initial render by default
  660. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  661. vm.ok = false
  662. waitForUpdate(() => {
  663. expect(vm.$el.children[0].className).toBe('test test-anim-long-leave test-anim-long-leave-active')
  664. }).thenWaitFor(nextFrame).then(() => {
  665. expect(vm.$el.children[0].className).toBe('test test-anim-long-leave-active test-anim-long-leave-to')
  666. }).thenWaitFor(duration + 5).then(() => {
  667. // should not end early due to transition presence
  668. expect(vm.$el.children[0].className).toBe('test test-anim-long-leave-active test-anim-long-leave-to')
  669. }).thenWaitFor(duration + 5).then(() => {
  670. expect(vm.$el.children.length).toBe(0)
  671. vm.ok = true
  672. }).then(() => {
  673. expect(vm.$el.children[0].className).toBe('test test-anim-long-enter test-anim-long-enter-active')
  674. }).thenWaitFor(nextFrame).then(() => {
  675. expect(vm.$el.children[0].className).toBe('test test-anim-long-enter-active test-anim-long-enter-to')
  676. }).thenWaitFor(duration + 5).then(() => {
  677. expect(vm.$el.children[0].className).toBe('test test-anim-long-enter-active test-anim-long-enter-to')
  678. }).thenWaitFor(duration + 5).then(() => {
  679. expect(vm.$el.children[0].className).toBe('test')
  680. }).then(done)
  681. })
  682. it('transition on appear', done => {
  683. const vm = new Vue({
  684. template: `
  685. <div>
  686. <transition name="test"
  687. appear
  688. appear-class="test-appear"
  689. appear-to-class="test-appear-to"
  690. appear-active-class="test-appear-active">
  691. <div v-if="ok" class="test">foo</div>
  692. </transition>
  693. </div>
  694. `,
  695. data: { ok: true }
  696. }).$mount(el)
  697. waitForUpdate(() => {
  698. expect(vm.$el.children[0].className).toBe('test test-appear test-appear-active')
  699. }).thenWaitFor(nextFrame).then(() => {
  700. expect(vm.$el.children[0].className).toBe('test test-appear-active test-appear-to')
  701. }).thenWaitFor(duration + buffer).then(() => {
  702. expect(vm.$el.children[0].className).toBe('test')
  703. }).then(done)
  704. })
  705. it('transition on appear with v-show', done => {
  706. const vm = new Vue({
  707. template: `
  708. <div>
  709. <transition name="test" appear>
  710. <div v-show="ok" class="test">foo</div>
  711. </transition>
  712. </div>
  713. `,
  714. data: { ok: true }
  715. }).$mount(el)
  716. waitForUpdate(() => {
  717. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  718. }).thenWaitFor(nextFrame).then(() => {
  719. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  720. }).thenWaitFor(duration + buffer).then(() => {
  721. expect(vm.$el.children[0].className).toBe('test')
  722. }).then(done)
  723. })
  724. it('transition on SVG elements', done => {
  725. const vm = new Vue({
  726. template: `
  727. <svg>
  728. <transition>
  729. <circle cx="0" cy="0" r="10" v-if="ok" class="test"></circle>
  730. </transition>
  731. </svg>
  732. `,
  733. data: { ok: true }
  734. }).$mount(el)
  735. // should not apply transition on initial render by default
  736. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test')
  737. vm.ok = false
  738. waitForUpdate(() => {
  739. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-leave v-leave-active')
  740. }).thenWaitFor(nextFrame).then(() => {
  741. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-leave-active v-leave-to')
  742. }).thenWaitFor(duration + buffer).then(() => {
  743. expect(vm.$el.childNodes.length).toBe(1)
  744. expect(vm.$el.childNodes[0].nodeType).toBe(8) // should be an empty comment node
  745. expect(vm.$el.childNodes[0].textContent).toBe('')
  746. vm.ok = true
  747. }).then(() => {
  748. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-enter v-enter-active')
  749. }).thenWaitFor(nextFrame).then(() => {
  750. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test v-enter-active v-enter-to')
  751. }).thenWaitFor(duration + buffer).then(() => {
  752. expect(vm.$el.childNodes[0].getAttribute('class')).toBe('test')
  753. }).then(done)
  754. })
  755. it('transition on child components', done => {
  756. const vm = new Vue({
  757. template: `
  758. <div>
  759. <transition>
  760. <test v-if="ok" class="test"></test>
  761. </transition>
  762. </div>
  763. `,
  764. data: { ok: true },
  765. components: {
  766. test: {
  767. template: `
  768. <transition name="test">
  769. <div>foo</div>
  770. </transition>
  771. ` // test transition override from parent
  772. }
  773. }
  774. }).$mount(el)
  775. // should not apply transition on initial render by default
  776. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  777. vm.ok = false
  778. waitForUpdate(() => {
  779. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  780. }).thenWaitFor(nextFrame).then(() => {
  781. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  782. }).thenWaitFor(duration + buffer).then(() => {
  783. expect(vm.$el.children.length).toBe(0)
  784. vm.ok = true
  785. }).then(() => {
  786. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  787. }).thenWaitFor(nextFrame).then(() => {
  788. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  789. }).thenWaitFor(duration + buffer).then(() => {
  790. expect(vm.$el.children[0].className).toBe('test')
  791. }).then(done)
  792. })
  793. it('transition inside child component', done => {
  794. const vm = new Vue({
  795. template: `
  796. <div>
  797. <test v-if="ok" class="test"></test>
  798. </div>
  799. `,
  800. data: { ok: true },
  801. components: {
  802. test: {
  803. template: `
  804. <transition>
  805. <div>foo</div>
  806. </transition>
  807. `
  808. }
  809. }
  810. }).$mount(el)
  811. // should not apply transition on initial render by default
  812. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  813. vm.ok = false
  814. waitForUpdate(() => {
  815. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  816. }).thenWaitFor(nextFrame).then(() => {
  817. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  818. }).thenWaitFor(duration + buffer).then(() => {
  819. expect(vm.$el.children.length).toBe(0)
  820. vm.ok = true
  821. }).then(() => {
  822. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  823. }).thenWaitFor(nextFrame).then(() => {
  824. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  825. }).thenWaitFor(duration + buffer).then(() => {
  826. expect(vm.$el.children[0].className).toBe('test')
  827. }).then(done)
  828. })
  829. it('custom transition higher-order component', done => {
  830. const vm = new Vue({
  831. template: '<div><my-transition><div v-if="ok" class="test">foo</div></my-transition></div>',
  832. data: { ok: true },
  833. components: {
  834. 'my-transition': {
  835. functional: true,
  836. render (h, { data, children }) {
  837. (data.props || (data.props = {})).name = 'test'
  838. return h('transition', data, children)
  839. }
  840. }
  841. }
  842. }).$mount(el)
  843. // should not apply transition on initial render by default
  844. expect(vm.$el.innerHTML).toBe('<div class="test">foo</div>')
  845. vm.ok = false
  846. waitForUpdate(() => {
  847. expect(vm.$el.children[0].className).toBe('test test-leave test-leave-active')
  848. }).thenWaitFor(nextFrame).then(() => {
  849. expect(vm.$el.children[0].className).toBe('test test-leave-active test-leave-to')
  850. }).thenWaitFor(duration + buffer).then(() => {
  851. expect(vm.$el.children.length).toBe(0)
  852. vm.ok = true
  853. }).then(() => {
  854. expect(vm.$el.children[0].className).toBe('test test-enter test-enter-active')
  855. }).thenWaitFor(nextFrame).then(() => {
  856. expect(vm.$el.children[0].className).toBe('test test-enter-active test-enter-to')
  857. }).thenWaitFor(duration + buffer).then(() => {
  858. expect(vm.$el.children[0].className).toBe('test')
  859. }).then(done)
  860. })
  861. it('warn when used on multiple elements', () => {
  862. new Vue({
  863. template: `<transition><p>1</p><p>2</p></transition>`
  864. }).$mount()
  865. expect(`<transition> can only be used on a single element`).toHaveBeenWarned()
  866. })
  867. describe('explicit durations -', () => {
  868. it('single value', done => {
  869. const vm = new Vue({
  870. template: `
  871. <div>
  872. <transition duration="${explicitDuration}">
  873. <div v-if="ok" class="test">foo</div>
  874. </transition>
  875. </div>
  876. `,
  877. data: { ok: true }
  878. }).$mount(el)
  879. vm.ok = false
  880. waitForUpdate(() => {
  881. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  882. }).thenWaitFor(nextFrame).then(() => {
  883. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  884. }).thenWaitFor(explicitDuration + buffer).then(() => {
  885. expect(vm.$el.children.length).toBe(0)
  886. vm.ok = true
  887. }).then(() => {
  888. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  889. }).thenWaitFor(nextFrame).then(() => {
  890. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  891. }).thenWaitFor(explicitDuration + buffer).then(() => {
  892. expect(vm.$el.children[0].className).toBe('test')
  893. }).then(done)
  894. })
  895. it('enter and auto leave', done => {
  896. const vm = new Vue({
  897. template: `
  898. <div>
  899. <transition :duration="{ enter: ${explicitDuration} }">
  900. <div v-if="ok" class="test">foo</div>
  901. </transition>
  902. </div>
  903. `,
  904. data: { ok: true }
  905. }).$mount(el)
  906. vm.ok = false
  907. waitForUpdate(() => {
  908. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  909. }).thenWaitFor(nextFrame).then(() => {
  910. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  911. }).thenWaitFor(duration + buffer).then(() => {
  912. expect(vm.$el.children.length).toBe(0)
  913. vm.ok = true
  914. }).then(() => {
  915. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  916. }).thenWaitFor(nextFrame).then(() => {
  917. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  918. }).thenWaitFor(explicitDuration + buffer).then(() => {
  919. expect(vm.$el.children[0].className).toBe('test')
  920. }).then(done)
  921. })
  922. it('leave and auto enter', done => {
  923. const vm = new Vue({
  924. template: `
  925. <div>
  926. <transition :duration="{ leave: ${explicitDuration} }">
  927. <div v-if="ok" class="test">foo</div>
  928. </transition>
  929. </div>
  930. `,
  931. data: { ok: true }
  932. }).$mount(el)
  933. vm.ok = false
  934. waitForUpdate(() => {
  935. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  936. }).thenWaitFor(nextFrame).then(() => {
  937. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  938. }).thenWaitFor(explicitDuration + buffer).then(() => {
  939. expect(vm.$el.children.length).toBe(0)
  940. vm.ok = true
  941. }).then(() => {
  942. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  943. }).thenWaitFor(nextFrame).then(() => {
  944. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  945. }).thenWaitFor(duration + buffer).then(() => {
  946. expect(vm.$el.children[0].className).toBe('test')
  947. }).then(done)
  948. })
  949. it('separate enter and leave', done => {
  950. const enter = explicitDuration
  951. const leave = explicitDuration * 2
  952. const vm = new Vue({
  953. template: `
  954. <div>
  955. <transition :duration="{ enter: ${enter}, leave: ${leave} }">
  956. <div v-if="ok" class="test">foo</div>
  957. </transition>
  958. </div>
  959. `,
  960. data: { ok: true }
  961. }).$mount(el)
  962. vm.ok = false
  963. waitForUpdate(() => {
  964. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  965. }).thenWaitFor(nextFrame).then(() => {
  966. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  967. }).thenWaitFor(leave + buffer).then(() => {
  968. expect(vm.$el.children.length).toBe(0)
  969. vm.ok = true
  970. }).then(() => {
  971. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  972. }).thenWaitFor(nextFrame).then(() => {
  973. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  974. }).thenWaitFor(enter + buffer).then(() => {
  975. expect(vm.$el.children[0].className).toBe('test')
  976. }).then(done)
  977. })
  978. it('enter and leave + duration change', done => {
  979. const enter1 = explicitDuration * 2
  980. const enter2 = explicitDuration
  981. const leave1 = explicitDuration * 0.5
  982. const leave2 = explicitDuration * 3
  983. const vm = new Vue({
  984. template: `
  985. <div>
  986. <transition :duration="{ enter: enter, leave: leave }">
  987. <div v-if="ok" class="test">foo</div>
  988. </transition>
  989. </div>
  990. `,
  991. data: {
  992. ok: true,
  993. enter: enter1,
  994. leave: leave1
  995. }
  996. }).$mount(el)
  997. vm.ok = false
  998. waitForUpdate(() => {
  999. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  1000. }).thenWaitFor(nextFrame).then(() => {
  1001. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  1002. }).thenWaitFor(leave1 + buffer).then(() => {
  1003. expect(vm.$el.children.length).toBe(0)
  1004. vm.ok = true
  1005. }).then(() => {
  1006. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  1007. }).thenWaitFor(nextFrame).then(() => {
  1008. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  1009. }).thenWaitFor(enter1 + buffer).then(() => {
  1010. expect(vm.$el.children[0].className).toBe('test')
  1011. vm.enter = enter2
  1012. vm.leave = leave2
  1013. }).then(() => {
  1014. vm.ok = false
  1015. }).then(() => {
  1016. expect(vm.$el.children[0].className).toBe('test v-leave v-leave-active')
  1017. }).thenWaitFor(nextFrame).then(() => {
  1018. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  1019. }).thenWaitFor(leave2 + buffer).then(() => {
  1020. expect(vm.$el.children.length).toBe(0)
  1021. vm.ok = true
  1022. }).then(() => {
  1023. expect(vm.$el.children[0].className).toBe('test v-enter v-enter-active')
  1024. }).thenWaitFor(nextFrame).then(() => {
  1025. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  1026. }).thenWaitFor(enter2 + buffer).then(() => {
  1027. expect(vm.$el.children[0].className).toBe('test')
  1028. }).then(done)
  1029. }, 10000)
  1030. it('warn invalid durations', done => {
  1031. const vm = new Vue({
  1032. template: `
  1033. <div>
  1034. <transition :duration="{ enter: NaN, leave: 'foo' }">
  1035. <div v-if="ok" class="test">foo</div>
  1036. </transition>
  1037. </div>
  1038. `,
  1039. data: {
  1040. ok: true
  1041. }
  1042. }).$mount(el)
  1043. vm.ok = false
  1044. waitForUpdate(() => {
  1045. expect(`<transition> explicit leave duration is not a valid number - got "foo"`).toHaveBeenWarned()
  1046. }).thenWaitFor(duration + buffer).then(() => {
  1047. vm.ok = true
  1048. }).then(() => {
  1049. expect(`<transition> explicit enter duration is NaN`).toHaveBeenWarned()
  1050. }).then(done)
  1051. })
  1052. })
  1053. // #6687
  1054. it('transition on child components with empty root node', done => {
  1055. const vm = new Vue({
  1056. template: `
  1057. <div>
  1058. <transition mode="out-in">
  1059. <component class="test" :is="view"></component>
  1060. </transition>
  1061. </div>
  1062. `,
  1063. data: { view: 'one' },
  1064. components: {
  1065. 'one': {
  1066. template: '<div v-if="false">one</div>'
  1067. },
  1068. 'two': {
  1069. template: '<div>two</div>'
  1070. }
  1071. }
  1072. }).$mount(el)
  1073. // should not apply transition on initial render by default
  1074. expect(vm.$el.innerHTML).toBe('<!---->')
  1075. vm.view = 'two'
  1076. waitForUpdate(() => {
  1077. expect(vm.$el.innerHTML).toBe('<div class="test v-enter v-enter-active">two</div>')
  1078. }).thenWaitFor(nextFrame).then(() => {
  1079. expect(vm.$el.children[0].className).toBe('test v-enter-active v-enter-to')
  1080. }).thenWaitFor(duration + buffer).then(() => {
  1081. expect(vm.$el.children[0].className).toBe('test')
  1082. vm.view = 'one'
  1083. }).then(() => {
  1084. // incoming comment node is appended instantly because it doesn't have
  1085. // data and therefore doesn't go through the transition module.
  1086. expect(vm.$el.innerHTML).toBe('<div class="test v-leave v-leave-active">two</div><!---->')
  1087. }).thenWaitFor(nextFrame).then(() => {
  1088. expect(vm.$el.children[0].className).toBe('test v-leave-active v-leave-to')
  1089. }).thenWaitFor(duration + buffer).then(() => {
  1090. expect(vm.$el.innerHTML).toBe('<!---->')
  1091. }).then(done)
  1092. })
  1093. })
  1094. }