emittermixin.js 30 KB

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