8
0

emittermixin.js 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177
  1. /**
  2. * @license Copyright (c) 2003-2017, CKSource - Frederico Knabben. All rights reserved.
  3. * For licensing, see LICENSE.md.
  4. */
  5. import { default as EmitterMixin, _getEmitterListenedTo, _getEmitterId, _setEmitterId } from '../src/emittermixin';
  6. import EventInfo from '../src/eventinfo';
  7. describe( 'EmitterMixin', () => {
  8. let emitter, listener;
  9. beforeEach( () => {
  10. emitter = getEmitterInstance();
  11. listener = getEmitterInstance();
  12. } );
  13. describe( 'fire', () => {
  14. it( 'should execute callbacks in the right order without priority', () => {
  15. const spy1 = sinon.spy().named( 1 );
  16. const spy2 = sinon.spy().named( 2 );
  17. const spy3 = sinon.spy().named( 3 );
  18. emitter.on( 'test', spy1 );
  19. emitter.on( 'test', spy2 );
  20. emitter.on( 'test', spy3 );
  21. emitter.fire( 'test' );
  22. sinon.assert.callOrder( spy1, spy2, spy3 );
  23. } );
  24. it( 'should execute callbacks in the right order with priority defined', () => {
  25. const spy1 = sinon.spy().named( 1 );
  26. const spy2 = sinon.spy().named( 2 );
  27. const spy3 = sinon.spy().named( 3 );
  28. const spy4 = sinon.spy().named( 4 );
  29. const spy5 = sinon.spy().named( 5 );
  30. emitter.on( 'test', spy2, { priority: 'high' } );
  31. emitter.on( 'test', spy3 ); // Defaults to 'normal'.
  32. emitter.on( 'test', spy4, { priority: 'low' } );
  33. emitter.on( 'test', spy1, { priority: 'highest' } );
  34. emitter.on( 'test', spy5, { priority: 'lowest' } );
  35. emitter.fire( 'test' );
  36. sinon.assert.callOrder( spy1, spy2, spy3, spy4, spy5 );
  37. } );
  38. it( 'should pass arguments to callbacks', () => {
  39. const spy1 = sinon.spy();
  40. const spy2 = sinon.spy();
  41. emitter.on( 'test', spy1 );
  42. emitter.on( 'test', spy2 );
  43. emitter.fire( 'test', 1, 'b', true );
  44. sinon.assert.calledWithExactly( spy1, sinon.match.instanceOf( EventInfo ), 1, 'b', true );
  45. sinon.assert.calledWithExactly( spy2, sinon.match.instanceOf( EventInfo ), 1, 'b', true );
  46. } );
  47. it( 'should pass proper context to callbacks', () => {
  48. const spy = sinon.spy();
  49. emitter.on( 'test', spy );
  50. emitter.fire( 'test' );
  51. sinon.assert.calledOn( spy, emitter );
  52. } );
  53. it( 'should fire the right event', () => {
  54. const spy1 = sinon.spy();
  55. const spy2 = sinon.spy();
  56. emitter.on( '1', spy1 );
  57. emitter.on( '2', spy2 );
  58. emitter.fire( '2' );
  59. sinon.assert.notCalled( spy1 );
  60. sinon.assert.called( spy2 );
  61. } );
  62. it( 'should execute callbacks many times', () => {
  63. const spy = sinon.spy();
  64. emitter.on( 'test', spy );
  65. emitter.fire( 'test' );
  66. emitter.fire( 'test' );
  67. emitter.fire( 'test' );
  68. sinon.assert.calledThrice( spy );
  69. } );
  70. it( 'should do nothing for a non listened event', () => {
  71. emitter.fire( 'test' );
  72. } );
  73. it( 'should accept the same callback many times', () => {
  74. const spy = sinon.spy();
  75. emitter.on( 'test', spy );
  76. emitter.on( 'test', spy );
  77. emitter.on( 'test', spy );
  78. emitter.fire( 'test' );
  79. sinon.assert.calledThrice( spy );
  80. } );
  81. it( 'should not fire callbacks for an event that were added while firing that event', () => {
  82. const spy = sinon.spy();
  83. emitter.on( 'test', () => {
  84. emitter.on( 'test', spy );
  85. } );
  86. emitter.fire( 'test' );
  87. sinon.assert.notCalled( spy );
  88. } );
  89. it( 'should correctly fire callbacks for namespaced events', () => {
  90. const spyFoo = sinon.spy();
  91. const spyBar = sinon.spy();
  92. const spyAbc = sinon.spy();
  93. const spyFoo2 = sinon.spy();
  94. // Mess up with callbacks order to check whether they are called in adding order.
  95. emitter.on( 'foo', spyFoo );
  96. emitter.on( 'foo:bar:abc', spyAbc );
  97. emitter.on( 'foo:bar', spyBar );
  98. // This tests whether generic callbacks are also added to specific callbacks lists.
  99. emitter.on( 'foo', spyFoo2 );
  100. // All four callbacks should be fired.
  101. emitter.fire( 'foo:bar:abc' );
  102. sinon.assert.callOrder( spyFoo, spyAbc, spyBar, spyFoo2 );
  103. sinon.assert.calledOnce( spyFoo );
  104. sinon.assert.calledOnce( spyAbc );
  105. sinon.assert.calledOnce( spyBar );
  106. sinon.assert.calledOnce( spyFoo2 );
  107. // Only callbacks for foo and foo:bar event should be called.
  108. emitter.fire( 'foo:bar' );
  109. sinon.assert.calledOnce( spyAbc );
  110. sinon.assert.calledTwice( spyFoo );
  111. sinon.assert.calledTwice( spyBar );
  112. sinon.assert.calledTwice( spyFoo2 );
  113. // Only callback for foo should be called as foo:abc has not been registered.
  114. // Still, foo is a valid, existing namespace.
  115. emitter.fire( 'foo:abc' );
  116. sinon.assert.calledOnce( spyAbc );
  117. sinon.assert.calledTwice( spyBar );
  118. sinon.assert.calledThrice( spyFoo );
  119. sinon.assert.calledThrice( spyFoo2 );
  120. } );
  121. describe( 'return value', () => {
  122. it( 'is undefined by default', () => {
  123. expect( emitter.fire( 'foo' ) ).to.be.undefined;
  124. } );
  125. it( 'is undefined if none of the listeners modified EventInfo#return', () => {
  126. emitter.on( 'foo', () => {} );
  127. expect( emitter.fire( 'foo' ) ).to.be.undefined;
  128. } );
  129. it( 'equals EventInfo#return\'s value', () => {
  130. emitter.on( 'foo', evt => {
  131. evt.return = 1;
  132. } );
  133. expect( emitter.fire( 'foo' ) ).to.equal( 1 );
  134. } );
  135. it( 'equals EventInfo#return\'s value even if the event was stopped', () => {
  136. emitter.on( 'foo', evt => {
  137. evt.return = 1;
  138. } );
  139. emitter.on( 'foo', evt => {
  140. evt.stop();
  141. } );
  142. expect( emitter.fire( 'foo' ) ).to.equal( 1 );
  143. } );
  144. it( 'equals EventInfo#return\'s value when it was set in a namespaced event', () => {
  145. emitter.on( 'foo', evt => {
  146. evt.return = 1;
  147. } );
  148. expect( emitter.fire( 'foo:bar' ) ).to.equal( 1 );
  149. } );
  150. // Rationale – delegation keeps the listeners of the two objects separate.
  151. // E.g. the emitterB's listeners will always be executed before emitterA's ones.
  152. // Hence, values should not be shared either.
  153. it( 'is not affected by listeners executed on emitter to which the event was delegated', () => {
  154. const emitterA = getEmitterInstance();
  155. const emitterB = getEmitterInstance();
  156. emitterB.delegate( 'foo' ).to( emitterA );
  157. emitterA.on( 'foo', evt => {
  158. evt.return = 1;
  159. } );
  160. expect( emitterB.fire( 'foo' ) ).to.be.undefined;
  161. } );
  162. it( 'equals the value set by the last callback', () => {
  163. emitter.on( 'foo', evt => {
  164. evt.return = 1;
  165. } );
  166. emitter.on( 'foo', evt => {
  167. evt.return = 2;
  168. }, { priority: 'high' } );
  169. expect( emitter.fire( 'foo' ) ).to.equal( 1 );
  170. } );
  171. } );
  172. } );
  173. describe( 'on', () => {
  174. it( 'should stop()', () => {
  175. const spy1 = sinon.spy();
  176. const spy2 = sinon.spy();
  177. const spy3 = sinon.spy( event => {
  178. event.stop();
  179. } );
  180. emitter.on( 'test', spy1 );
  181. emitter.on( 'test', spy2 );
  182. emitter.on( 'test', spy3 );
  183. emitter.on( 'test', sinon.stub().throws() );
  184. emitter.on( 'test', sinon.stub().throws() );
  185. emitter.fire( 'test' );
  186. sinon.assert.called( spy1 );
  187. sinon.assert.called( spy2 );
  188. sinon.assert.called( spy3 );
  189. } );
  190. it( 'should take a callback off()', () => {
  191. const spy1 = sinon.spy();
  192. const spy2 = sinon.spy( event => {
  193. event.off();
  194. } );
  195. const spy3 = sinon.spy();
  196. emitter.on( 'test', spy1 );
  197. emitter.on( 'test', spy2 );
  198. emitter.on( 'test', spy3 );
  199. emitter.fire( 'test' );
  200. emitter.fire( 'test' );
  201. sinon.assert.calledTwice( spy1 );
  202. sinon.assert.calledOnce( spy2 );
  203. sinon.assert.calledTwice( spy3 );
  204. } );
  205. it( 'should take the callback off() even after stop()', () => {
  206. const spy1 = sinon.spy( event => {
  207. event.stop();
  208. event.off();
  209. } );
  210. const spy2 = sinon.spy();
  211. emitter.on( 'test', spy1 );
  212. emitter.on( 'test', spy2 );
  213. emitter.fire( 'test' );
  214. emitter.fire( 'test' );
  215. sinon.assert.calledOnce( spy1 );
  216. sinon.assert.calledOnce( spy2 );
  217. } );
  218. } );
  219. describe( 'once', () => {
  220. it( 'should be called just once', () => {
  221. const spy1 = sinon.spy();
  222. const spy2 = sinon.spy();
  223. const spy3 = sinon.spy();
  224. emitter.on( 'test', spy1 );
  225. emitter.once( 'test', spy2 );
  226. emitter.on( 'test', spy3 );
  227. emitter.fire( 'test' );
  228. emitter.fire( 'test' );
  229. sinon.assert.calledTwice( spy1 );
  230. sinon.assert.calledOnce( spy2 );
  231. sinon.assert.calledTwice( spy3 );
  232. } );
  233. it( 'should have proper scope', () => {
  234. const spy = sinon.spy();
  235. emitter.once( 'test', spy );
  236. emitter.fire( 'test' );
  237. sinon.assert.calledOn( spy, emitter );
  238. } );
  239. it( 'should have proper arguments', () => {
  240. const spy = sinon.spy();
  241. emitter.once( 'test', spy );
  242. emitter.fire( 'test', 1, 2, 3 );
  243. sinon.assert.calledWithExactly( spy, sinon.match.instanceOf( EventInfo ), 1, 2, 3 );
  244. } );
  245. } );
  246. describe( 'off', () => {
  247. it( 'should get callbacks off()', () => {
  248. const spy1 = sinon.spy();
  249. const spy2 = sinon.spy();
  250. const spy3 = sinon.spy();
  251. emitter.on( 'test', spy1 );
  252. emitter.on( 'test', spy2 );
  253. emitter.on( 'test', spy3 );
  254. emitter.fire( 'test' );
  255. emitter.off( 'test', spy2 );
  256. emitter.fire( 'test' );
  257. emitter.fire( 'test' );
  258. sinon.assert.calledThrice( spy1 );
  259. sinon.assert.calledOnce( spy2 );
  260. sinon.assert.calledThrice( spy3 );
  261. } );
  262. it( 'should not fail with unknown events', () => {
  263. emitter.off( 'test', () => {} );
  264. } );
  265. it( 'should remove all entries for the same callback', () => {
  266. const spy1 = sinon.spy().named( 1 );
  267. const spy2 = sinon.spy().named( 2 );
  268. emitter.on( 'test', spy1 );
  269. emitter.on( 'test', spy2 );
  270. emitter.on( 'test', spy1 );
  271. emitter.on( 'test', spy2 );
  272. emitter.fire( 'test' );
  273. emitter.off( 'test', spy1 );
  274. emitter.fire( 'test' );
  275. sinon.assert.callCount( spy1, 2 );
  276. sinon.assert.callCount( spy2, 4 );
  277. } );
  278. it( 'should properly remove callbacks for namespaced events', () => {
  279. const spyFoo = sinon.spy();
  280. const spyAbc = sinon.spy();
  281. const spyBar = sinon.spy();
  282. const spyFoo2 = sinon.spy();
  283. emitter.on( 'foo', spyFoo );
  284. emitter.on( 'foo:bar:abc', spyAbc );
  285. emitter.on( 'foo:bar', spyBar );
  286. emitter.on( 'foo', spyFoo2 );
  287. emitter.off( 'foo', spyFoo );
  288. emitter.fire( 'foo:bar:abc' );
  289. sinon.assert.calledOnce( spyAbc );
  290. sinon.assert.calledOnce( spyBar );
  291. sinon.assert.calledOnce( spyFoo2 );
  292. sinon.assert.notCalled( spyFoo );
  293. emitter.fire( 'foo:bar' );
  294. sinon.assert.notCalled( spyFoo );
  295. sinon.assert.calledOnce( spyAbc );
  296. sinon.assert.calledTwice( spyBar );
  297. sinon.assert.calledTwice( spyFoo2 );
  298. emitter.fire( 'foo' );
  299. sinon.assert.notCalled( spyFoo );
  300. sinon.assert.calledOnce( spyAbc );
  301. sinon.assert.calledTwice( spyBar );
  302. sinon.assert.calledThrice( spyFoo2 );
  303. } );
  304. } );
  305. describe( 'listenTo', () => {
  306. it( 'should properly register callbacks', () => {
  307. const spy = sinon.spy();
  308. listener.listenTo( emitter, 'test', spy );
  309. emitter.fire( 'test' );
  310. sinon.assert.called( spy );
  311. } );
  312. it( 'should correctly listen to namespaced events', () => {
  313. const spyFoo = sinon.spy();
  314. const spyBar = sinon.spy();
  315. listener.listenTo( emitter, 'foo', spyFoo );
  316. listener.listenTo( emitter, 'foo:bar', spyBar );
  317. emitter.fire( 'foo:bar' );
  318. sinon.assert.calledOnce( spyFoo );
  319. sinon.assert.calledOnce( spyBar );
  320. emitter.fire( 'foo' );
  321. sinon.assert.calledTwice( spyFoo );
  322. sinon.assert.calledOnce( spyBar );
  323. } );
  324. } );
  325. describe( 'stopListening', () => {
  326. it( 'should stop listening to given event callback', () => {
  327. const spy1 = sinon.spy();
  328. const spy2 = sinon.spy();
  329. listener.listenTo( emitter, 'event1', spy1 );
  330. listener.listenTo( emitter, 'event2', spy2 );
  331. emitter.fire( 'event1' );
  332. emitter.fire( 'event2' );
  333. listener.stopListening( emitter, 'event1', spy1 );
  334. emitter.fire( 'event1' );
  335. emitter.fire( 'event2' );
  336. sinon.assert.calledOnce( spy1 );
  337. sinon.assert.calledTwice( spy2 );
  338. } );
  339. it( 'should stop listening to given event', () => {
  340. const spy1a = sinon.spy();
  341. const spy1b = sinon.spy();
  342. const spy2 = sinon.spy();
  343. listener.listenTo( emitter, 'event1', spy1a );
  344. listener.listenTo( emitter, 'event1', spy1b );
  345. listener.listenTo( emitter, 'event2', spy2 );
  346. emitter.fire( 'event1' );
  347. emitter.fire( 'event2' );
  348. listener.stopListening( emitter, 'event1' );
  349. emitter.fire( 'event1' );
  350. emitter.fire( 'event2' );
  351. sinon.assert.calledOnce( spy1a );
  352. sinon.assert.calledOnce( spy1b );
  353. sinon.assert.calledTwice( spy2 );
  354. } );
  355. it( 'should stop listening to all events from given emitter', () => {
  356. const spy1 = sinon.spy();
  357. const spy2 = sinon.spy();
  358. listener.listenTo( emitter, 'event1', spy1 );
  359. listener.listenTo( emitter, 'event2', spy2 );
  360. emitter.fire( 'event1' );
  361. emitter.fire( 'event2' );
  362. listener.stopListening( emitter );
  363. emitter.fire( 'event1' );
  364. emitter.fire( 'event2' );
  365. sinon.assert.calledOnce( spy1 );
  366. sinon.assert.calledOnce( spy2 );
  367. } );
  368. it( 'should stop listening to everything', () => {
  369. const spy1 = sinon.spy();
  370. const spy2 = sinon.spy();
  371. const emitter1 = getEmitterInstance();
  372. const emitter2 = getEmitterInstance();
  373. listener.listenTo( emitter1, 'event1', spy1 );
  374. listener.listenTo( emitter2, 'event2', spy2 );
  375. emitter1.fire( 'event1' );
  376. emitter2.fire( 'event2' );
  377. listener.stopListening();
  378. emitter1.fire( 'event1' );
  379. emitter2.fire( 'event2' );
  380. sinon.assert.calledOnce( spy1 );
  381. sinon.assert.calledOnce( spy2 );
  382. } );
  383. it( 'should not stop other emitters when a non-listened emitter is provided', () => {
  384. const spy = sinon.spy();
  385. const emitter1 = getEmitterInstance();
  386. const emitter2 = getEmitterInstance();
  387. listener.listenTo( emitter1, 'test', spy );
  388. listener.stopListening( emitter2 );
  389. emitter1.fire( 'test' );
  390. sinon.assert.called( spy );
  391. } );
  392. it( 'should correctly stop listening to namespaced events', () => {
  393. const spyFoo = sinon.spy();
  394. const spyBar = sinon.spy();
  395. listener.listenTo( emitter, 'foo', spyFoo );
  396. listener.listenTo( emitter, 'foo:bar', spyBar );
  397. listener.stopListening( emitter, 'foo' );
  398. emitter.fire( 'foo:bar' );
  399. sinon.assert.notCalled( spyFoo );
  400. sinon.assert.calledOnce( spyBar );
  401. } );
  402. } );
  403. describe( 'delegate', () => {
  404. it( 'should chain for a single event', () => {
  405. const emitter = getEmitterInstance();
  406. expect( emitter.delegate( 'foo' ) ).to.contain.keys( 'to' );
  407. } );
  408. it( 'should chain for multiple events', () => {
  409. const emitter = getEmitterInstance();
  410. expect( emitter.delegate( 'foo', 'bar' ) ).to.contain.keys( 'to' );
  411. } );
  412. describe( 'to', () => {
  413. it( 'forwards an event to another emitter', done => {
  414. const emitterA = getEmitterInstance();
  415. const emitterB = getEmitterInstance();
  416. const dataA = {};
  417. const dataB = {};
  418. emitterB.delegate( 'foo' ).to( emitterA );
  419. emitterA.on( 'foo', ( ...args ) => {
  420. assertDelegated( args, {
  421. expectedSource: emitterB,
  422. expectedName: 'foo',
  423. expectedPath: [ emitterB, emitterA ],
  424. expectedData: [ dataA, dataB ]
  425. } );
  426. done();
  427. } );
  428. emitterB.fire( 'foo', dataA, dataB );
  429. } );
  430. it( 'forwards multiple events to another emitter', () => {
  431. const emitterA = getEmitterInstance();
  432. const emitterB = getEmitterInstance();
  433. const spyFoo = sinon.spy();
  434. const spyBar = sinon.spy();
  435. const spyBaz = sinon.spy();
  436. const dataA = {};
  437. const dataB = {};
  438. emitterB.delegate( 'foo', 'bar', 'baz' ).to( emitterA );
  439. emitterA.on( 'foo', spyFoo );
  440. emitterA.on( 'bar', spyBar );
  441. emitterA.on( 'baz', spyBaz );
  442. emitterB.fire( 'foo', dataA, dataB );
  443. sinon.assert.calledOnce( spyFoo );
  444. sinon.assert.notCalled( spyBar );
  445. sinon.assert.notCalled( spyBaz );
  446. assertDelegated( spyFoo.args[ 0 ], {
  447. expectedSource: emitterB,
  448. expectedName: 'foo',
  449. expectedPath: [ emitterB, emitterA ],
  450. expectedData: [ dataA, dataB ]
  451. } );
  452. emitterB.fire( 'bar' );
  453. sinon.assert.calledOnce( spyFoo );
  454. sinon.assert.calledOnce( spyBar );
  455. sinon.assert.notCalled( spyBaz );
  456. assertDelegated( spyBar.args[ 0 ], {
  457. expectedSource: emitterB,
  458. expectedName: 'bar',
  459. expectedPath: [ emitterB, emitterA ],
  460. expectedData: []
  461. } );
  462. emitterB.fire( 'baz' );
  463. sinon.assert.calledOnce( spyFoo );
  464. sinon.assert.calledOnce( spyBar );
  465. sinon.assert.calledOnce( spyBaz );
  466. assertDelegated( spyBaz.args[ 0 ], {
  467. expectedSource: emitterB,
  468. expectedName: 'baz',
  469. expectedPath: [ emitterB, emitterA ],
  470. expectedData: []
  471. } );
  472. emitterB.fire( 'not-delegated' );
  473. sinon.assert.calledOnce( spyFoo );
  474. sinon.assert.calledOnce( spyBar );
  475. sinon.assert.calledOnce( spyBaz );
  476. } );
  477. it( 'does not forward events which are not supposed to be delegated', () => {
  478. const emitterA = getEmitterInstance();
  479. const emitterB = getEmitterInstance();
  480. const spyFoo = sinon.spy();
  481. const spyBar = sinon.spy();
  482. const spyBaz = sinon.spy();
  483. emitterB.delegate( 'foo', 'bar', 'baz' ).to( emitterA );
  484. emitterA.on( 'foo', spyFoo );
  485. emitterA.on( 'bar', spyBar );
  486. emitterA.on( 'baz', spyBaz );
  487. emitterB.fire( 'foo' );
  488. emitterB.fire( 'bar' );
  489. emitterB.fire( 'baz' );
  490. emitterB.fire( 'not-delegated' );
  491. sinon.assert.callOrder( spyFoo, spyBar, spyBaz );
  492. sinon.assert.callCount( spyFoo, 1 );
  493. sinon.assert.callCount( spyBar, 1 );
  494. sinon.assert.callCount( spyBaz, 1 );
  495. } );
  496. it( 'supports deep chain event delegation', done => {
  497. const emitterA = getEmitterInstance();
  498. const emitterB = getEmitterInstance();
  499. const emitterC = getEmitterInstance();
  500. const data = {};
  501. emitterC.delegate( 'foo' ).to( emitterB );
  502. emitterB.delegate( 'foo' ).to( emitterA );
  503. emitterA.on( 'foo', ( ...args ) => {
  504. assertDelegated( args, {
  505. expectedSource: emitterC,
  506. expectedName: 'foo',
  507. expectedPath: [ emitterC, emitterB, emitterA ],
  508. expectedData: [ data ]
  509. } );
  510. done();
  511. } );
  512. emitterC.fire( 'foo', data );
  513. } );
  514. it( 'preserves path in event delegation', done => {
  515. const data = {};
  516. const emitterA = getEmitterInstance();
  517. const emitterB = getEmitterInstance();
  518. const emitterC = getEmitterInstance();
  519. const emitterD = getEmitterInstance();
  520. emitterB.delegate( 'foo' ).to( emitterA );
  521. emitterB.delegate( 'foo' ).to( emitterC );
  522. emitterB.delegate( 'foo' ).to( emitterD );
  523. emitterD.on( 'foo', ( ...args ) => {
  524. assertDelegated( args, {
  525. expectedSource: emitterB,
  526. expectedName: 'foo',
  527. expectedPath: [ emitterB, emitterD ],
  528. expectedData: [ data ]
  529. } );
  530. done();
  531. } );
  532. emitterB.fire( 'foo', data );
  533. emitterC.fire( 'foo', data );
  534. } );
  535. it( 'executes callbacks first, then delegates further', () => {
  536. const emitterA = getEmitterInstance();
  537. const emitterB = getEmitterInstance();
  538. const spyA = sinon.spy();
  539. const spyB = sinon.spy();
  540. emitterB.delegate( 'foo' ).to( emitterA );
  541. emitterA.on( 'foo', spyA );
  542. emitterB.on( 'foo', spyB );
  543. emitterB.fire( 'foo' );
  544. sinon.assert.callOrder( spyB, spyA );
  545. } );
  546. it( 'supports delegation under a different name', () => {
  547. const emitterA = getEmitterInstance();
  548. const emitterB = getEmitterInstance();
  549. const emitterC = getEmitterInstance();
  550. const emitterD = getEmitterInstance();
  551. const spyAFoo = sinon.spy();
  552. const spyABar = sinon.spy();
  553. const spyCBaz = sinon.spy();
  554. const spyDFoo = sinon.spy();
  555. emitterB.delegate( 'foo' ).to( emitterA, 'bar' );
  556. emitterB.delegate( 'foo' ).to( emitterC, name => name + '-baz' );
  557. emitterB.delegate( 'foo' ).to( emitterD );
  558. emitterA.on( 'foo', spyAFoo );
  559. emitterA.on( 'bar', spyABar );
  560. emitterC.on( 'foo-baz', spyCBaz );
  561. emitterD.on( 'foo', spyDFoo );
  562. emitterB.fire( 'foo' );
  563. sinon.assert.calledOnce( spyABar );
  564. sinon.assert.calledOnce( spyCBaz );
  565. sinon.assert.calledOnce( spyDFoo );
  566. sinon.assert.notCalled( spyAFoo );
  567. } );
  568. it( 'supports delegation under a different name with multiple events', () => {
  569. const emitterA = getEmitterInstance();
  570. const emitterB = getEmitterInstance();
  571. const spyAFoo = sinon.spy();
  572. const spyABar = sinon.spy();
  573. const spyABaz = sinon.spy();
  574. const spyAQux = sinon.spy();
  575. emitterB.delegate( 'foo', 'bar', 'baz' ).to( emitterA, 'qux' );
  576. emitterA.on( 'foo', spyAFoo );
  577. emitterA.on( 'bar', spyABar );
  578. emitterA.on( 'baz', spyABaz );
  579. emitterA.on( 'qux', spyAQux );
  580. emitterB.fire( 'foo' );
  581. emitterB.fire( 'baz' );
  582. emitterB.fire( 'bar' );
  583. sinon.assert.notCalled( spyAFoo );
  584. sinon.assert.notCalled( spyABar );
  585. sinon.assert.notCalled( spyABaz );
  586. sinon.assert.calledThrice( spyAQux );
  587. } );
  588. it( 'supports delegation with multiple events, each under a different name', () => {
  589. const emitterA = getEmitterInstance();
  590. const emitterB = getEmitterInstance();
  591. const spyAFoo = sinon.spy();
  592. const spyABar = sinon.spy();
  593. const spyABaz = sinon.spy();
  594. const spyAFooQux = sinon.spy();
  595. const spyABarQux = sinon.spy();
  596. const spyABazQux = sinon.spy();
  597. emitterB.delegate( 'foo', 'bar', 'baz' ).to( emitterA, name => name + '-qux' );
  598. emitterA.on( 'foo', spyAFoo );
  599. emitterA.on( 'bar', spyABar );
  600. emitterA.on( 'baz', spyABaz );
  601. emitterA.on( 'foo-qux', spyAFooQux );
  602. emitterA.on( 'bar-qux', spyABarQux );
  603. emitterA.on( 'baz-qux', spyABazQux );
  604. emitterB.fire( 'foo' );
  605. emitterB.fire( 'baz' );
  606. emitterB.fire( 'bar' );
  607. sinon.assert.notCalled( spyAFoo );
  608. sinon.assert.notCalled( spyABar );
  609. sinon.assert.notCalled( spyABaz );
  610. sinon.assert.calledOnce( spyAFooQux );
  611. sinon.assert.calledOnce( spyABarQux );
  612. sinon.assert.calledOnce( spyABazQux );
  613. sinon.assert.callOrder( spyAFooQux, spyABazQux, spyABarQux );
  614. } );
  615. it( 'preserves path in delegation under a different name', done => {
  616. const data = {};
  617. const emitterA = getEmitterInstance();
  618. const emitterB = getEmitterInstance();
  619. const emitterC = getEmitterInstance();
  620. const emitterD = getEmitterInstance();
  621. emitterB.delegate( 'foo' ).to( emitterA, 'bar' );
  622. emitterB.delegate( 'foo' ).to( emitterC, 'baz' );
  623. emitterB.delegate( 'foo' ).to( emitterD );
  624. emitterD.on( 'foo', ( ...args ) => {
  625. assertDelegated( args, {
  626. expectedSource: emitterB,
  627. expectedName: 'foo',
  628. expectedPath: [ emitterB, emitterD ],
  629. expectedData: [ data ]
  630. } );
  631. done();
  632. } );
  633. emitterB.fire( 'foo', data );
  634. } );
  635. it( 'supports delegation of all events', () => {
  636. const emitterA = getEmitterInstance();
  637. const emitterB = getEmitterInstance();
  638. const spyAFoo = sinon.spy();
  639. const spyABar = sinon.spy();
  640. const spyABaz = sinon.spy();
  641. emitterB.delegate( '*' ).to( emitterA );
  642. emitterA.on( 'foo', spyAFoo );
  643. emitterA.on( 'bar', spyABar );
  644. emitterA.on( 'baz', spyABaz );
  645. emitterB.fire( 'foo' );
  646. emitterB.fire( 'baz' );
  647. emitterB.fire( 'bar' );
  648. sinon.assert.callOrder( spyAFoo, spyABaz, spyABar );
  649. } );
  650. it( 'supports delegation of all events under different names', () => {
  651. const emitterA = getEmitterInstance();
  652. const emitterB = getEmitterInstance();
  653. const spyAFoo = sinon.spy();
  654. const spyABar = sinon.spy();
  655. const spyABaz = sinon.spy();
  656. const spyAFooDel = sinon.spy();
  657. const spyABarDel = sinon.spy();
  658. const spyABazDel = sinon.spy();
  659. emitterB.delegate( '*' ).to( emitterA, name => name + '-delegated' );
  660. emitterA.on( 'foo', spyAFoo );
  661. emitterA.on( 'bar', spyABar );
  662. emitterA.on( 'baz', spyABaz );
  663. emitterA.on( 'foo-delegated', spyAFooDel );
  664. emitterA.on( 'bar-delegated', spyABarDel );
  665. emitterA.on( 'baz-delegated', spyABazDel );
  666. emitterB.fire( 'foo' );
  667. emitterB.fire( 'baz' );
  668. emitterB.fire( 'bar' );
  669. sinon.assert.notCalled( spyAFoo );
  670. sinon.assert.notCalled( spyABar );
  671. sinon.assert.notCalled( spyABaz );
  672. sinon.assert.callOrder( spyAFooDel, spyABazDel, spyABarDel );
  673. } );
  674. } );
  675. } );
  676. describe( 'stopDelegating', () => {
  677. it( 'passes if no delegation was set', () => {
  678. expect( () => {
  679. getEmitterInstance().stopDelegating();
  680. } ).to.not.throw();
  681. } );
  682. it( 'stops delegating all events to all emitters', () => {
  683. const emitterA = getEmitterInstance();
  684. const emitterB = getEmitterInstance();
  685. const emitterC = getEmitterInstance();
  686. const spyFoo = sinon.spy();
  687. const spyBar = sinon.spy();
  688. emitterA.delegate( 'foo' ).to( emitterB );
  689. emitterA.delegate( 'bar' ).to( emitterC );
  690. emitterB.on( 'foo', spyFoo );
  691. emitterC.on( 'bar', spyBar );
  692. emitterA.fire( 'foo' );
  693. emitterA.fire( 'bar' );
  694. sinon.assert.callOrder( spyFoo, spyBar );
  695. emitterA.stopDelegating();
  696. emitterA.fire( 'foo' );
  697. emitterA.fire( 'bar' );
  698. sinon.assert.callOrder( spyFoo, spyBar );
  699. } );
  700. it( 'stops delegating a specific event to all emitters', () => {
  701. const emitterA = getEmitterInstance();
  702. const emitterB = getEmitterInstance();
  703. const emitterC = getEmitterInstance();
  704. const spyFooB = sinon.spy();
  705. const spyFooC = sinon.spy();
  706. const spyBarC = sinon.spy();
  707. emitterA.delegate( 'foo' ).to( emitterB );
  708. emitterA.delegate( 'foo' ).to( emitterC );
  709. emitterA.delegate( 'bar' ).to( emitterC );
  710. emitterB.on( 'foo', spyFooB );
  711. emitterC.on( 'foo', spyFooC );
  712. emitterC.on( 'bar', spyBarC );
  713. emitterA.fire( 'foo' );
  714. emitterA.fire( 'bar' );
  715. sinon.assert.callOrder( spyFooB, spyFooC, spyBarC );
  716. emitterA.stopDelegating( 'foo' );
  717. emitterA.fire( 'foo' );
  718. emitterA.fire( 'bar' );
  719. sinon.assert.callOrder( spyFooB, spyFooC, spyBarC, spyBarC );
  720. } );
  721. it( 'stops delegating a specific event to a specific emitter', () => {
  722. const emitterA = getEmitterInstance();
  723. const emitterB = getEmitterInstance();
  724. const emitterC = getEmitterInstance();
  725. const spyFooB = sinon.spy();
  726. const spyFooC = sinon.spy();
  727. emitterA.delegate( 'foo' ).to( emitterB );
  728. emitterA.delegate( 'foo' ).to( emitterC );
  729. emitterB.on( 'foo', spyFooB );
  730. emitterC.on( 'foo', spyFooC );
  731. emitterA.fire( 'foo' );
  732. sinon.assert.callOrder( spyFooB, spyFooC );
  733. emitterA.stopDelegating( 'foo', emitterC );
  734. emitterA.fire( 'foo' );
  735. sinon.assert.callOrder( spyFooB, spyFooC, spyFooB );
  736. } );
  737. it( 'stops delegating a specific event under a different name to a specific emitter', () => {
  738. const emitterA = getEmitterInstance();
  739. const emitterB = getEmitterInstance();
  740. const emitterC = getEmitterInstance();
  741. const spyFooB = sinon.spy();
  742. const spyFooC = sinon.spy();
  743. emitterA.delegate( 'foo' ).to( emitterB );
  744. emitterA.delegate( 'foo' ).to( emitterC, 'bar' );
  745. emitterB.on( 'foo', spyFooB );
  746. emitterC.on( 'bar', spyFooC );
  747. emitterA.fire( 'foo' );
  748. sinon.assert.callOrder( spyFooB, spyFooC );
  749. emitterA.stopDelegating( 'foo', emitterC );
  750. emitterA.fire( 'foo' );
  751. sinon.assert.callOrder( spyFooB, spyFooC, spyFooB );
  752. } );
  753. it( 'stops delegating all ("*")', () => {
  754. const emitterA = getEmitterInstance();
  755. const emitterB = getEmitterInstance();
  756. const emitterC = getEmitterInstance();
  757. const spyAFoo = sinon.spy();
  758. const spyABar = sinon.spy();
  759. const spyCFoo = sinon.spy();
  760. const spyCBar = sinon.spy();
  761. emitterB.delegate( '*' ).to( emitterA );
  762. emitterB.delegate( '*' ).to( emitterC );
  763. emitterA.on( 'foo', spyAFoo );
  764. emitterA.on( 'bar', spyABar );
  765. emitterC.on( 'foo', spyCFoo );
  766. emitterC.on( 'bar', spyCBar );
  767. emitterB.fire( 'foo' );
  768. emitterB.fire( 'bar' );
  769. sinon.assert.calledOnce( spyAFoo );
  770. sinon.assert.calledOnce( spyABar );
  771. sinon.assert.calledOnce( spyCFoo );
  772. sinon.assert.calledOnce( spyCBar );
  773. emitterB.stopDelegating( '*' );
  774. emitterB.fire( 'foo' );
  775. emitterB.fire( 'bar' );
  776. sinon.assert.calledOnce( spyAFoo );
  777. sinon.assert.calledOnce( spyABar );
  778. sinon.assert.calledOnce( spyCFoo );
  779. sinon.assert.calledOnce( spyCBar );
  780. } );
  781. it( 'stops delegating all ("*") to a specific emitter', () => {
  782. const emitterA = getEmitterInstance();
  783. const emitterB = getEmitterInstance();
  784. const emitterC = getEmitterInstance();
  785. const spyAFoo = sinon.spy();
  786. const spyABar = sinon.spy();
  787. const spyCFoo = sinon.spy();
  788. const spyCBar = sinon.spy();
  789. emitterB.delegate( '*' ).to( emitterA );
  790. emitterB.delegate( 'foo' ).to( emitterC );
  791. emitterA.on( 'foo', spyAFoo );
  792. emitterA.on( 'bar', spyABar );
  793. emitterC.on( 'foo', spyCFoo );
  794. emitterC.on( 'bar', spyCBar );
  795. emitterB.fire( 'foo' );
  796. emitterB.fire( 'bar' );
  797. sinon.assert.calledOnce( spyAFoo );
  798. sinon.assert.calledOnce( spyABar );
  799. sinon.assert.calledOnce( spyCFoo );
  800. sinon.assert.notCalled( spyCBar );
  801. emitterB.stopDelegating( '*', emitterA );
  802. emitterB.fire( 'foo' );
  803. emitterB.fire( 'bar' );
  804. sinon.assert.calledOnce( spyAFoo );
  805. sinon.assert.calledOnce( spyABar );
  806. sinon.assert.calledTwice( spyCFoo );
  807. sinon.assert.notCalled( spyCBar );
  808. } );
  809. it( 'passes when stopping delegation of a specific event which has never been delegated', () => {
  810. const emitterA = getEmitterInstance();
  811. const emitterB = getEmitterInstance();
  812. expect( () => {
  813. emitterA.stopDelegating( 'bar' );
  814. emitterA.stopDelegating( 'bar', emitterB );
  815. } ).to.not.throw();
  816. } );
  817. it( 'passes when stopping delegation of a specific event to an emitter which wasn\'t a destination', () => {
  818. const emitterA = getEmitterInstance();
  819. const emitterB = getEmitterInstance();
  820. const emitterC = getEmitterInstance();
  821. emitterA.delegate( 'foo' ).to( emitterB );
  822. expect( () => {
  823. emitterA.stopDelegating( 'foo', emitterC );
  824. } ).to.not.throw();
  825. } );
  826. it( 'passes when stopping delegation of a specific event to a specific emitter which has never been delegated', () => {
  827. const emitterA = getEmitterInstance();
  828. const emitterB = getEmitterInstance();
  829. const emitterC = getEmitterInstance();
  830. emitterA.delegate( 'foo' ).to( emitterB );
  831. expect( () => {
  832. emitterA.stopDelegating( 'bar', emitterC );
  833. } ).to.not.throw();
  834. } );
  835. } );
  836. function assertDelegated( evtArgs, { expectedName, expectedSource, expectedPath, expectedData } ) {
  837. const evtInfo = evtArgs[ 0 ];
  838. expect( evtInfo.name ).to.equal( expectedName );
  839. expect( evtInfo.source ).to.equal( expectedSource );
  840. expect( evtInfo.path ).to.deep.equal( expectedPath );
  841. expect( evtArgs.slice( 1 ) ).to.deep.equal( expectedData );
  842. }
  843. } );
  844. describe( 'emitter id', () => {
  845. let emitter;
  846. beforeEach( () => {
  847. emitter = getEmitterInstance();
  848. } );
  849. it( 'should be undefined before it is set', () => {
  850. expect( _getEmitterId( emitter ) ).to.be.undefined;
  851. } );
  852. it( 'should be settable but only once', () => {
  853. _setEmitterId( emitter, 'abc' );
  854. expect( _getEmitterId( emitter ) ).to.equal( 'abc' );
  855. _setEmitterId( emitter, 'xyz' );
  856. expect( _getEmitterId( emitter ) ).to.equal( 'abc' );
  857. } );
  858. } );
  859. describe( '_getEmitterListenedTo', () => {
  860. let emitter, listener;
  861. beforeEach( () => {
  862. emitter = getEmitterInstance();
  863. listener = getEmitterInstance();
  864. } );
  865. it( 'should return null if listener do not listen to emitter with given id', () => {
  866. expect( _getEmitterListenedTo( listener, 'abc' ) ).to.be.null;
  867. } );
  868. it( 'should return emitter with given id', () => {
  869. listener.listenTo( emitter, 'eventName', () => {} );
  870. const emitterId = _getEmitterId( emitter );
  871. expect( _getEmitterListenedTo( listener, emitterId ) ).to.equal( emitter );
  872. } );
  873. } );
  874. function getEmitterInstance() {
  875. return Object.create( EmitterMixin );
  876. }