eventtargettester.js 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. // Copyright 2012 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview goog.events.EventTarget tester.
  16. * @author chrishenry@google.com (Chris Henry)
  17. */
  18. goog.provide('goog.events.eventTargetTester');
  19. goog.setTestOnly('goog.events.eventTargetTester');
  20. goog.provide('goog.events.eventTargetTester.KeyType');
  21. goog.setTestOnly('goog.events.eventTargetTester.KeyType');
  22. goog.provide('goog.events.eventTargetTester.UnlistenReturnType');
  23. goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');
  24. goog.require('goog.array');
  25. goog.require('goog.events');
  26. goog.require('goog.events.Event');
  27. goog.require('goog.events.EventTarget');
  28. goog.require('goog.testing.asserts');
  29. goog.require('goog.testing.recordFunction');
  30. /**
  31. * Setup step for the test functions. This needs to be called from the
  32. * test setUp.
  33. * @param {function():!goog.events.Listenable} listenableFactoryFn Function
  34. * that will return a new Listenable instance each time it is called.
  35. * @param {Function} listenFn Function that, given the same signature
  36. * as goog.events.listen, will add listener to the given event
  37. * target.
  38. * @param {Function} unlistenFn Function that, given the same
  39. * signature as goog.events.unlisten, will remove listener from
  40. * the given event target.
  41. * @param {Function} unlistenByKeyFn Function that, given 2
  42. * parameters: src and key, will remove the corresponding
  43. * listener.
  44. * @param {Function} listenOnceFn Function that, given the same
  45. * signature as goog.events.listenOnce, will add a one-time
  46. * listener to the given event target.
  47. * @param {Function} dispatchEventFn Function that, given the same
  48. * signature as goog.events.dispatchEvent, will dispatch the event
  49. * on the given event target.
  50. * @param {Function} removeAllFn Function that, given the same
  51. * signature as goog.events.removeAll, will remove all listeners
  52. * according to the contract of goog.events.removeAll.
  53. * @param {Function} getListenersFn Function that, given the same
  54. * signature as goog.events.getListeners, will retrieve listeners.
  55. * @param {Function} getListenerFn Function that, given the same
  56. * signature as goog.events.getListener, will retrieve the
  57. * listener object.
  58. * @param {Function} hasListenerFn Function that, given the same
  59. * signature as goog.events.hasListener, will determine whether
  60. * listeners exist.
  61. * @param {goog.events.eventTargetTester.KeyType} listenKeyType The
  62. * key type returned by listen call.
  63. * @param {goog.events.eventTargetTester.UnlistenReturnType}
  64. * unlistenFnReturnType
  65. * Whether we should check return value from
  66. * unlisten call. If unlisten does not return a value, this should
  67. * be set to false.
  68. * @param {boolean} objectListenerSupported Whether listener of type
  69. * Object is supported.
  70. */
  71. goog.events.eventTargetTester.setUp = function(
  72. listenableFactoryFn, listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,
  73. dispatchEventFn, removeAllFn, getListenersFn, getListenerFn, hasListenerFn,
  74. listenKeyType, unlistenFnReturnType, objectListenerSupported) {
  75. listenableFactory = listenableFactoryFn;
  76. listen = listenFn;
  77. unlisten = unlistenFn;
  78. unlistenByKey = unlistenByKeyFn;
  79. listenOnce = listenOnceFn;
  80. dispatchEvent = dispatchEventFn;
  81. removeAll = removeAllFn;
  82. getListeners = getListenersFn;
  83. getListener = getListenerFn;
  84. hasListener = hasListenerFn;
  85. keyType = listenKeyType;
  86. unlistenReturnType = unlistenFnReturnType;
  87. objectTypeListenerSupported = objectListenerSupported;
  88. listeners = [];
  89. for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
  90. listeners[i] = createListener();
  91. }
  92. eventTargets = [];
  93. for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
  94. eventTargets[i] = listenableFactory();
  95. }
  96. };
  97. /**
  98. * Teardown step for the test functions. This needs to be called from
  99. * test teardown.
  100. */
  101. goog.events.eventTargetTester.tearDown = function() {
  102. for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
  103. goog.dispose(eventTargets[i]);
  104. }
  105. };
  106. /**
  107. * The type of key returned by key-returning functions (listen).
  108. * @enum {number}
  109. */
  110. goog.events.eventTargetTester.KeyType = {
  111. /**
  112. * Returns number for key.
  113. */
  114. NUMBER: 0,
  115. /**
  116. * Returns undefined (no return value).
  117. */
  118. UNDEFINED: 1
  119. };
  120. /**
  121. * The type of unlisten function's return value.
  122. * @enum {number}
  123. */
  124. goog.events.eventTargetTester.UnlistenReturnType = {
  125. /**
  126. * Returns boolean indicating whether unlisten is successful.
  127. */
  128. BOOLEAN: 0,
  129. /**
  130. * Returns undefind (no return value).
  131. */
  132. UNDEFINED: 1
  133. };
  134. /**
  135. * Expando property used on "listener" function to determine if a
  136. * listener has already been checked. This is what allows us to
  137. * implement assertNoOtherListenerIsCalled.
  138. * @type {string}
  139. */
  140. goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';
  141. /**
  142. * Expando property used on "listener" function to record the number
  143. * of times it has been called the last time assertListenerIsCalled is
  144. * done. This allows us to verify that it has not been called more
  145. * times in assertNoOtherListenerIsCalled.
  146. */
  147. goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';
  148. /**
  149. * The maximum number of initialized event targets (in eventTargets
  150. * array) and listeners (in listeners array).
  151. * @type {number}
  152. * @private
  153. */
  154. goog.events.eventTargetTester.MAX_ = 10;
  155. /**
  156. * Contains test event types.
  157. * @enum {string}
  158. */
  159. var EventType = {
  160. A: goog.events.getUniqueId('a'),
  161. B: goog.events.getUniqueId('b'),
  162. C: goog.events.getUniqueId('c')
  163. };
  164. var listenableFactory, listen, unlisten, unlistenByKey, listenOnce;
  165. var dispatchEvent, removeAll, getListeners, getListener, hasListener;
  166. var keyType, unlistenReturnType, objectTypeListenerSupported;
  167. var eventTargets, listeners;
  168. /**
  169. * Custom event object for testing.
  170. * @constructor
  171. * @extends {goog.events.Event}
  172. * @final
  173. */
  174. var TestEvent = function() {
  175. TestEvent.base(this, 'constructor', EventType.A);
  176. };
  177. goog.inherits(TestEvent, goog.events.Event);
  178. /**
  179. * Creates a listener that executes the given function (optional).
  180. * @param {!Function=} opt_listenerFn The optional function to execute.
  181. * @return {!Function} The listener function.
  182. */
  183. function createListener(opt_listenerFn) {
  184. return goog.testing.recordFunction(opt_listenerFn);
  185. }
  186. /**
  187. * Asserts that the given listener is called numCount number of times.
  188. * @param {!Function} listener The listener to check.
  189. * @param {number} numCount The number of times. See also the times()
  190. * function below.
  191. */
  192. function assertListenerIsCalled(listener, numCount) {
  193. assertEquals(
  194. 'Listeners is not called the correct number of times.', numCount,
  195. listener.getCallCount());
  196. listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;
  197. listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;
  198. }
  199. /**
  200. * Asserts that no other listeners, other than those verified via
  201. * assertListenerIsCalled, have been called since the last
  202. * resetListeners().
  203. */
  204. function assertNoOtherListenerIsCalled() {
  205. goog.array.forEach(listeners, function(l, index) {
  206. if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {
  207. assertEquals(
  208. 'Listeners ' + index + ' is unexpectedly called.', 0,
  209. l.getCallCount());
  210. } else {
  211. assertEquals(
  212. 'Listeners ' + index + ' is unexpectedly called.',
  213. l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());
  214. }
  215. });
  216. }
  217. /**
  218. * Resets all listeners call count to 0.
  219. */
  220. function resetListeners() {
  221. goog.array.forEach(listeners, function(l) {
  222. l.reset();
  223. l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;
  224. });
  225. }
  226. /**
  227. * The number of times a listener should have been executed. This
  228. * exists to make assertListenerIsCalled more readable. This is used
  229. * like so: assertListenerIsCalled(listener, times(2));
  230. * @param {number} n The number of times a listener should have been
  231. * executed.
  232. * @return {number} The number n.
  233. */
  234. function times(n) {
  235. return n;
  236. }
  237. function testNoListener() {
  238. dispatchEvent(eventTargets[0], EventType.A);
  239. assertNoOtherListenerIsCalled();
  240. }
  241. function testOneListener() {
  242. listen(eventTargets[0], EventType.A, listeners[0]);
  243. dispatchEvent(eventTargets[0], EventType.A);
  244. assertListenerIsCalled(listeners[0], times(1));
  245. assertNoOtherListenerIsCalled();
  246. resetListeners();
  247. dispatchEvent(eventTargets[0], EventType.B);
  248. dispatchEvent(eventTargets[0], EventType.C);
  249. assertNoOtherListenerIsCalled();
  250. }
  251. function testTwoListenersOfSameType() {
  252. var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
  253. var key2 = listen(eventTargets[0], EventType.A, listeners[1]);
  254. if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
  255. assertNotEquals(key1, key2);
  256. } else {
  257. assertUndefined(key1);
  258. assertUndefined(key2);
  259. }
  260. dispatchEvent(eventTargets[0], EventType.A);
  261. assertListenerIsCalled(listeners[0], times(1));
  262. assertListenerIsCalled(listeners[1], times(1));
  263. assertNoOtherListenerIsCalled();
  264. }
  265. function testInstallingSameListeners() {
  266. var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
  267. var key2 = listen(eventTargets[0], EventType.A, listeners[0]);
  268. var key3 = listen(eventTargets[0], EventType.B, listeners[0]);
  269. if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
  270. assertEquals(key1, key2);
  271. assertNotEquals(key1, key3);
  272. } else {
  273. assertUndefined(key1);
  274. assertUndefined(key2);
  275. assertUndefined(key3);
  276. }
  277. dispatchEvent(eventTargets[0], EventType.A);
  278. assertListenerIsCalled(listeners[0], times(1));
  279. dispatchEvent(eventTargets[0], EventType.B);
  280. assertListenerIsCalled(listeners[0], times(2));
  281. assertNoOtherListenerIsCalled();
  282. }
  283. function testScope() {
  284. listeners[0] = createListener(function(e) {
  285. assertEquals('Wrong scope with undefined scope', eventTargets[0], this);
  286. });
  287. listeners[1] = createListener(function(e) {
  288. assertEquals('Wrong scope with null scope', eventTargets[0], this);
  289. });
  290. var scope = {};
  291. listeners[2] = createListener(function(e) {
  292. assertEquals('Wrong scope with specific scope object', scope, this);
  293. });
  294. listen(eventTargets[0], EventType.A, listeners[0]);
  295. listen(eventTargets[0], EventType.A, listeners[1], false, null);
  296. listen(eventTargets[0], EventType.A, listeners[2], false, scope);
  297. dispatchEvent(eventTargets[0], EventType.A);
  298. assertListenerIsCalled(listeners[0], times(1));
  299. assertListenerIsCalled(listeners[1], times(1));
  300. assertListenerIsCalled(listeners[2], times(1));
  301. }
  302. function testDispatchEventDoesNotThrowWithDisposedEventTarget() {
  303. goog.dispose(eventTargets[0]);
  304. assertTrue(dispatchEvent(eventTargets[0], EventType.A));
  305. }
  306. function testDispatchEventWithObjectLiteral() {
  307. listen(eventTargets[0], EventType.A, listeners[0]);
  308. assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));
  309. assertListenerIsCalled(listeners[0], times(1));
  310. assertNoOtherListenerIsCalled();
  311. }
  312. function testDispatchEventWithCustomEventObject() {
  313. listen(eventTargets[0], EventType.A, listeners[0]);
  314. var e = new TestEvent();
  315. assertTrue(dispatchEvent(eventTargets[0], e));
  316. assertListenerIsCalled(listeners[0], times(1));
  317. assertNoOtherListenerIsCalled();
  318. var actualEvent = listeners[0].getLastCall().getArgument(0);
  319. assertEquals(e, actualEvent);
  320. assertEquals(eventTargets[0], actualEvent.target);
  321. }
  322. function testDisposingEventTargetRemovesListeners() {
  323. if (!(listenableFactory() instanceof goog.events.EventTarget)) {
  324. return;
  325. }
  326. listen(eventTargets[0], EventType.A, listeners[0]);
  327. goog.dispose(eventTargets[0]);
  328. dispatchEvent(eventTargets[0], EventType.A);
  329. assertNoOtherListenerIsCalled();
  330. }
  331. /**
  332. * Unlisten/unlistenByKey should still work after disposal. There are
  333. * many circumstances when this is actually necessary. For example, a
  334. * user may have listened to an event target and stored the key
  335. * (e.g. in a goog.events.EventHandler) and only unlisten after the
  336. * target has been disposed.
  337. */
  338. function testUnlistenWorksAfterDisposal() {
  339. var key = listen(eventTargets[0], EventType.A, listeners[0]);
  340. goog.dispose(eventTargets[0]);
  341. unlisten(eventTargets[0], EventType.A, listeners[1]);
  342. if (unlistenByKey) {
  343. unlistenByKey(eventTargets[0], key);
  344. }
  345. }
  346. function testRemovingListener() {
  347. var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);
  348. listen(eventTargets[0], EventType.A, listeners[0]);
  349. var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);
  350. var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);
  351. var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);
  352. dispatchEvent(eventTargets[0], EventType.A);
  353. assertListenerIsCalled(listeners[0], times(1));
  354. var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);
  355. var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);
  356. dispatchEvent(eventTargets[0], EventType.A);
  357. assertListenerIsCalled(listeners[0], times(1));
  358. assertNoOtherListenerIsCalled();
  359. if (unlistenReturnType ==
  360. goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {
  361. assertFalse(ret1);
  362. assertFalse(ret2);
  363. assertFalse(ret3);
  364. assertFalse(ret4);
  365. assertTrue(ret5);
  366. assertFalse(ret6);
  367. } else {
  368. assertUndefined(ret1);
  369. assertUndefined(ret2);
  370. assertUndefined(ret3);
  371. assertUndefined(ret4);
  372. assertUndefined(ret5);
  373. assertUndefined(ret6);
  374. }
  375. }
  376. function testCapture() {
  377. eventTargets[0].setParentEventTarget(eventTargets[1]);
  378. eventTargets[1].setParentEventTarget(eventTargets[2]);
  379. eventTargets[9].setParentEventTarget(eventTargets[0]);
  380. var ordering = 0;
  381. listeners[0] = createListener(function(e) {
  382. assertEquals(eventTargets[2], e.currentTarget);
  383. assertEquals(eventTargets[0], e.target);
  384. assertEquals('First capture listener is not called first', 0, ordering);
  385. ordering++;
  386. });
  387. listeners[1] = createListener(function(e) {
  388. assertEquals(eventTargets[1], e.currentTarget);
  389. assertEquals(eventTargets[0], e.target);
  390. assertEquals('2nd capture listener is not called 2nd', 1, ordering);
  391. ordering++;
  392. });
  393. listeners[2] = createListener(function(e) {
  394. assertEquals(eventTargets[0], e.currentTarget);
  395. assertEquals(eventTargets[0], e.target);
  396. assertEquals('3rd capture listener is not called 3rd', 2, ordering);
  397. ordering++;
  398. });
  399. listen(eventTargets[2], EventType.A, listeners[0], true);
  400. listen(eventTargets[1], EventType.A, listeners[1], true);
  401. listen(eventTargets[0], EventType.A, listeners[2], true);
  402. // These should not be called.
  403. listen(eventTargets[3], EventType.A, listeners[3], true);
  404. listen(eventTargets[0], EventType.B, listeners[4], true);
  405. listen(eventTargets[0], EventType.C, listeners[5], true);
  406. listen(eventTargets[1], EventType.B, listeners[6], true);
  407. listen(eventTargets[1], EventType.C, listeners[7], true);
  408. listen(eventTargets[2], EventType.B, listeners[8], true);
  409. listen(eventTargets[2], EventType.C, listeners[9], true);
  410. dispatchEvent(eventTargets[0], EventType.A);
  411. assertListenerIsCalled(listeners[0], times(1));
  412. assertListenerIsCalled(listeners[1], times(1));
  413. assertListenerIsCalled(listeners[2], times(1));
  414. assertNoOtherListenerIsCalled();
  415. }
  416. function testBubble() {
  417. eventTargets[0].setParentEventTarget(eventTargets[1]);
  418. eventTargets[1].setParentEventTarget(eventTargets[2]);
  419. eventTargets[9].setParentEventTarget(eventTargets[0]);
  420. var ordering = 0;
  421. listeners[0] = createListener(function(e) {
  422. assertEquals(eventTargets[0], e.currentTarget);
  423. assertEquals(eventTargets[0], e.target);
  424. assertEquals('First bubble listener is not called first', 0, ordering);
  425. ordering++;
  426. });
  427. listeners[1] = createListener(function(e) {
  428. assertEquals(eventTargets[1], e.currentTarget);
  429. assertEquals(eventTargets[0], e.target);
  430. assertEquals('2nd bubble listener is not called 2nd', 1, ordering);
  431. ordering++;
  432. });
  433. listeners[2] = createListener(function(e) {
  434. assertEquals(eventTargets[2], e.currentTarget);
  435. assertEquals(eventTargets[0], e.target);
  436. assertEquals('3rd bubble listener is not called 3rd', 2, ordering);
  437. ordering++;
  438. });
  439. listen(eventTargets[0], EventType.A, listeners[0]);
  440. listen(eventTargets[1], EventType.A, listeners[1]);
  441. listen(eventTargets[2], EventType.A, listeners[2]);
  442. // These should not be called.
  443. listen(eventTargets[3], EventType.A, listeners[3]);
  444. listen(eventTargets[0], EventType.B, listeners[4]);
  445. listen(eventTargets[0], EventType.C, listeners[5]);
  446. listen(eventTargets[1], EventType.B, listeners[6]);
  447. listen(eventTargets[1], EventType.C, listeners[7]);
  448. listen(eventTargets[2], EventType.B, listeners[8]);
  449. listen(eventTargets[2], EventType.C, listeners[9]);
  450. dispatchEvent(eventTargets[0], EventType.A);
  451. assertListenerIsCalled(listeners[0], times(1));
  452. assertListenerIsCalled(listeners[1], times(1));
  453. assertListenerIsCalled(listeners[2], times(1));
  454. assertNoOtherListenerIsCalled();
  455. }
  456. function testCaptureAndBubble() {
  457. eventTargets[0].setParentEventTarget(eventTargets[1]);
  458. eventTargets[1].setParentEventTarget(eventTargets[2]);
  459. listen(eventTargets[0], EventType.A, listeners[0], true);
  460. listen(eventTargets[1], EventType.A, listeners[1], true);
  461. listen(eventTargets[2], EventType.A, listeners[2], true);
  462. listen(eventTargets[0], EventType.A, listeners[3]);
  463. listen(eventTargets[1], EventType.A, listeners[4]);
  464. listen(eventTargets[2], EventType.A, listeners[5]);
  465. dispatchEvent(eventTargets[0], EventType.A);
  466. assertListenerIsCalled(listeners[0], times(1));
  467. assertListenerIsCalled(listeners[1], times(1));
  468. assertListenerIsCalled(listeners[2], times(1));
  469. assertListenerIsCalled(listeners[3], times(1));
  470. assertListenerIsCalled(listeners[4], times(1));
  471. assertListenerIsCalled(listeners[5], times(1));
  472. assertNoOtherListenerIsCalled();
  473. }
  474. function testPreventDefaultByReturningFalse() {
  475. listeners[0] = createListener(function(e) { return false; });
  476. listeners[1] = createListener(function(e) { return true; });
  477. listen(eventTargets[0], EventType.A, listeners[0]);
  478. listen(eventTargets[0], EventType.A, listeners[1]);
  479. var result = dispatchEvent(eventTargets[0], EventType.A);
  480. assertFalse(result);
  481. }
  482. function testPreventDefault() {
  483. listeners[0] = createListener(function(e) { e.preventDefault(); });
  484. listeners[1] = createListener(function(e) { return true; });
  485. listen(eventTargets[0], EventType.A, listeners[0]);
  486. listen(eventTargets[0], EventType.A, listeners[1]);
  487. var result = dispatchEvent(eventTargets[0], EventType.A);
  488. assertFalse(result);
  489. }
  490. function testPreventDefaultAtCapture() {
  491. listeners[0] = createListener(function(e) { e.preventDefault(); });
  492. listeners[1] = createListener(function(e) { return true; });
  493. listen(eventTargets[0], EventType.A, listeners[0], true);
  494. listen(eventTargets[0], EventType.A, listeners[1], true);
  495. var result = dispatchEvent(eventTargets[0], EventType.A);
  496. assertFalse(result);
  497. }
  498. function testStopPropagation() {
  499. eventTargets[0].setParentEventTarget(eventTargets[1]);
  500. eventTargets[1].setParentEventTarget(eventTargets[2]);
  501. listeners[0] = createListener(function(e) { e.stopPropagation(); });
  502. listen(eventTargets[0], EventType.A, listeners[0]);
  503. listen(eventTargets[0], EventType.A, listeners[1]);
  504. listen(eventTargets[1], EventType.A, listeners[2]);
  505. listen(eventTargets[2], EventType.A, listeners[3]);
  506. dispatchEvent(eventTargets[0], EventType.A);
  507. assertListenerIsCalled(listeners[0], times(1));
  508. assertListenerIsCalled(listeners[1], times(1));
  509. assertNoOtherListenerIsCalled();
  510. }
  511. function testStopPropagation2() {
  512. eventTargets[0].setParentEventTarget(eventTargets[1]);
  513. eventTargets[1].setParentEventTarget(eventTargets[2]);
  514. listeners[1] = createListener(function(e) { e.stopPropagation(); });
  515. listen(eventTargets[0], EventType.A, listeners[0]);
  516. listen(eventTargets[0], EventType.A, listeners[1]);
  517. listen(eventTargets[1], EventType.A, listeners[2]);
  518. listen(eventTargets[2], EventType.A, listeners[3]);
  519. dispatchEvent(eventTargets[0], EventType.A);
  520. assertListenerIsCalled(listeners[0], times(1));
  521. assertListenerIsCalled(listeners[1], times(1));
  522. assertNoOtherListenerIsCalled();
  523. }
  524. function testStopPropagation3() {
  525. eventTargets[0].setParentEventTarget(eventTargets[1]);
  526. eventTargets[1].setParentEventTarget(eventTargets[2]);
  527. listeners[2] = createListener(function(e) { e.stopPropagation(); });
  528. listen(eventTargets[0], EventType.A, listeners[0]);
  529. listen(eventTargets[0], EventType.A, listeners[1]);
  530. listen(eventTargets[1], EventType.A, listeners[2]);
  531. listen(eventTargets[2], EventType.A, listeners[3]);
  532. dispatchEvent(eventTargets[0], EventType.A);
  533. assertListenerIsCalled(listeners[0], times(1));
  534. assertListenerIsCalled(listeners[1], times(1));
  535. assertListenerIsCalled(listeners[2], times(1));
  536. assertNoOtherListenerIsCalled();
  537. }
  538. function testStopPropagationAtCapture() {
  539. eventTargets[0].setParentEventTarget(eventTargets[1]);
  540. eventTargets[1].setParentEventTarget(eventTargets[2]);
  541. listeners[0] = createListener(function(e) { e.stopPropagation(); });
  542. listen(eventTargets[2], EventType.A, listeners[0], true);
  543. listen(eventTargets[1], EventType.A, listeners[1], true);
  544. listen(eventTargets[0], EventType.A, listeners[2], true);
  545. listen(eventTargets[0], EventType.A, listeners[3]);
  546. listen(eventTargets[1], EventType.A, listeners[4]);
  547. listen(eventTargets[2], EventType.A, listeners[5]);
  548. dispatchEvent(eventTargets[0], EventType.A);
  549. assertListenerIsCalled(listeners[0], times(1));
  550. assertNoOtherListenerIsCalled();
  551. }
  552. function testHandleEvent() {
  553. if (!objectTypeListenerSupported) {
  554. return;
  555. }
  556. var obj = {};
  557. obj.handleEvent = goog.testing.recordFunction();
  558. listen(eventTargets[0], EventType.A, obj);
  559. dispatchEvent(eventTargets[0], EventType.A);
  560. assertEquals(1, obj.handleEvent.getCallCount());
  561. }
  562. function testListenOnce() {
  563. if (!listenOnce) {
  564. return;
  565. }
  566. listenOnce(eventTargets[0], EventType.A, listeners[0], true);
  567. listenOnce(eventTargets[0], EventType.A, listeners[1]);
  568. listenOnce(eventTargets[0], EventType.B, listeners[2]);
  569. dispatchEvent(eventTargets[0], EventType.A);
  570. assertListenerIsCalled(listeners[0], times(1));
  571. assertListenerIsCalled(listeners[1], times(1));
  572. assertListenerIsCalled(listeners[2], times(0));
  573. assertNoOtherListenerIsCalled();
  574. resetListeners();
  575. dispatchEvent(eventTargets[0], EventType.A);
  576. assertListenerIsCalled(listeners[0], times(0));
  577. assertListenerIsCalled(listeners[1], times(0));
  578. assertListenerIsCalled(listeners[2], times(0));
  579. dispatchEvent(eventTargets[0], EventType.B);
  580. assertListenerIsCalled(listeners[2], times(1));
  581. assertNoOtherListenerIsCalled();
  582. }
  583. function testUnlistenInListen() {
  584. listeners[1] = createListener(function(e) {
  585. unlisten(eventTargets[0], EventType.A, listeners[1]);
  586. unlisten(eventTargets[0], EventType.A, listeners[2]);
  587. });
  588. listen(eventTargets[0], EventType.A, listeners[0]);
  589. listen(eventTargets[0], EventType.A, listeners[1]);
  590. listen(eventTargets[0], EventType.A, listeners[2]);
  591. listen(eventTargets[0], EventType.A, listeners[3]);
  592. dispatchEvent(eventTargets[0], EventType.A);
  593. assertListenerIsCalled(listeners[0], times(1));
  594. assertListenerIsCalled(listeners[1], times(1));
  595. assertListenerIsCalled(listeners[2], times(0));
  596. assertListenerIsCalled(listeners[3], times(1));
  597. assertNoOtherListenerIsCalled();
  598. resetListeners();
  599. dispatchEvent(eventTargets[0], EventType.A);
  600. assertListenerIsCalled(listeners[0], times(1));
  601. assertListenerIsCalled(listeners[1], times(0));
  602. assertListenerIsCalled(listeners[2], times(0));
  603. assertListenerIsCalled(listeners[3], times(1));
  604. assertNoOtherListenerIsCalled();
  605. }
  606. function testUnlistenByKeyInListen() {
  607. if (!unlistenByKey) {
  608. return;
  609. }
  610. var key1, key2;
  611. listeners[1] = createListener(function(e) {
  612. unlistenByKey(eventTargets[0], key1);
  613. unlistenByKey(eventTargets[0], key2);
  614. });
  615. listen(eventTargets[0], EventType.A, listeners[0]);
  616. key1 = listen(eventTargets[0], EventType.A, listeners[1]);
  617. key2 = listen(eventTargets[0], EventType.A, listeners[2]);
  618. listen(eventTargets[0], EventType.A, listeners[3]);
  619. dispatchEvent(eventTargets[0], EventType.A);
  620. assertListenerIsCalled(listeners[0], times(1));
  621. assertListenerIsCalled(listeners[1], times(1));
  622. assertListenerIsCalled(listeners[2], times(0));
  623. assertListenerIsCalled(listeners[3], times(1));
  624. assertNoOtherListenerIsCalled();
  625. resetListeners();
  626. dispatchEvent(eventTargets[0], EventType.A);
  627. assertListenerIsCalled(listeners[0], times(1));
  628. assertListenerIsCalled(listeners[1], times(0));
  629. assertListenerIsCalled(listeners[2], times(0));
  630. assertListenerIsCalled(listeners[3], times(1));
  631. assertNoOtherListenerIsCalled();
  632. }
  633. function testSetParentEventTarget() {
  634. assertNull(eventTargets[0].getParentEventTarget());
  635. eventTargets[0].setParentEventTarget(eventTargets[1]);
  636. assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());
  637. assertNull(eventTargets[1].getParentEventTarget());
  638. eventTargets[0].setParentEventTarget(null);
  639. assertNull(eventTargets[0].getParentEventTarget());
  640. }
  641. function testListenOnceAfterListenDoesNotChangeExistingListener() {
  642. if (!listenOnce) {
  643. return;
  644. }
  645. listen(eventTargets[0], EventType.A, listeners[0]);
  646. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  647. dispatchEvent(eventTargets[0], EventType.A);
  648. dispatchEvent(eventTargets[0], EventType.A);
  649. dispatchEvent(eventTargets[0], EventType.A);
  650. assertListenerIsCalled(listeners[0], times(3));
  651. assertNoOtherListenerIsCalled();
  652. }
  653. function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
  654. if (!listenOnce) {
  655. return;
  656. }
  657. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  658. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  659. dispatchEvent(eventTargets[0], EventType.A);
  660. dispatchEvent(eventTargets[0], EventType.A);
  661. dispatchEvent(eventTargets[0], EventType.A);
  662. assertListenerIsCalled(listeners[0], times(1));
  663. assertNoOtherListenerIsCalled();
  664. }
  665. function testListenAfterListenOnceRemoveOnceness() {
  666. if (!listenOnce) {
  667. return;
  668. }
  669. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  670. listen(eventTargets[0], EventType.A, listeners[0]);
  671. dispatchEvent(eventTargets[0], EventType.A);
  672. dispatchEvent(eventTargets[0], EventType.A);
  673. dispatchEvent(eventTargets[0], EventType.A);
  674. assertListenerIsCalled(listeners[0], times(3));
  675. assertNoOtherListenerIsCalled();
  676. }
  677. function testUnlistenAfterListenOnce() {
  678. if (!listenOnce) {
  679. return;
  680. }
  681. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  682. unlisten(eventTargets[0], EventType.A, listeners[0]);
  683. dispatchEvent(eventTargets[0], EventType.A);
  684. listen(eventTargets[0], EventType.A, listeners[0]);
  685. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  686. unlisten(eventTargets[0], EventType.A, listeners[0]);
  687. dispatchEvent(eventTargets[0], EventType.A);
  688. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  689. listen(eventTargets[0], EventType.A, listeners[0]);
  690. unlisten(eventTargets[0], EventType.A, listeners[0]);
  691. dispatchEvent(eventTargets[0], EventType.A);
  692. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  693. listenOnce(eventTargets[0], EventType.A, listeners[0]);
  694. unlisten(eventTargets[0], EventType.A, listeners[0]);
  695. dispatchEvent(eventTargets[0], EventType.A);
  696. assertNoOtherListenerIsCalled();
  697. }
  698. function testRemoveAllWithType() {
  699. if (!removeAll) {
  700. return;
  701. }
  702. listen(eventTargets[0], EventType.A, listeners[0], true);
  703. listen(eventTargets[0], EventType.A, listeners[1]);
  704. listen(eventTargets[0], EventType.C, listeners[2], true);
  705. listen(eventTargets[0], EventType.C, listeners[3]);
  706. listen(eventTargets[0], EventType.B, listeners[4], true);
  707. listen(eventTargets[0], EventType.B, listeners[5], true);
  708. listen(eventTargets[0], EventType.B, listeners[6]);
  709. listen(eventTargets[0], EventType.B, listeners[7]);
  710. assertEquals(4, removeAll(eventTargets[0], EventType.B));
  711. dispatchEvent(eventTargets[0], EventType.A);
  712. dispatchEvent(eventTargets[0], EventType.B);
  713. dispatchEvent(eventTargets[0], EventType.C);
  714. assertListenerIsCalled(listeners[0], times(1));
  715. assertListenerIsCalled(listeners[1], times(1));
  716. assertListenerIsCalled(listeners[2], times(1));
  717. assertListenerIsCalled(listeners[3], times(1));
  718. assertNoOtherListenerIsCalled();
  719. }
  720. function testRemoveAll() {
  721. if (!removeAll) {
  722. return;
  723. }
  724. listen(eventTargets[0], EventType.A, listeners[0], true);
  725. listen(eventTargets[0], EventType.A, listeners[1]);
  726. listen(eventTargets[0], EventType.C, listeners[2], true);
  727. listen(eventTargets[0], EventType.C, listeners[3]);
  728. listen(eventTargets[0], EventType.B, listeners[4], true);
  729. listen(eventTargets[0], EventType.B, listeners[5], true);
  730. listen(eventTargets[0], EventType.B, listeners[6]);
  731. listen(eventTargets[0], EventType.B, listeners[7]);
  732. assertEquals(8, removeAll(eventTargets[0]));
  733. dispatchEvent(eventTargets[0], EventType.A);
  734. dispatchEvent(eventTargets[0], EventType.B);
  735. dispatchEvent(eventTargets[0], EventType.C);
  736. assertNoOtherListenerIsCalled();
  737. }
  738. function testRemoveAllCallsMarkAsRemoved() {
  739. if (!removeAll) {
  740. return;
  741. }
  742. var key0 = listen(eventTargets[0], EventType.A, listeners[0]);
  743. var key1 = listen(eventTargets[1], EventType.A, listeners[1]);
  744. assertNotNullNorUndefined(key0.listener);
  745. assertFalse(key0.removed);
  746. assertNotNullNorUndefined(key1.listener);
  747. assertFalse(key1.removed);
  748. assertEquals(1, removeAll(eventTargets[0]));
  749. assertNull(key0.listener);
  750. assertTrue(key0.removed);
  751. assertNotNullNorUndefined(key1.listener);
  752. assertFalse(key1.removed);
  753. assertEquals(1, removeAll(eventTargets[1]));
  754. assertNull(key1.listener);
  755. assertTrue(key1.removed);
  756. }
  757. function testGetListeners() {
  758. if (!getListeners) {
  759. return;
  760. }
  761. listen(eventTargets[0], EventType.A, listeners[0], true);
  762. listen(eventTargets[0], EventType.A, listeners[1], true);
  763. listen(eventTargets[0], EventType.A, listeners[2]);
  764. listen(eventTargets[0], EventType.A, listeners[3]);
  765. var l = getListeners(eventTargets[0], EventType.A, true);
  766. assertEquals(2, l.length);
  767. assertEquals(listeners[0], l[0].listener);
  768. assertEquals(listeners[1], l[1].listener);
  769. l = getListeners(eventTargets[0], EventType.A, false);
  770. assertEquals(2, l.length);
  771. assertEquals(listeners[2], l[0].listener);
  772. assertEquals(listeners[3], l[1].listener);
  773. l = getListeners(eventTargets[0], EventType.B, true);
  774. assertEquals(0, l.length);
  775. }
  776. function testGetListener() {
  777. if (!getListener) {
  778. return;
  779. }
  780. listen(eventTargets[0], EventType.A, listeners[0], true);
  781. assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));
  782. assertNull(getListener(eventTargets[0], EventType.A, listeners[0], true, {}));
  783. assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));
  784. assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));
  785. assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));
  786. }
  787. function testHasListener() {
  788. if (!hasListener) {
  789. return;
  790. }
  791. assertFalse(hasListener(eventTargets[0]));
  792. listen(eventTargets[0], EventType.A, listeners[0], true);
  793. assertTrue(hasListener(eventTargets[0]));
  794. assertTrue(hasListener(eventTargets[0], EventType.A));
  795. assertTrue(hasListener(eventTargets[0], EventType.A, true));
  796. assertTrue(hasListener(eventTargets[0], undefined, true));
  797. assertFalse(hasListener(eventTargets[0], EventType.A, false));
  798. assertFalse(hasListener(eventTargets[0], undefined, false));
  799. assertFalse(hasListener(eventTargets[0], EventType.B));
  800. assertFalse(hasListener(eventTargets[0], EventType.B, true));
  801. assertFalse(hasListener(eventTargets[1]));
  802. }
  803. function testFiringEventBeforeDisposeInternalWorks() {
  804. /**
  805. * @extends {goog.events.EventTarget}
  806. * @constructor
  807. * @final
  808. */
  809. var MockTarget = function() { MockTarget.base(this, 'constructor'); };
  810. goog.inherits(MockTarget, goog.events.EventTarget);
  811. MockTarget.prototype.disposeInternal = function() {
  812. dispatchEvent(this, EventType.A);
  813. MockTarget.base(this, 'disposeInternal');
  814. };
  815. var t = new MockTarget();
  816. try {
  817. listen(t, EventType.A, listeners[0]);
  818. t.dispose();
  819. assertListenerIsCalled(listeners[0], times(1));
  820. } catch (e) {
  821. goog.dispose(t);
  822. }
  823. }
  824. function testLoopDetection() {
  825. var target = listenableFactory();
  826. target.setParentEventTarget(target);
  827. try {
  828. target.dispatchEvent('string');
  829. fail('expected error');
  830. } catch (e) {
  831. assertContains('infinite', e.message);
  832. }
  833. }