events_test.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  1. // Copyright 2006 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. goog.provide('goog.eventsTest');
  15. goog.setTestOnly('goog.eventsTest');
  16. goog.require('goog.asserts.AssertionError');
  17. goog.require('goog.debug.EntryPointMonitor');
  18. goog.require('goog.debug.ErrorHandler');
  19. goog.require('goog.debug.entryPointRegistry');
  20. goog.require('goog.dom');
  21. goog.require('goog.dom.TagName');
  22. goog.require('goog.events');
  23. goog.require('goog.events.BrowserFeature');
  24. goog.require('goog.events.CaptureSimulationMode');
  25. goog.require('goog.events.Event');
  26. goog.require('goog.events.EventTarget');
  27. goog.require('goog.events.EventType');
  28. goog.require('goog.events.Listener');
  29. goog.require('goog.functions');
  30. goog.require('goog.testing.PropertyReplacer');
  31. goog.require('goog.testing.jsunit');
  32. goog.require('goog.testing.recordFunction');
  33. var originalHandleBrowserEvent = goog.events.handleBrowserEvent_;
  34. var propertyReplacer;
  35. var et1, et2, et3;
  36. function setUp() {
  37. et1 = new goog.events.EventTarget();
  38. et2 = new goog.events.EventTarget();
  39. et3 = new goog.events.EventTarget();
  40. propertyReplacer = new goog.testing.PropertyReplacer();
  41. }
  42. function tearDown() {
  43. goog.events.CAPTURE_SIMULATION_MODE = goog.events.CaptureSimulationMode.ON;
  44. goog.events.handleBrowserEvent_ = originalHandleBrowserEvent;
  45. goog.disposeAll(et1, et2, et3);
  46. goog.events.removeAll(document.body);
  47. propertyReplacer.reset();
  48. }
  49. function testProtectBrowserEventEntryPoint() {
  50. var errorHandlerFn = goog.testing.recordFunction();
  51. var errorHandler = new goog.debug.ErrorHandler(errorHandlerFn);
  52. goog.events.protectBrowserEventEntryPoint(errorHandler);
  53. var browserEventHandler =
  54. goog.testing.recordFunction(goog.events.handleBrowserEvent_);
  55. goog.events.handleBrowserEvent_ = function() {
  56. try {
  57. browserEventHandler.apply(this, arguments);
  58. } catch (e) {
  59. // Ignored.
  60. }
  61. };
  62. var err = Error('test');
  63. var body = document.body;
  64. goog.events.listen(
  65. body, goog.events.EventType.CLICK, function() { throw err; });
  66. dispatchClick(body);
  67. assertEquals(
  68. 'Error handler callback should be called.', 1,
  69. errorHandlerFn.getCallCount());
  70. assertEquals(err, errorHandlerFn.getLastCall().getArgument(0));
  71. assertEquals(1, browserEventHandler.getCallCount());
  72. var err2 = browserEventHandler.getLastCall().getError();
  73. assertNotNull(err2);
  74. assertTrue(err2 instanceof goog.debug.ErrorHandler.ProtectedFunctionError);
  75. }
  76. function testSelfRemove() {
  77. var callback = function() {
  78. // This listener removes itself during event dispatching, so it
  79. // is marked as 'removed' but not actually removed until after event
  80. // dispatching ends.
  81. goog.events.removeAll(et1, 'click');
  82. // Test that goog.events.getListener ignores events marked as 'removed'.
  83. assertNull(goog.events.getListener(et1, 'click', callback));
  84. };
  85. var key = goog.events.listen(et1, 'click', callback);
  86. goog.events.dispatchEvent(et1, 'click');
  87. }
  88. function testHasListener() {
  89. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  90. assertFalse(goog.events.hasListener(div));
  91. var key = goog.events.listen(div, 'click', function() {});
  92. assertTrue(goog.events.hasListener(div));
  93. assertTrue(goog.events.hasListener(div, 'click'));
  94. assertTrue(goog.events.hasListener(div, 'click', false));
  95. assertTrue(goog.events.hasListener(div, undefined, false));
  96. assertFalse(goog.events.hasListener(div, 'click', true));
  97. assertFalse(goog.events.hasListener(div, undefined, true));
  98. assertFalse(goog.events.hasListener(div, 'mouseup'));
  99. // Test that hasListener returns false when all listeners are removed.
  100. goog.events.unlistenByKey(key);
  101. assertFalse(goog.events.hasListener(div));
  102. }
  103. function testHasListenerWithEventTarget() {
  104. assertFalse(goog.events.hasListener(et1));
  105. function callback(){};
  106. goog.events.listen(et1, 'test', callback, true);
  107. assertTrue(goog.events.hasListener(et1));
  108. assertTrue(goog.events.hasListener(et1, 'test'));
  109. assertTrue(goog.events.hasListener(et1, 'test', true));
  110. assertTrue(goog.events.hasListener(et1, undefined, true));
  111. assertFalse(goog.events.hasListener(et1, 'click'));
  112. assertFalse(goog.events.hasListener(et1, 'test', false));
  113. goog.events.unlisten(et1, 'test', callback, true);
  114. assertFalse(goog.events.hasListener(et1));
  115. }
  116. function testHasListenerWithMultipleTargets() {
  117. function callback(){};
  118. goog.events.listen(et1, 'test1', callback, true);
  119. goog.events.listen(et2, 'test2', callback, true);
  120. assertTrue(goog.events.hasListener(et1));
  121. assertTrue(goog.events.hasListener(et2));
  122. assertTrue(goog.events.hasListener(et1, 'test1'));
  123. assertTrue(goog.events.hasListener(et2, 'test2'));
  124. assertFalse(goog.events.hasListener(et1, 'et2'));
  125. assertFalse(goog.events.hasListener(et2, 'et1'));
  126. goog.events.removeAll(et1);
  127. goog.events.removeAll(et2);
  128. }
  129. function testBubbleSingle() {
  130. et1.setParentEventTarget(et2);
  131. et2.setParentEventTarget(et3);
  132. var count = 0;
  133. function callback() { count++; }
  134. goog.events.listen(et3, 'test', callback, false);
  135. et1.dispatchEvent('test');
  136. assertEquals(1, count);
  137. goog.events.removeAll(et1);
  138. goog.events.removeAll(et2);
  139. goog.events.removeAll(et3);
  140. }
  141. function testCaptureSingle() {
  142. et1.setParentEventTarget(et2);
  143. et2.setParentEventTarget(et3);
  144. var count = 0;
  145. function callback() { count++; }
  146. goog.events.listen(et3, 'test', callback, true);
  147. et1.dispatchEvent('test');
  148. assertEquals(1, count);
  149. goog.events.removeAll(et1);
  150. goog.events.removeAll(et2);
  151. goog.events.removeAll(et3);
  152. }
  153. function testCaptureAndBubble() {
  154. et1.setParentEventTarget(et2);
  155. et2.setParentEventTarget(et3);
  156. var count = 0;
  157. function callbackCapture1() {
  158. count++;
  159. assertEquals(3, count);
  160. }
  161. function callbackBubble1() {
  162. count++;
  163. assertEquals(4, count);
  164. }
  165. function callbackCapture2() {
  166. count++;
  167. assertEquals(2, count);
  168. }
  169. function callbackBubble2() {
  170. count++;
  171. assertEquals(5, count);
  172. }
  173. function callbackCapture3() {
  174. count++;
  175. assertEquals(1, count);
  176. }
  177. function callbackBubble3() {
  178. count++;
  179. assertEquals(6, count);
  180. }
  181. goog.events.listen(et1, 'test', callbackCapture1, true);
  182. goog.events.listen(et1, 'test', callbackBubble1, false);
  183. goog.events.listen(et2, 'test', callbackCapture2, true);
  184. goog.events.listen(et2, 'test', callbackBubble2, false);
  185. goog.events.listen(et3, 'test', callbackCapture3, true);
  186. goog.events.listen(et3, 'test', callbackBubble3, false);
  187. et1.dispatchEvent('test');
  188. assertEquals(6, count);
  189. goog.events.removeAll(et1);
  190. goog.events.removeAll(et2);
  191. goog.events.removeAll(et3);
  192. // Try again with the new API:
  193. count = 0;
  194. goog.events.listen(et1, 'test', callbackCapture1, {capture: true});
  195. goog.events.listen(et1, 'test', callbackBubble1, {capture: false});
  196. goog.events.listen(et2, 'test', callbackCapture2, {capture: true});
  197. goog.events.listen(et2, 'test', callbackBubble2, {capture: false});
  198. goog.events.listen(et3, 'test', callbackCapture3, {capture: true});
  199. goog.events.listen(et3, 'test', callbackBubble3, {capture: false});
  200. et1.dispatchEvent('test');
  201. assertEquals(6, count);
  202. goog.events.removeAll(et1);
  203. goog.events.removeAll(et2);
  204. goog.events.removeAll(et3);
  205. // Try again with the new API and without capture simulation:
  206. if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) return;
  207. goog.events.CAPTURE_SIMULATION_MODE =
  208. goog.events.CaptureSimulationMode.OFF_AND_FAIL;
  209. count = 0;
  210. goog.events.listen(et1, 'test', callbackCapture1, {capture: true});
  211. goog.events.listen(et1, 'test', callbackBubble1, {capture: false});
  212. goog.events.listen(et2, 'test', callbackCapture2, {capture: true});
  213. goog.events.listen(et2, 'test', callbackBubble2, {capture: false});
  214. goog.events.listen(et3, 'test', callbackCapture3, {capture: true});
  215. goog.events.listen(et3, 'test', callbackBubble3, {capture: false});
  216. et1.dispatchEvent('test');
  217. assertEquals(6, count);
  218. goog.events.removeAll(et1);
  219. goog.events.removeAll(et2);
  220. goog.events.removeAll(et3);
  221. }
  222. function testCapturingRemovesBubblingListener() {
  223. var bubbleCount = 0;
  224. function callbackBubble() { bubbleCount++; }
  225. var captureCount = 0;
  226. function callbackCapture() {
  227. captureCount++;
  228. goog.events.removeAll(et1);
  229. }
  230. goog.events.listen(et1, 'test', callbackCapture, true);
  231. goog.events.listen(et1, 'test', callbackBubble, false);
  232. et1.dispatchEvent('test');
  233. assertEquals(1, captureCount);
  234. assertEquals(0, bubbleCount);
  235. }
  236. function dispatchClick(target) {
  237. if (target.click) {
  238. target.click();
  239. } else {
  240. var e = document.createEvent('MouseEvents');
  241. e.initMouseEvent(
  242. 'click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false,
  243. 0, null);
  244. target.dispatchEvent(e);
  245. }
  246. }
  247. function testHandleBrowserEventBubblingListener() {
  248. var count = 0;
  249. var body = document.body;
  250. goog.events.listen(body, 'click', function() { count++; });
  251. dispatchClick(body);
  252. assertEquals(1, count);
  253. }
  254. function testHandleBrowserEventCapturingListener() {
  255. var count = 0;
  256. var body = document.body;
  257. goog.events.listen(body, 'click', function() { count++; }, true);
  258. dispatchClick(body);
  259. assertEquals(1, count);
  260. }
  261. function testHandleBrowserEventCapturingAndBubblingListener() {
  262. var count = 1;
  263. var body = document.body;
  264. goog.events.listen(body, 'click', function() { count += 3; }, true);
  265. goog.events.listen(body, 'click', function() { count *= 5; }, false);
  266. dispatchClick(body);
  267. assertEquals(20, count);
  268. }
  269. function testHandleBrowserEventCapturingRemovesBubblingListener() {
  270. var body = document.body;
  271. var bubbleCount = 0;
  272. function callbackBubble() { bubbleCount++; }
  273. var captureCount = 0;
  274. function callbackCapture() {
  275. captureCount++;
  276. goog.events.removeAll(body);
  277. }
  278. goog.events.listen(body, 'click', callbackCapture, true);
  279. goog.events.listen(body, 'click', callbackBubble, false);
  280. dispatchClick(body);
  281. assertEquals(1, captureCount);
  282. assertEquals(0, bubbleCount);
  283. }
  284. function testHandleEventPropagationOnParentElement() {
  285. var count = 1;
  286. goog.events.listen(
  287. document.documentElement, 'click', function() { count += 3; }, true);
  288. goog.events.listen(
  289. document.documentElement, 'click', function() { count *= 5; }, false);
  290. dispatchClick(document.body);
  291. assertEquals(20, count);
  292. }
  293. function testEntryPointRegistry() {
  294. var monitor = new goog.debug.EntryPointMonitor();
  295. var replacement = function() {};
  296. monitor.wrap =
  297. goog.testing.recordFunction(goog.functions.constant(replacement));
  298. goog.debug.entryPointRegistry.monitorAll(monitor);
  299. assertTrue(monitor.wrap.getCallCount() >= 1);
  300. assertEquals(replacement, goog.events.handleBrowserEvent_);
  301. }
  302. // Fixes bug http://b/6434926
  303. function testListenOnceHandlerDispatchCausingInfiniteLoop() {
  304. var handleFoo =
  305. goog.testing.recordFunction(function() { et1.dispatchEvent('foo'); });
  306. goog.events.listenOnce(et1, 'foo', handleFoo);
  307. et1.dispatchEvent('foo');
  308. assertEquals(
  309. 'Handler should be called only once.', 1, handleFoo.getCallCount());
  310. }
  311. function testCreationStack() {
  312. if (!new Error().stack) return;
  313. propertyReplacer.replace(goog.events.Listener, 'ENABLE_MONITORING', true);
  314. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  315. var key =
  316. goog.events.listen(div, goog.events.EventType.CLICK, goog.nullFunction);
  317. var listenerStack = key.creationStack;
  318. // Check that the name of this test function occurs in the stack trace.
  319. assertContains('testCreationStack', listenerStack);
  320. goog.events.unlistenByKey(key);
  321. }
  322. function testListenOnceAfterListenDoesNotChangeExistingListener() {
  323. var listener = goog.testing.recordFunction();
  324. goog.events.listen(document.body, 'click', listener);
  325. goog.events.listenOnce(document.body, 'click', listener);
  326. dispatchClick(document.body);
  327. dispatchClick(document.body);
  328. dispatchClick(document.body);
  329. assertEquals(3, listener.getCallCount());
  330. }
  331. function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
  332. var listener = goog.testing.recordFunction();
  333. goog.events.listenOnce(document.body, 'click', listener);
  334. goog.events.listenOnce(document.body, 'click', listener);
  335. dispatchClick(document.body);
  336. dispatchClick(document.body);
  337. dispatchClick(document.body);
  338. assertEquals(1, listener.getCallCount());
  339. }
  340. function testListenAfterListenOnceRemoveOnceness() {
  341. var listener = goog.testing.recordFunction();
  342. goog.events.listenOnce(document.body, 'click', listener);
  343. goog.events.listen(document.body, 'click', listener);
  344. dispatchClick(document.body);
  345. dispatchClick(document.body);
  346. dispatchClick(document.body);
  347. assertEquals(3, listener.getCallCount());
  348. }
  349. function testUnlistenAfterListenOnce() {
  350. var listener = goog.testing.recordFunction();
  351. goog.events.listenOnce(document.body, 'click', listener);
  352. goog.events.unlisten(document.body, 'click', listener);
  353. dispatchClick(document.body);
  354. goog.events.listenOnce(document.body, 'click', listener);
  355. goog.events.listen(document.body, 'click', listener);
  356. goog.events.unlisten(document.body, 'click', listener);
  357. dispatchClick(document.body);
  358. goog.events.listen(document.body, 'click', listener);
  359. goog.events.listenOnce(document.body, 'click', listener);
  360. goog.events.unlisten(document.body, 'click', listener);
  361. dispatchClick(document.body);
  362. goog.events.listenOnce(document.body, 'click', listener);
  363. goog.events.listenOnce(document.body, 'click', listener);
  364. goog.events.unlisten(document.body, 'click', listener);
  365. dispatchClick(document.body);
  366. assertEquals(0, listener.getCallCount());
  367. }
  368. function testEventBubblingWithReentrantDispatch_bubbling() {
  369. runEventPropagationWithReentrantDispatch(false);
  370. }
  371. function testEventBubblingWithReentrantDispatch_capture() {
  372. runEventPropagationWithReentrantDispatch(true);
  373. }
  374. function runEventPropagationWithReentrantDispatch(useCapture) {
  375. var eventType = 'test-event-type';
  376. var child = et1;
  377. var parent = et2;
  378. child.setParentEventTarget(parent);
  379. var firstTarget = useCapture ? parent : child;
  380. var secondTarget = useCapture ? child : parent;
  381. var firstListener = function(evt) {
  382. if (evt.isFirstEvent) {
  383. // Fires another event of the same type the first time it is invoked.
  384. child.dispatchEvent(new goog.events.Event(eventType));
  385. }
  386. };
  387. goog.events.listen(firstTarget, eventType, firstListener, useCapture);
  388. var secondListener = goog.testing.recordFunction();
  389. goog.events.listen(secondTarget, eventType, secondListener, useCapture);
  390. // Fire the first event.
  391. var firstEvent = new goog.events.Event(eventType);
  392. firstEvent.isFirstEvent = true;
  393. child.dispatchEvent(firstEvent);
  394. assertEquals(2, secondListener.getCallCount());
  395. }
  396. function testEventPropagationWhenListenerRemoved_bubbling() {
  397. runEventPropagationWhenListenerRemoved(false);
  398. }
  399. function testEventPropagationWhenListenerRemoved_capture() {
  400. runEventPropagationWhenListenerRemoved(true);
  401. }
  402. function runEventPropagationWhenListenerRemoved(useCapture) {
  403. var eventType = 'test-event-type';
  404. var child = et1;
  405. var parent = et2;
  406. child.setParentEventTarget(parent);
  407. var firstTarget = useCapture ? parent : child;
  408. var secondTarget = useCapture ? child : parent;
  409. var firstListener = goog.testing.recordFunction();
  410. var secondListener = goog.testing.recordFunction();
  411. goog.events.listenOnce(firstTarget, eventType, firstListener, useCapture);
  412. goog.events.listen(secondTarget, eventType, secondListener, useCapture);
  413. child.dispatchEvent(new goog.events.Event(eventType));
  414. assertEquals(1, secondListener.getCallCount());
  415. }
  416. function testEventPropagationWhenListenerAdded_bubbling() {
  417. runEventPropagationWhenListenerAdded(false);
  418. }
  419. function testEventPropagationWhenListenerAdded_capture() {
  420. runEventPropagationWhenListenerAdded(true);
  421. }
  422. function runEventPropagationWhenListenerAdded(useCapture) {
  423. var eventType = 'test-event-type';
  424. var child = et1;
  425. var parent = et2;
  426. child.setParentEventTarget(parent);
  427. var firstTarget = useCapture ? parent : child;
  428. var secondTarget = useCapture ? child : parent;
  429. var firstListener = function() {
  430. goog.events.listen(secondTarget, eventType, secondListener, useCapture);
  431. };
  432. var secondListener = goog.testing.recordFunction();
  433. goog.events.listen(firstTarget, eventType, firstListener, useCapture);
  434. child.dispatchEvent(new goog.events.Event(eventType));
  435. assertEquals(1, secondListener.getCallCount());
  436. }
  437. function testEventPropagationWhenListenerAddedAndRemoved_bubbling() {
  438. runEventPropagationWhenListenerAddedAndRemoved(false);
  439. }
  440. function testEventPropagationWhenListenerAddedAndRemoved_capture() {
  441. runEventPropagationWhenListenerAddedAndRemoved(true);
  442. }
  443. function runEventPropagationWhenListenerAddedAndRemoved(useCapture) {
  444. var eventType = 'test-event-type';
  445. var child = et1;
  446. var parent = et2;
  447. child.setParentEventTarget(parent);
  448. var firstTarget = useCapture ? parent : child;
  449. var secondTarget = useCapture ? child : parent;
  450. var firstListener = function() {
  451. goog.events.listen(secondTarget, eventType, secondListener, useCapture);
  452. };
  453. var secondListener = goog.testing.recordFunction();
  454. goog.events.listenOnce(firstTarget, eventType, firstListener, useCapture);
  455. child.dispatchEvent(new goog.events.Event(eventType));
  456. assertEquals(1, secondListener.getCallCount());
  457. }
  458. function testAssertWhenUsedWithUninitializedCustomEventTarget() {
  459. var SubClass = function() { /* does not call superclass ctor */ };
  460. goog.inherits(SubClass, goog.events.EventTarget);
  461. var instance = new SubClass();
  462. var e;
  463. e = assertThrows(function() {
  464. goog.events.listen(instance, 'test1', function() {});
  465. });
  466. assertTrue(e instanceof goog.asserts.AssertionError);
  467. e = assertThrows(function() {
  468. goog.events.dispatchEvent(instance, 'test1');
  469. });
  470. assertTrue(e instanceof goog.asserts.AssertionError);
  471. e = assertThrows(function() { instance.dispatchEvent('test1'); });
  472. assertTrue(e instanceof goog.asserts.AssertionError);
  473. }
  474. function testAssertWhenDispatchEventIsUsedWithNonCustomEventTarget() {
  475. var obj = {};
  476. e = assertThrows(function() { goog.events.dispatchEvent(obj, 'test1'); });
  477. assertTrue(e instanceof goog.asserts.AssertionError);
  478. }
  479. function testPropagationStoppedDuringCapture() {
  480. var captureHandler =
  481. goog.testing.recordFunction(function(e) { e.stopPropagation(); });
  482. var bubbleHandler = goog.testing.recordFunction();
  483. var body = document.body;
  484. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  485. body.appendChild(div);
  486. try {
  487. goog.events.listen(body, 'click', captureHandler, true);
  488. goog.events.listen(div, 'click', bubbleHandler, false);
  489. goog.events.listen(body, 'click', bubbleHandler, false);
  490. dispatchClick(div);
  491. assertEquals(1, captureHandler.getCallCount());
  492. assertEquals(0, bubbleHandler.getCallCount());
  493. goog.events.unlisten(body, 'click', captureHandler, true);
  494. dispatchClick(div);
  495. assertEquals(2, bubbleHandler.getCallCount());
  496. } finally {
  497. goog.dom.removeNode(div);
  498. goog.events.removeAll(body);
  499. goog.events.removeAll(div);
  500. }
  501. }
  502. function testPropagationStoppedDuringBubble() {
  503. var captureHandler = goog.testing.recordFunction();
  504. var bubbleHandler1 =
  505. goog.testing.recordFunction(function(e) { e.stopPropagation(); });
  506. var bubbleHandler2 = goog.testing.recordFunction();
  507. var body = document.body;
  508. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  509. body.appendChild(div);
  510. try {
  511. goog.events.listen(body, 'click', captureHandler, true);
  512. goog.events.listen(div, 'click', bubbleHandler1, false);
  513. goog.events.listen(body, 'click', bubbleHandler2, false);
  514. dispatchClick(div);
  515. assertEquals(1, captureHandler.getCallCount());
  516. assertEquals(1, bubbleHandler1.getCallCount());
  517. assertEquals(0, bubbleHandler2.getCallCount());
  518. } finally {
  519. goog.dom.removeNode(div);
  520. goog.events.removeAll(body);
  521. goog.events.removeAll(div);
  522. }
  523. }
  524. function testAddingCaptureListenerDuringBubbleShouldNotFireTheListener() {
  525. var body = document.body;
  526. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  527. body.appendChild(div);
  528. var captureHandler1 = goog.testing.recordFunction();
  529. var captureHandler2 = goog.testing.recordFunction();
  530. var bubbleHandler = goog.testing.recordFunction(function(e) {
  531. goog.events.listen(body, 'click', captureHandler1, true);
  532. goog.events.listen(div, 'click', captureHandler2, true);
  533. });
  534. try {
  535. goog.events.listen(div, 'click', bubbleHandler, false);
  536. dispatchClick(div);
  537. // These verify that the capture handlers registered in the bubble
  538. // handler is not invoked in the same event propagation phase.
  539. assertEquals(0, captureHandler1.getCallCount());
  540. assertEquals(0, captureHandler2.getCallCount());
  541. assertEquals(1, bubbleHandler.getCallCount());
  542. } finally {
  543. goog.dom.removeNode(div);
  544. goog.events.removeAll(body);
  545. goog.events.removeAll(div);
  546. }
  547. }
  548. function testRemovingCaptureListenerDuringBubbleWouldNotFireListenerTwice() {
  549. var body = document.body;
  550. var div = goog.dom.createElement(goog.dom.TagName.DIV);
  551. body.appendChild(div);
  552. var captureHandler = goog.testing.recordFunction();
  553. var bubbleHandler1 = goog.testing.recordFunction(function(e) {
  554. goog.events.unlisten(body, 'click', captureHandler, true);
  555. });
  556. var bubbleHandler2 = goog.testing.recordFunction();
  557. try {
  558. goog.events.listen(body, 'click', captureHandler, true);
  559. goog.events.listen(div, 'click', bubbleHandler1, false);
  560. goog.events.listen(body, 'click', bubbleHandler2, false);
  561. dispatchClick(div);
  562. assertEquals(1, captureHandler.getCallCount());
  563. // Verify that neither of these handlers are called more than once.
  564. assertEquals(1, bubbleHandler1.getCallCount());
  565. assertEquals(1, bubbleHandler2.getCallCount());
  566. } finally {
  567. goog.dom.removeNode(div);
  568. goog.events.removeAll(body);
  569. goog.events.removeAll(div);
  570. }
  571. }
  572. function testCaptureSimulationModeOffAndFail() {
  573. goog.events.CAPTURE_SIMULATION_MODE =
  574. goog.events.CaptureSimulationMode.OFF_AND_FAIL;
  575. var captureHandler = goog.testing.recordFunction();
  576. if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
  577. var err = assertThrows(function() {
  578. goog.events.listen(document.body, 'click', captureHandler, true);
  579. });
  580. assertTrue(err instanceof goog.asserts.AssertionError);
  581. // Sanity tests.
  582. dispatchClick(document.body);
  583. assertEquals(0, captureHandler.getCallCount());
  584. } else {
  585. goog.events.listen(document.body, 'click', captureHandler, true);
  586. dispatchClick(document.body);
  587. assertEquals(1, captureHandler.getCallCount());
  588. }
  589. }
  590. function testCaptureSimulationModeOffAndSilent() {
  591. goog.events.CAPTURE_SIMULATION_MODE =
  592. goog.events.CaptureSimulationMode.OFF_AND_SILENT;
  593. var captureHandler = goog.testing.recordFunction();
  594. goog.events.listen(document.body, 'click', captureHandler, true);
  595. if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
  596. dispatchClick(document.body);
  597. assertEquals(0, captureHandler.getCallCount());
  598. } else {
  599. dispatchClick(document.body);
  600. assertEquals(1, captureHandler.getCallCount());
  601. }
  602. }