8
0

emittermixin.js 30 KB

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