events_spec.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. var Vue = require('src')
  2. describe('Events API', function () {
  3. var vm, spy
  4. beforeEach(function () {
  5. vm = new Vue()
  6. spy = jasmine.createSpy('emitter')
  7. })
  8. it('$on', function () {
  9. vm.$on('test', function () {
  10. // expect correct context
  11. expect(this).toBe(vm)
  12. spy.apply(this, arguments)
  13. })
  14. vm.$emit('test', 1, 2, 3, 4)
  15. expect(spy.calls.count()).toBe(1)
  16. expect(spy).toHaveBeenCalledWith(1, 2, 3, 4)
  17. })
  18. it('$once', function () {
  19. vm.$once('test', spy)
  20. vm.$emit('test', 1, 2, 3)
  21. vm.$emit('test', 2, 3, 4)
  22. expect(spy.calls.count()).toBe(1)
  23. expect(spy).toHaveBeenCalledWith(1, 2, 3)
  24. })
  25. it('$off', function () {
  26. vm.$on('test1', spy)
  27. vm.$on('test2', spy)
  28. vm.$off()
  29. vm.$emit('test1')
  30. vm.$emit('test2')
  31. expect(spy).not.toHaveBeenCalled()
  32. })
  33. it('$off event', function () {
  34. vm.$on('test1', spy)
  35. vm.$on('test2', spy)
  36. vm.$off('test1')
  37. vm.$off('test1') // test off something that's already off
  38. vm.$emit('test1', 1)
  39. vm.$emit('test2', 2)
  40. expect(spy.calls.count()).toBe(1)
  41. expect(spy).toHaveBeenCalledWith(2)
  42. })
  43. it('$off event + fn', function () {
  44. var spy2 = jasmine.createSpy('emitter')
  45. vm.$on('test', spy)
  46. vm.$on('test', spy2)
  47. vm.$off('test', spy)
  48. vm.$emit('test', 1, 2, 3)
  49. expect(spy).not.toHaveBeenCalled()
  50. expect(spy2.calls.count()).toBe(1)
  51. expect(spy2).toHaveBeenCalledWith(1, 2, 3)
  52. })
  53. it('$broadcast', function () {
  54. var child1 = new Vue({ parent: vm })
  55. var child2 = new Vue({ parent: vm })
  56. var child3 = new Vue({ parent: child1 })
  57. child1.$on('test', spy)
  58. child2.$on('test', spy)
  59. child3.$on('test', spy)
  60. vm.$broadcast('test')
  61. expect(spy.calls.count()).toBe(2) // should not propagate by default
  62. })
  63. it('$broadcast with propagation', function () {
  64. var child1 = new Vue({ parent: vm })
  65. var child2 = new Vue({ parent: vm })
  66. var child3 = new Vue({ parent: child1 })
  67. child1.$on('test', function () {
  68. spy()
  69. return true
  70. })
  71. child2.$on('test', spy)
  72. child3.$on('test', spy)
  73. vm.$broadcast('test')
  74. expect(spy.calls.count()).toBe(3)
  75. })
  76. it('$broadcast optimization', function () {
  77. var child = new Vue({ parent: vm })
  78. var child2 = new Vue({ parent: child })
  79. // hooks should not incurr the bookkeeping cost
  80. child.$on('hook:created', function () {})
  81. expect(vm._eventsCount['hook:created']).toBeUndefined()
  82. function handler () {
  83. spy()
  84. return true
  85. }
  86. child.$on('test', handler)
  87. expect(vm._eventsCount['test']).toBe(1)
  88. // child2's $emit & $broadcast
  89. // shouldn't get called if no child listens to the event
  90. child2.$emit = spy
  91. child2.$broadcast = spy
  92. vm.$broadcast('test')
  93. expect(spy.calls.count()).toBe(1)
  94. // check $off bookkeeping
  95. child.$off('test', handler)
  96. expect(vm._eventsCount['test']).toBe(0)
  97. function noop () {}
  98. child.$on('test', noop)
  99. child2.$on('test', noop)
  100. expect(vm._eventsCount['test']).toBe(2)
  101. child.$off('test')
  102. expect(vm._eventsCount['test']).toBe(1)
  103. child.$on('test', noop)
  104. child2.$on('test', noop)
  105. expect(vm._eventsCount['test']).toBe(3)
  106. child.$off()
  107. child2.$off()
  108. expect(vm._eventsCount['test']).toBe(0)
  109. })
  110. it('$broadcast cancel', function () {
  111. var child = new Vue({ parent: vm })
  112. var child2 = new Vue({ parent: child })
  113. child.$on('test', function () {
  114. return false
  115. })
  116. child2.$on('test', spy)
  117. vm.$broadcast('test')
  118. expect(spy).not.toHaveBeenCalled()
  119. })
  120. it('$dispatch', function () {
  121. var child = new Vue({ parent: vm })
  122. var child2 = new Vue({ parent: child })
  123. child2.$on('test', spy)
  124. child.$on('test', spy)
  125. vm.$on('test', spy)
  126. child2.$dispatch('test')
  127. expect(spy.calls.count()).toBe(2) // should trigger on self, but not propagate to root
  128. })
  129. it('$dispatch with propagation', function () {
  130. var child = new Vue({ parent: vm })
  131. var child2 = new Vue({ parent: child })
  132. var child3 = new Vue({ parent: child2 })
  133. child.$on('test', function () {
  134. spy()
  135. return true
  136. })
  137. vm.$on('test', spy)
  138. child3.$dispatch('test')
  139. expect(spy.calls.count()).toBe(2)
  140. })
  141. it('handle $dispatch by v-on inline-statement', function () {
  142. var parent = new Vue({
  143. el: document.createElement('div'),
  144. template: '<child1 @test="onTest()" v-ref:child></child1>',
  145. methods: {
  146. onTest: function () {
  147. spy()
  148. }
  149. },
  150. components: {
  151. child1: {
  152. template: '<child2 @test="onTest" v-ref:child></child2>',
  153. methods: {
  154. onTest: function () {
  155. spy()
  156. }
  157. },
  158. components: {
  159. child2: {
  160. template: '<child3 @test="onTest()" v-ref:child></child3>',
  161. methods: {
  162. onTest: function () {
  163. spy()
  164. return true
  165. }
  166. },
  167. components: {
  168. child3: {
  169. template: '<child4 @test="onTest" v-ref:child></child4>',
  170. methods: {
  171. onTest: function () {
  172. spy()
  173. return true
  174. }
  175. },
  176. components: {
  177. child4: {}
  178. }
  179. }
  180. }
  181. }
  182. }
  183. }
  184. }
  185. })
  186. parent
  187. .$refs.child // child1
  188. .$refs.child // child2
  189. .$refs.child // child3
  190. .$refs.child // child4
  191. .$dispatch('test')
  192. expect(spy.calls.count()).toBe(3)
  193. })
  194. it('$dispatch forward on immediate inline component handler', function () {
  195. var shouldPropagate = true
  196. var parent = new Vue({
  197. el: document.createElement('div'),
  198. template: '<child @test="onTest" v-ref:child></child>',
  199. events: {
  200. test: spy
  201. },
  202. methods: {
  203. onTest: function () {
  204. spy()
  205. return shouldPropagate
  206. }
  207. },
  208. components: {
  209. child: {}
  210. }
  211. })
  212. parent.$refs.child.$dispatch('test')
  213. expect(spy.calls.count()).toBe(2)
  214. shouldPropagate = false
  215. parent.$refs.child.$dispatch('test')
  216. expect(spy.calls.count()).toBe(3)
  217. })
  218. })