events_spec.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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 v-ref:child></child4>',
  170. // `v-on` on component will be treat as its inner handler
  171. // so propagation cancelling is ignored on `<child4 @test="handler">`
  172. components: {
  173. child4: {}
  174. }
  175. }
  176. }
  177. }
  178. }
  179. }
  180. }
  181. })
  182. parent
  183. .$refs.child // child1
  184. .$refs.child // child2
  185. .$refs.child // child3
  186. .$refs.child // child4
  187. .$dispatch('test')
  188. expect(spy.calls.count()).toBe(2)
  189. })
  190. it('$dispatch cancel', function () {
  191. var child = new Vue({ parent: vm })
  192. var child2 = new Vue({ parent: child })
  193. child.$on('test', function () {
  194. return false
  195. })
  196. vm.$on('test', spy)
  197. child2.$dispatch('test')
  198. expect(spy).not.toHaveBeenCalled()
  199. })
  200. })