transition.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. describe('UNIT: Transition', function () {
  2. var transition = require('vue/src/transition'),
  3. config = require('vue/src/config'),
  4. codes = transition.codes,
  5. endEvent = sniffTransitionEndEvent(),
  6. enterClass = config.enterClass,
  7. leaveClass = config.leaveClass
  8. describe('General', function () {
  9. it('should skip if compiler is in init stage', function () {
  10. var c = mockChange(),
  11. compiler = mockCompiler()
  12. compiler.init = true
  13. var code = transition(null, 1, c.change, compiler)
  14. assert.ok(c.called)
  15. assert.strictEqual(code, codes.INIT)
  16. assert.ok(compiler.enteredView)
  17. })
  18. it('should skip if no transition is found on the node', function () {
  19. var c = mockChange(),
  20. compiler = mockCompiler(),
  21. code = transition(mockEl(), 1, c.change, compiler)
  22. assert.ok(c.called)
  23. assert.strictEqual(code, codes.SKIP)
  24. assert.ok(compiler.enteredView)
  25. })
  26. })
  27. describe('CSS class transition', function () {
  28. if (!endEvent) { // IE9 only test case
  29. it('should skip if transition is not available', function () {
  30. var c = mockChange(),
  31. compiler = mockCompiler(),
  32. code = transition(mockEl('css'), 1, c.change, compiler)
  33. assert.ok(c.called)
  34. assert.strictEqual(code, codes.CSS_SKIP)
  35. assert.ok(compiler.enteredView)
  36. })
  37. // skip the rest
  38. return
  39. }
  40. describe('enter', function () {
  41. var el = mockEl('css'),
  42. c = mockChange(function () {
  43. c.called = true
  44. assert.ok(el.classList.contains(enterClass))
  45. }),
  46. compiler = mockCompiler(),
  47. code,
  48. cbCalled = false
  49. el.vue_trans_cb = function () {
  50. cbCalled = true
  51. }
  52. el.addEventListener(endEvent, el.vue_trans_cb)
  53. it('should add the class before calling changeState()', function () {
  54. code = transition(el, 1, c.change, compiler)
  55. assert.ok(c.called)
  56. })
  57. it('should remove unfinished leave callback if exists', function () {
  58. assert.notOk(el.vue_trans_cb)
  59. var e = mockHTMLEvent(endEvent)
  60. el.dispatchEvent(e)
  61. assert.notOk(cbCalled)
  62. })
  63. it('should remove the class afterwards', function () {
  64. assert.notOk(el.classList.contains(enterClass))
  65. })
  66. it('should return correct code', function () {
  67. assert.strictEqual(code, codes.CSS_E)
  68. })
  69. it('should have called enteredView hook', function () {
  70. assert.ok(compiler.enteredView)
  71. })
  72. })
  73. describe('leave', function () {
  74. var el = mockEl('css'),
  75. c = mockChange(),
  76. compiler = mockCompiler(),
  77. code = transition(el, -1, c.change, compiler)
  78. it('should attach an ontransitionend listener', function () {
  79. assert.ok(typeof el.vue_trans_cb === 'function')
  80. })
  81. it('should add the class', function () {
  82. assert.ok(el.classList.contains(leaveClass))
  83. })
  84. it('should call changeState on transitionend', function () {
  85. var e = mockHTMLEvent(endEvent)
  86. el.dispatchEvent(e)
  87. assert.ok(c.called)
  88. })
  89. it('should remove the callback after called', function () {
  90. assert.notOk(el.vue_trans_cb)
  91. var e = mockHTMLEvent(endEvent)
  92. el.dispatchEvent(e)
  93. assert.strictEqual(c.n, 1)
  94. })
  95. it('should remove the class after called', function () {
  96. assert.notOk(el.classList.contains(leaveClass))
  97. })
  98. it('should return correct code', function () {
  99. assert.strictEqual(code, codes.CSS_L)
  100. })
  101. it('should have called leftView hook', function () {
  102. assert.ok(compiler.leftView)
  103. })
  104. })
  105. })
  106. describe('JavaScript transition', function () {
  107. it('should skip if correspinding option is not defined', function () {
  108. var c = mockChange(),
  109. compiler = mockCompiler(),
  110. code = transition(mockEl('js'), 1, c.change, compiler)
  111. assert.ok(c.called)
  112. assert.strictEqual(code, codes.JS_SKIP)
  113. assert.ok(compiler.enteredView)
  114. })
  115. it('should skip if the option is given but the enter/leave func is not defined', function () {
  116. var c = mockChange(),
  117. compiler = mockCompiler({}),
  118. code = transition(mockEl('js'), 1, c.change, compiler)
  119. assert.ok(c.called)
  120. assert.strictEqual(code, codes.JS_SKIP_E)
  121. assert.ok(compiler.enteredView)
  122. c = mockChange()
  123. compiler = mockCompiler({})
  124. code = transition(mockEl('js'), -1, c.change, compiler)
  125. assert.ok(c.called)
  126. assert.strictEqual(code, codes.JS_SKIP_L)
  127. assert.ok(compiler.leftView)
  128. })
  129. describe('enter', function () {
  130. var code,
  131. c = mockChange(),
  132. el = mockEl('js'),
  133. def = {
  134. enter: function (element, change) {
  135. assert.strictEqual(el, element)
  136. change()
  137. }
  138. },
  139. compiler = mockCompiler(def)
  140. it('should call the enter function', function () {
  141. code = transition(el, 1, c.change, compiler)
  142. assert.ok(c.called)
  143. })
  144. it('should return correct code', function () {
  145. assert.strictEqual(code, codes.JS_E)
  146. })
  147. it('should have called enteredView hook', function () {
  148. assert.ok(compiler.enteredView)
  149. })
  150. })
  151. describe('leave', function () {
  152. var code,
  153. c = mockChange(),
  154. el = mockEl('js'),
  155. def = {
  156. leave: function (element, change) {
  157. assert.strictEqual(el, element)
  158. change()
  159. }
  160. },
  161. compiler = mockCompiler(def)
  162. it('should call the leave function', function () {
  163. code = transition(el, -1, c.change, compiler)
  164. assert.ok(c.called)
  165. })
  166. it('should return correct code', function () {
  167. assert.strictEqual(code, codes.JS_L)
  168. })
  169. it('should have called leftView hook', function () {
  170. assert.ok(compiler.leftView)
  171. })
  172. })
  173. })
  174. function mockChange (change) {
  175. var c = {
  176. called: false,
  177. n: 0,
  178. change: change || function () {
  179. c.called = true
  180. c.n += 1
  181. }
  182. }
  183. return c
  184. }
  185. function mockEl (type) {
  186. var el = document.createElement('div')
  187. if (type === 'css') {
  188. el.vue_trans = ''
  189. } else if (type === 'js') {
  190. el.vue_trans = 'test'
  191. }
  192. return el
  193. }
  194. function mockCompiler (opt) {
  195. return {
  196. getOption: function () {
  197. return opt
  198. },
  199. execHook: function (hook) {
  200. this[hook] = true
  201. }
  202. }
  203. }
  204. function sniffTransitionEndEvent () {
  205. var el = document.createElement('vue'),
  206. defaultEvent = 'transitionend',
  207. events = {
  208. 'transition' : defaultEvent,
  209. 'MozTransition' : defaultEvent,
  210. 'WebkitTransition' : 'webkitTransitionEnd'
  211. }
  212. for (var name in events) {
  213. if (el.style[name] !== undefined) {
  214. return events[name]
  215. }
  216. }
  217. }
  218. })