emittermixin.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /**
  2. * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. 'use strict';
  6. const modules = bender.amd.require( 'core/emittermixin', 'core/eventinfo', 'core/lib/lodash/object' );
  7. let EmitterMixin, EventInfo, utilsObject;
  8. let emitter, listener;
  9. before( () => {
  10. EmitterMixin = modules[ 'core/emittermixin' ];
  11. EventInfo = modules[ 'core/eventinfo' ];
  12. utilsObject = modules[ 'core/lib/lodash/object' ];
  13. } );
  14. beforeEach( refreshEmitter );
  15. describe( 'fire', () => {
  16. it( 'should execute callbacks in the right order without priority', () => {
  17. let spy1 = sinon.spy().named( 1 );
  18. let spy2 = sinon.spy().named( 2 );
  19. let spy3 = sinon.spy().named( 3 );
  20. emitter.on( 'test', spy1 );
  21. emitter.on( 'test', spy2 );
  22. emitter.on( 'test', spy3 );
  23. emitter.fire( 'test' );
  24. sinon.assert.callOrder( spy1, spy2, spy3 );
  25. } );
  26. it( 'should execute callbacks in the right order with priority defined', () => {
  27. let spy1 = sinon.spy().named( 1 );
  28. let spy2 = sinon.spy().named( 2 );
  29. let spy3 = sinon.spy().named( 3 );
  30. let spy4 = sinon.spy().named( 4 );
  31. let spy5 = sinon.spy().named( 5 );
  32. emitter.on( 'test', spy2, null, 9 );
  33. emitter.on( 'test', spy3 ); // Defaults to 10.
  34. emitter.on( 'test', spy4, null, 11 );
  35. emitter.on( 'test', spy1, null, -1 );
  36. emitter.on( 'test', spy5, null, 11 );
  37. emitter.fire( 'test' );
  38. sinon.assert.callOrder( spy1, spy2, spy3, spy4, spy5 );
  39. } );
  40. it( 'should pass arguments to callbacks', () => {
  41. let spy1 = sinon.spy();
  42. let spy2 = sinon.spy();
  43. emitter.on( 'test', spy1 );
  44. emitter.on( 'test', spy2 );
  45. emitter.fire( 'test', 1, 'b', true );
  46. sinon.assert.calledWithExactly( spy1, sinon.match.instanceOf( EventInfo ), 1, 'b', true );
  47. sinon.assert.calledWithExactly( spy2, sinon.match.instanceOf( EventInfo ), 1, 'b', true );
  48. } );
  49. it( 'should pass proper context to callbacks', () => {
  50. let ctx1 = {};
  51. let ctx2 = {};
  52. let spy1 = sinon.spy();
  53. let spy2 = sinon.spy();
  54. let spy3 = sinon.spy();
  55. emitter.on( 'test', spy1, ctx1 );
  56. emitter.on( 'test', spy2, ctx2 );
  57. emitter.on( 'test', spy3 );
  58. emitter.fire( 'test' );
  59. sinon.assert.calledOn( spy1, ctx1 );
  60. sinon.assert.calledOn( spy2, ctx2 );
  61. sinon.assert.calledOn( spy3, emitter );
  62. } );
  63. it( 'should fire the right event', () => {
  64. let spy1 = sinon.spy();
  65. let spy2 = sinon.spy();
  66. emitter.on( '1', spy1 );
  67. emitter.on( '2', spy2 );
  68. emitter.fire( '2' );
  69. sinon.assert.notCalled( spy1 );
  70. sinon.assert.called( spy2 );
  71. } );
  72. it( 'should execute callbacks many times', () => {
  73. let spy = sinon.spy();
  74. emitter.on( 'test', spy );
  75. emitter.fire( 'test' );
  76. emitter.fire( 'test' );
  77. emitter.fire( 'test' );
  78. sinon.assert.calledThrice( spy );
  79. } );
  80. it( 'should do nothing for a non listened event', () => {
  81. emitter.fire( 'test' );
  82. } );
  83. it( 'should accept the same callback many times', () => {
  84. let spy = sinon.spy();
  85. emitter.on( 'test', spy );
  86. emitter.on( 'test', spy );
  87. emitter.on( 'test', spy );
  88. emitter.fire( 'test' );
  89. sinon.assert.calledThrice( spy );
  90. } );
  91. it( 'should not fire callbacks for an event that were added while firing that event', () => {
  92. let spy = sinon.spy();
  93. emitter.on( 'test', () => {
  94. emitter.on( 'test', spy );
  95. } );
  96. emitter.fire( 'test' );
  97. sinon.assert.notCalled( spy );
  98. } );
  99. } );
  100. describe( 'on', () => {
  101. it( 'should stop()', () => {
  102. let spy1 = sinon.spy();
  103. let spy2 = sinon.spy();
  104. let spy3 = sinon.spy( ( event ) => {
  105. event.stop();
  106. } );
  107. emitter.on( 'test', spy1 );
  108. emitter.on( 'test', spy2 );
  109. emitter.on( 'test', spy3 );
  110. emitter.on( 'test', sinon.stub().throws() );
  111. emitter.on( 'test', sinon.stub().throws() );
  112. emitter.fire( 'test' );
  113. sinon.assert.called( spy1 );
  114. sinon.assert.called( spy2 );
  115. sinon.assert.called( spy3 );
  116. } );
  117. it( 'should take a callback off()', () => {
  118. let spy1 = sinon.spy();
  119. let spy2 = sinon.spy( ( event ) => {
  120. event.off();
  121. } );
  122. let spy3 = sinon.spy();
  123. emitter.on( 'test', spy1 );
  124. emitter.on( 'test', spy2 );
  125. emitter.on( 'test', spy3 );
  126. emitter.fire( 'test' );
  127. emitter.fire( 'test' );
  128. sinon.assert.calledTwice( spy1 );
  129. sinon.assert.calledOnce( spy2 );
  130. sinon.assert.calledTwice( spy3 );
  131. } );
  132. it( 'should take the callback off() even after stop()', () => {
  133. let spy1 = sinon.spy( ( event ) => {
  134. event.stop();
  135. event.off();
  136. } );
  137. let spy2 = sinon.spy();
  138. emitter.on( 'test', spy1 );
  139. emitter.on( 'test', spy2 );
  140. emitter.fire( 'test' );
  141. emitter.fire( 'test' );
  142. sinon.assert.calledOnce( spy1 );
  143. sinon.assert.calledOnce( spy2 );
  144. } );
  145. } );
  146. describe( 'once', () => {
  147. it( 'should be called just once', () => {
  148. let spy1 = sinon.spy();
  149. let spy2 = sinon.spy();
  150. let spy3 = sinon.spy();
  151. emitter.on( 'test', spy1 );
  152. emitter.once( 'test', spy2 );
  153. emitter.on( 'test', spy3 );
  154. emitter.fire( 'test' );
  155. emitter.fire( 'test' );
  156. sinon.assert.calledTwice( spy1 );
  157. sinon.assert.calledOnce( spy2 );
  158. sinon.assert.calledTwice( spy3 );
  159. } );
  160. it( 'should have proper scope', () => {
  161. let ctx = {};
  162. let spy1 = sinon.spy();
  163. let spy2 = sinon.spy();
  164. emitter.once( 'test', spy1, ctx );
  165. emitter.once( 'test', spy2 );
  166. emitter.fire( 'test' );
  167. sinon.assert.calledOn( spy1, ctx );
  168. sinon.assert.calledOn( spy2, emitter );
  169. } );
  170. it( 'should have proper arguments', () => {
  171. let spy = sinon.spy();
  172. emitter.once( 'test', spy );
  173. emitter.fire( 'test', 1, 2, 3 );
  174. sinon.assert.calledWithExactly( spy, sinon.match.instanceOf( EventInfo ), 1, 2, 3 );
  175. } );
  176. } );
  177. describe( 'off', () => {
  178. it( 'should get callbacks off()', () => {
  179. let spy1 = sinon.spy();
  180. let spy2 = sinon.spy();
  181. let spy3 = sinon.spy();
  182. emitter.on( 'test', spy1 );
  183. emitter.on( 'test', spy2 );
  184. emitter.on( 'test', spy3 );
  185. emitter.fire( 'test' );
  186. emitter.off( 'test', spy2 );
  187. emitter.fire( 'test' );
  188. emitter.fire( 'test' );
  189. sinon.assert.calledThrice( spy1 );
  190. sinon.assert.calledOnce( spy2 );
  191. sinon.assert.calledThrice( spy3 );
  192. } );
  193. it( 'should not fail with unknown events', () => {
  194. emitter.off( 'test', () => {} );
  195. } );
  196. it( 'should remove all entries for the same callback', () => {
  197. let spy1 = sinon.spy().named( 1 );
  198. let spy2 = sinon.spy().named( 2 );
  199. emitter.on( 'test', spy1 );
  200. emitter.on( 'test', spy2 );
  201. emitter.on( 'test', spy1 );
  202. emitter.on( 'test', spy2 );
  203. emitter.fire( 'test' );
  204. emitter.off( 'test', spy1 );
  205. emitter.fire( 'test' );
  206. sinon.assert.callCount( spy1, 2 );
  207. sinon.assert.callCount( spy2, 4 );
  208. } );
  209. it( 'should remove the callback for a specific context only', () => {
  210. let spy = sinon.spy().named( 1 );
  211. let ctx1 = { ctx: 1 };
  212. let ctx2 = { ctx: 2 };
  213. emitter.on( 'test', spy, ctx1 );
  214. emitter.on( 'test', spy, ctx2 );
  215. emitter.fire( 'test' );
  216. spy.reset();
  217. emitter.off( 'test', spy, ctx1 );
  218. emitter.fire( 'test' );
  219. sinon.assert.calledOnce( spy );
  220. sinon.assert.calledOn( spy, ctx2 );
  221. } );
  222. } );
  223. describe( 'listenTo', () => {
  224. beforeEach( refreshListener );
  225. it( 'should properly register callbacks', () => {
  226. let spy = sinon.spy();
  227. listener.listenTo( emitter, 'test', spy );
  228. emitter.fire( 'test' );
  229. sinon.assert.called( spy );
  230. } );
  231. } );
  232. describe( 'stopListening', () => {
  233. beforeEach( refreshListener );
  234. it( 'should stop listening to a specific event callback', () => {
  235. let spy1 = sinon.spy();
  236. let spy2 = sinon.spy();
  237. listener.listenTo( emitter, 'event1', spy1 );
  238. listener.listenTo( emitter, 'event2', spy2 );
  239. emitter.fire( 'event1' );
  240. emitter.fire( 'event2' );
  241. listener.stopListening( emitter, 'event1', spy1 );
  242. emitter.fire( 'event1' );
  243. emitter.fire( 'event2' );
  244. sinon.assert.calledOnce( spy1 );
  245. sinon.assert.calledTwice( spy2 );
  246. } );
  247. it( 'should stop listening to an specific event', () => {
  248. let spy1a = sinon.spy();
  249. let spy1b = sinon.spy();
  250. let spy2 = sinon.spy();
  251. listener.listenTo( emitter, 'event1', spy1a );
  252. listener.listenTo( emitter, 'event1', spy1b );
  253. listener.listenTo( emitter, 'event2', spy2 );
  254. emitter.fire( 'event1' );
  255. emitter.fire( 'event2' );
  256. listener.stopListening( emitter, 'event1' );
  257. emitter.fire( 'event1' );
  258. emitter.fire( 'event2' );
  259. sinon.assert.calledOnce( spy1a );
  260. sinon.assert.calledOnce( spy1b );
  261. sinon.assert.calledTwice( spy2 );
  262. } );
  263. it( 'should stop listening to all events from a specific emitter', () => {
  264. let spy1 = sinon.spy();
  265. let spy2 = sinon.spy();
  266. listener.listenTo( emitter, 'event1', spy1 );
  267. listener.listenTo( emitter, 'event2', spy2 );
  268. emitter.fire( 'event1' );
  269. emitter.fire( 'event2' );
  270. listener.stopListening( emitter );
  271. emitter.fire( 'event1' );
  272. emitter.fire( 'event2' );
  273. sinon.assert.calledOnce( spy1 );
  274. sinon.assert.calledOnce( spy2 );
  275. } );
  276. it( 'should stop listening to everything', () => {
  277. let spy1 = sinon.spy();
  278. let spy2 = sinon.spy();
  279. let emitter1 = getEmitterInstance();
  280. let emitter2 = getEmitterInstance();
  281. listener.listenTo( emitter1, 'event1', spy1 );
  282. listener.listenTo( emitter2, 'event2', spy2 );
  283. expect( listener ).to.have.property( '_listeningTo' );
  284. emitter1.fire( 'event1' );
  285. emitter2.fire( 'event2' );
  286. listener.stopListening();
  287. emitter1.fire( 'event1' );
  288. emitter2.fire( 'event2' );
  289. sinon.assert.calledOnce( spy1 );
  290. sinon.assert.calledOnce( spy2 );
  291. expect( listener ).to.not.have.property( '_listeningTo' );
  292. } );
  293. it( 'should not stop other emitters when a non-listened emitter is provided', () => {
  294. let spy = sinon.spy();
  295. let emitter1 = getEmitterInstance();
  296. let emitter2 = getEmitterInstance();
  297. listener.listenTo( emitter1, 'test', spy );
  298. listener.stopListening( emitter2 );
  299. emitter1.fire( 'test' );
  300. sinon.assert.called( spy );
  301. } );
  302. } );
  303. function refreshEmitter() {
  304. emitter = getEmitterInstance();
  305. }
  306. function refreshListener() {
  307. listener = getEmitterInstance();
  308. }
  309. function getEmitterInstance() {
  310. return utilsObject.extend( {}, EmitterMixin );
  311. }