transition-group.spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. import Vue from 'vue'
  2. import injectStyles from './inject-styles'
  3. import { nextFrame } from 'web/runtime/transition-util'
  4. describe.skip('Transition group', () => {
  5. const { duration, buffer } = injectStyles()
  6. let el
  7. beforeEach(() => {
  8. el = document.createElement('div')
  9. document.body.appendChild(el)
  10. })
  11. function createBasicVM(useIs?, appear = false) {
  12. const vm = new Vue({
  13. template: `
  14. <div>
  15. ${
  16. useIs
  17. ? `<span is="transition-group">`
  18. : `<transition-group${appear ? ` appear` : ``}>`
  19. }
  20. <div v-for="item in items" :key="item" class="test">{{ item }}</div>
  21. ${useIs ? `</span>` : `</transition-group>`}
  22. </div>
  23. `,
  24. data: {
  25. items: ['a', 'b', 'c']
  26. }
  27. }).$mount(el)
  28. if (!appear) {
  29. expect(vm.$el.innerHTML).toBe(
  30. `<span>` +
  31. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  32. `</span>`
  33. )
  34. }
  35. return vm
  36. }
  37. it('enter', (done) => {
  38. const vm = createBasicVM()
  39. vm.items.push('d', 'e')
  40. waitForUpdate(() => {
  41. expect(vm.$el.innerHTML).toBe(
  42. `<span>` +
  43. ['a', 'b', 'c'].map((i) => `<div class="test">${i}</div>`).join('') +
  44. `<div class="test v-enter v-enter-active">d</div>` +
  45. `<div class="test v-enter v-enter-active">e</div>` +
  46. `</span>`
  47. )
  48. })
  49. .thenWaitFor(nextFrame)
  50. .then(() => {
  51. expect(vm.$el.innerHTML).toBe(
  52. `<span>` +
  53. ['a', 'b', 'c']
  54. .map((i) => `<div class="test">${i}</div>`)
  55. .join('') +
  56. `<div class="test v-enter-active v-enter-to">d</div>` +
  57. `<div class="test v-enter-active v-enter-to">e</div>` +
  58. `</span>`
  59. )
  60. })
  61. .thenWaitFor(duration + buffer)
  62. .then(() => {
  63. expect(vm.$el.innerHTML).toBe(
  64. `<span>` +
  65. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  66. `</span>`
  67. )
  68. })
  69. .then(done)
  70. })
  71. it('leave', (done) => {
  72. const vm = createBasicVM()
  73. vm.items = ['b']
  74. waitForUpdate(() => {
  75. expect(vm.$el.innerHTML).toBe(
  76. `<span>` +
  77. `<div class="test v-leave v-leave-active">a</div>` +
  78. `<div class="test">b</div>` +
  79. `<div class="test v-leave v-leave-active">c</div>` +
  80. `</span>`
  81. )
  82. })
  83. .thenWaitFor(nextFrame)
  84. .then(() => {
  85. expect(vm.$el.innerHTML).toBe(
  86. `<span>` +
  87. `<div class="test v-leave-active v-leave-to">a</div>` +
  88. `<div class="test">b</div>` +
  89. `<div class="test v-leave-active v-leave-to">c</div>` +
  90. `</span>`
  91. )
  92. })
  93. .thenWaitFor(duration + buffer)
  94. .then(() => {
  95. expect(vm.$el.innerHTML).toBe(
  96. `<span>` +
  97. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  98. `</span>`
  99. )
  100. })
  101. .then(done)
  102. })
  103. it('enter + leave', (done) => {
  104. const vm = createBasicVM()
  105. vm.items = ['b', 'c', 'd']
  106. waitForUpdate(() => {
  107. expect(vm.$el.innerHTML).toBe(
  108. `<span>` +
  109. `<div class="test v-leave v-leave-active">a</div>` +
  110. `<div class="test">b</div>` +
  111. `<div class="test">c</div>` +
  112. `<div class="test v-enter v-enter-active">d</div>` +
  113. `</span>`
  114. )
  115. })
  116. .thenWaitFor(nextFrame)
  117. .then(() => {
  118. expect(vm.$el.innerHTML).toBe(
  119. `<span>` +
  120. `<div class="test v-leave-active v-leave-to">a</div>` +
  121. `<div class="test">b</div>` +
  122. `<div class="test">c</div>` +
  123. `<div class="test v-enter-active v-enter-to">d</div>` +
  124. `</span>`
  125. )
  126. })
  127. .thenWaitFor(duration + buffer)
  128. .then(() => {
  129. expect(vm.$el.innerHTML).toBe(
  130. `<span>` +
  131. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  132. `</span>`
  133. )
  134. })
  135. .then(done)
  136. })
  137. it('use with "is" attribute', (done) => {
  138. const vm = createBasicVM(true)
  139. vm.items = ['b', 'c', 'd']
  140. waitForUpdate(() => {
  141. expect(vm.$el.innerHTML).toBe(
  142. `<span>` +
  143. `<div class="test v-leave v-leave-active">a</div>` +
  144. `<div class="test">b</div>` +
  145. `<div class="test">c</div>` +
  146. `<div class="test v-enter v-enter-active">d</div>` +
  147. `</span>`
  148. )
  149. })
  150. .thenWaitFor(nextFrame)
  151. .then(() => {
  152. expect(vm.$el.innerHTML).toBe(
  153. `<span>` +
  154. `<div class="test v-leave-active v-leave-to">a</div>` +
  155. `<div class="test">b</div>` +
  156. `<div class="test">c</div>` +
  157. `<div class="test v-enter-active v-enter-to">d</div>` +
  158. `</span>`
  159. )
  160. })
  161. .thenWaitFor(duration + buffer)
  162. .then(() => {
  163. expect(vm.$el.innerHTML).toBe(
  164. `<span>` +
  165. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  166. `</span>`
  167. )
  168. })
  169. .then(done)
  170. })
  171. it('appear', (done) => {
  172. const vm = createBasicVM(false, true /* appear */)
  173. waitForUpdate(() => {
  174. expect(vm.$el.innerHTML).toBe(
  175. `<span>` +
  176. vm.items
  177. .map((i) => `<div class="test v-enter v-enter-active">${i}</div>`)
  178. .join('') +
  179. `</span>`
  180. )
  181. })
  182. .thenWaitFor(nextFrame)
  183. .then(() => {
  184. expect(vm.$el.innerHTML).toBe(
  185. `<span>` +
  186. vm.items
  187. .map(
  188. (i) => `<div class="test v-enter-active v-enter-to">${i}</div>`
  189. )
  190. .join('') +
  191. `</span>`
  192. )
  193. })
  194. .thenWaitFor(duration + buffer)
  195. .then(() => {
  196. expect(vm.$el.innerHTML).toBe(
  197. `<span>` +
  198. vm.items.map((i) => `<div class="test">${i}</div>`).join('') +
  199. `</span>`
  200. )
  201. })
  202. .then(done)
  203. })
  204. it('events', (done) => {
  205. let next
  206. const beforeEnterSpy = vi.fn()
  207. const afterEnterSpy = vi.fn()
  208. const afterLeaveSpy = vi.fn()
  209. const vm = new Vue({
  210. template: `
  211. <div>
  212. <transition-group @before-enter="beforeEnter" @after-enter="afterEnter" @after-leave="afterLeave">
  213. <div v-for="item in items" :key="item" class="test">{{ item }}</div>
  214. </transition-group>
  215. </div>
  216. `,
  217. data: {
  218. items: ['a', 'b', 'c']
  219. },
  220. methods: {
  221. beforeEnter(el) {
  222. expect(el.textContent).toBe('d')
  223. beforeEnterSpy()
  224. },
  225. afterEnter(el) {
  226. expect(el.textContent).toBe('d')
  227. afterEnterSpy()
  228. next()
  229. },
  230. afterLeave(el) {
  231. expect(el.textContent).toBe('a')
  232. afterLeaveSpy()
  233. next()
  234. }
  235. }
  236. }).$mount(el)
  237. vm.items.push('d')
  238. waitForUpdate(() => {
  239. expect(vm.$el.innerHTML).toBe(
  240. `<span>` +
  241. `<div class="test">a</div>` +
  242. `<div class="test">b</div>` +
  243. `<div class="test">c</div>` +
  244. `<div class="test v-enter v-enter-active">d</div>` +
  245. `</span>`
  246. )
  247. expect(beforeEnterSpy.mock.calls.length).toBe(1)
  248. })
  249. .thenWaitFor((_next) => {
  250. next = _next
  251. })
  252. .then(() => {
  253. expect(vm.$el.innerHTML).toBe(
  254. `<span>` +
  255. `<div class="test">a</div>` +
  256. `<div class="test">b</div>` +
  257. `<div class="test">c</div>` +
  258. `<div class="test">d</div>` +
  259. `</span>`
  260. )
  261. expect(afterEnterSpy.mock.calls.length).toBe(1)
  262. vm.items.shift()
  263. })
  264. .thenWaitFor((_next) => {
  265. next = _next
  266. })
  267. .then(() => {
  268. expect(vm.$el.innerHTML).toBe(
  269. `<span>` +
  270. `<div class="test">b</div>` +
  271. `<div class="test">c</div>` +
  272. `<div class="test">d</div>` +
  273. `</span>`
  274. )
  275. expect(afterLeaveSpy.mock.calls.length).toBe(1)
  276. })
  277. .then(done)
  278. })
  279. it('move', (done) => {
  280. const vm = new Vue({
  281. template: `
  282. <div>
  283. <transition-group name="group">
  284. <div v-for="item in items" :key="item" class="test">{{ item }}</div>
  285. </transition-group>
  286. </div>
  287. `,
  288. data: {
  289. items: ['a', 'b', 'c']
  290. }
  291. }).$mount(el)
  292. vm.items = ['d', 'b', 'a']
  293. waitForUpdate(() => {
  294. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  295. `<span>` +
  296. `<div class="test group-enter group-enter-active">d</div>` +
  297. `<div class="test">b</div>` +
  298. `<div class="test group-move">a</div>` +
  299. `<div class="test group-leave group-leave-active group-move">c</div>` +
  300. `</span>`
  301. )
  302. })
  303. .thenWaitFor(nextFrame)
  304. .then(() => {
  305. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  306. `<span>` +
  307. `<div class="test group-enter-active group-enter-to">d</div>` +
  308. `<div class="test">b</div>` +
  309. `<div class="test group-move">a</div>` +
  310. `<div class="test group-leave-active group-move group-leave-to">c</div>` +
  311. `</span>`
  312. )
  313. })
  314. .thenWaitFor(duration * 2)
  315. .then(() => {
  316. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  317. `<span>` +
  318. `<div class="test">d</div>` +
  319. `<div class="test">b</div>` +
  320. `<div class="test">a</div>` +
  321. `</span>`
  322. )
  323. })
  324. .then(done)
  325. })
  326. it('warn unkeyed children', () => {
  327. new Vue({
  328. template: `<div><transition-group><div v-for="i in 3"></div></transition-group></div>`
  329. }).$mount()
  330. expect(
  331. '<transition-group> children must be keyed: <div>'
  332. ).toHaveBeenWarned()
  333. })
  334. // GitHub issue #6006
  335. it('should work with dynamic name', (done) => {
  336. const vm = new Vue({
  337. template: `
  338. <div>
  339. <transition-group :name="name">
  340. <div v-for="item in items" :key="item">{{ item }}</div>
  341. </transition-group>
  342. </div>
  343. `,
  344. data: {
  345. items: ['a', 'b', 'c'],
  346. name: 'group'
  347. }
  348. }).$mount(el)
  349. vm.name = 'invalid-name'
  350. vm.items = ['b', 'c', 'a']
  351. waitForUpdate(() => {
  352. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  353. `<span>` + `<div>b</div>` + `<div>c</div>` + `<div>a</div>` + `</span>`
  354. )
  355. vm.name = 'group'
  356. vm.items = ['a', 'b', 'c']
  357. })
  358. .thenWaitFor(nextFrame)
  359. .then(() => {
  360. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  361. `<span>` +
  362. `<div class="group-move">a</div>` +
  363. `<div class="group-move">b</div>` +
  364. `<div class="group-move">c</div>` +
  365. `</span>`
  366. )
  367. })
  368. .thenWaitFor(duration * 2 + buffer)
  369. .then(() => {
  370. expect(vm.$el.innerHTML.replace(/\s?style=""(\s?)/g, '$1')).toBe(
  371. `<span>` +
  372. `<div>a</div>` +
  373. `<div>b</div>` +
  374. `<div>c</div>` +
  375. `</span>`
  376. )
  377. })
  378. .then(done)
  379. })
  380. })