12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052 |
- // Copyright 2012 The Closure Library Authors. All Rights Reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS-IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- /**
- * @fileoverview goog.events.EventTarget tester.
- * @author chrishenry@google.com (Chris Henry)
- */
- goog.provide('goog.events.eventTargetTester');
- goog.setTestOnly('goog.events.eventTargetTester');
- goog.provide('goog.events.eventTargetTester.KeyType');
- goog.setTestOnly('goog.events.eventTargetTester.KeyType');
- goog.provide('goog.events.eventTargetTester.UnlistenReturnType');
- goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');
- goog.require('goog.array');
- goog.require('goog.events');
- goog.require('goog.events.Event');
- goog.require('goog.events.EventTarget');
- goog.require('goog.testing.asserts');
- goog.require('goog.testing.recordFunction');
- /**
- * Setup step for the test functions. This needs to be called from the
- * test setUp.
- * @param {function():!goog.events.Listenable} listenableFactoryFn Function
- * that will return a new Listenable instance each time it is called.
- * @param {Function} listenFn Function that, given the same signature
- * as goog.events.listen, will add listener to the given event
- * target.
- * @param {Function} unlistenFn Function that, given the same
- * signature as goog.events.unlisten, will remove listener from
- * the given event target.
- * @param {Function} unlistenByKeyFn Function that, given 2
- * parameters: src and key, will remove the corresponding
- * listener.
- * @param {Function} listenOnceFn Function that, given the same
- * signature as goog.events.listenOnce, will add a one-time
- * listener to the given event target.
- * @param {Function} dispatchEventFn Function that, given the same
- * signature as goog.events.dispatchEvent, will dispatch the event
- * on the given event target.
- * @param {Function} removeAllFn Function that, given the same
- * signature as goog.events.removeAll, will remove all listeners
- * according to the contract of goog.events.removeAll.
- * @param {Function} getListenersFn Function that, given the same
- * signature as goog.events.getListeners, will retrieve listeners.
- * @param {Function} getListenerFn Function that, given the same
- * signature as goog.events.getListener, will retrieve the
- * listener object.
- * @param {Function} hasListenerFn Function that, given the same
- * signature as goog.events.hasListener, will determine whether
- * listeners exist.
- * @param {goog.events.eventTargetTester.KeyType} listenKeyType The
- * key type returned by listen call.
- * @param {goog.events.eventTargetTester.UnlistenReturnType}
- * unlistenFnReturnType
- * Whether we should check return value from
- * unlisten call. If unlisten does not return a value, this should
- * be set to false.
- * @param {boolean} objectListenerSupported Whether listener of type
- * Object is supported.
- */
- goog.events.eventTargetTester.setUp = function(
- listenableFactoryFn, listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,
- dispatchEventFn, removeAllFn, getListenersFn, getListenerFn, hasListenerFn,
- listenKeyType, unlistenFnReturnType, objectListenerSupported) {
- listenableFactory = listenableFactoryFn;
- listen = listenFn;
- unlisten = unlistenFn;
- unlistenByKey = unlistenByKeyFn;
- listenOnce = listenOnceFn;
- dispatchEvent = dispatchEventFn;
- removeAll = removeAllFn;
- getListeners = getListenersFn;
- getListener = getListenerFn;
- hasListener = hasListenerFn;
- keyType = listenKeyType;
- unlistenReturnType = unlistenFnReturnType;
- objectTypeListenerSupported = objectListenerSupported;
- listeners = [];
- for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
- listeners[i] = createListener();
- }
- eventTargets = [];
- for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
- eventTargets[i] = listenableFactory();
- }
- };
- /**
- * Teardown step for the test functions. This needs to be called from
- * test teardown.
- */
- goog.events.eventTargetTester.tearDown = function() {
- for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {
- goog.dispose(eventTargets[i]);
- }
- };
- /**
- * The type of key returned by key-returning functions (listen).
- * @enum {number}
- */
- goog.events.eventTargetTester.KeyType = {
- /**
- * Returns number for key.
- */
- NUMBER: 0,
- /**
- * Returns undefined (no return value).
- */
- UNDEFINED: 1
- };
- /**
- * The type of unlisten function's return value.
- * @enum {number}
- */
- goog.events.eventTargetTester.UnlistenReturnType = {
- /**
- * Returns boolean indicating whether unlisten is successful.
- */
- BOOLEAN: 0,
- /**
- * Returns undefind (no return value).
- */
- UNDEFINED: 1
- };
- /**
- * Expando property used on "listener" function to determine if a
- * listener has already been checked. This is what allows us to
- * implement assertNoOtherListenerIsCalled.
- * @type {string}
- */
- goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';
- /**
- * Expando property used on "listener" function to record the number
- * of times it has been called the last time assertListenerIsCalled is
- * done. This allows us to verify that it has not been called more
- * times in assertNoOtherListenerIsCalled.
- */
- goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';
- /**
- * The maximum number of initialized event targets (in eventTargets
- * array) and listeners (in listeners array).
- * @type {number}
- * @private
- */
- goog.events.eventTargetTester.MAX_ = 10;
- /**
- * Contains test event types.
- * @enum {string}
- */
- var EventType = {
- A: goog.events.getUniqueId('a'),
- B: goog.events.getUniqueId('b'),
- C: goog.events.getUniqueId('c')
- };
- var listenableFactory, listen, unlisten, unlistenByKey, listenOnce;
- var dispatchEvent, removeAll, getListeners, getListener, hasListener;
- var keyType, unlistenReturnType, objectTypeListenerSupported;
- var eventTargets, listeners;
- /**
- * Custom event object for testing.
- * @constructor
- * @extends {goog.events.Event}
- * @final
- */
- var TestEvent = function() {
- TestEvent.base(this, 'constructor', EventType.A);
- };
- goog.inherits(TestEvent, goog.events.Event);
- /**
- * Creates a listener that executes the given function (optional).
- * @param {!Function=} opt_listenerFn The optional function to execute.
- * @return {!Function} The listener function.
- */
- function createListener(opt_listenerFn) {
- return goog.testing.recordFunction(opt_listenerFn);
- }
- /**
- * Asserts that the given listener is called numCount number of times.
- * @param {!Function} listener The listener to check.
- * @param {number} numCount The number of times. See also the times()
- * function below.
- */
- function assertListenerIsCalled(listener, numCount) {
- assertEquals(
- 'Listeners is not called the correct number of times.', numCount,
- listener.getCallCount());
- listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;
- listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;
- }
- /**
- * Asserts that no other listeners, other than those verified via
- * assertListenerIsCalled, have been called since the last
- * resetListeners().
- */
- function assertNoOtherListenerIsCalled() {
- goog.array.forEach(listeners, function(l, index) {
- if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {
- assertEquals(
- 'Listeners ' + index + ' is unexpectedly called.', 0,
- l.getCallCount());
- } else {
- assertEquals(
- 'Listeners ' + index + ' is unexpectedly called.',
- l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());
- }
- });
- }
- /**
- * Resets all listeners call count to 0.
- */
- function resetListeners() {
- goog.array.forEach(listeners, function(l) {
- l.reset();
- l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;
- });
- }
- /**
- * The number of times a listener should have been executed. This
- * exists to make assertListenerIsCalled more readable. This is used
- * like so: assertListenerIsCalled(listener, times(2));
- * @param {number} n The number of times a listener should have been
- * executed.
- * @return {number} The number n.
- */
- function times(n) {
- return n;
- }
- function testNoListener() {
- dispatchEvent(eventTargets[0], EventType.A);
- assertNoOtherListenerIsCalled();
- }
- function testOneListener() {
- listen(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- resetListeners();
- dispatchEvent(eventTargets[0], EventType.B);
- dispatchEvent(eventTargets[0], EventType.C);
- assertNoOtherListenerIsCalled();
- }
- function testTwoListenersOfSameType() {
- var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
- var key2 = listen(eventTargets[0], EventType.A, listeners[1]);
- if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
- assertNotEquals(key1, key2);
- } else {
- assertUndefined(key1);
- assertUndefined(key2);
- }
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testInstallingSameListeners() {
- var key1 = listen(eventTargets[0], EventType.A, listeners[0]);
- var key2 = listen(eventTargets[0], EventType.A, listeners[0]);
- var key3 = listen(eventTargets[0], EventType.B, listeners[0]);
- if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {
- assertEquals(key1, key2);
- assertNotEquals(key1, key3);
- } else {
- assertUndefined(key1);
- assertUndefined(key2);
- assertUndefined(key3);
- }
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- dispatchEvent(eventTargets[0], EventType.B);
- assertListenerIsCalled(listeners[0], times(2));
- assertNoOtherListenerIsCalled();
- }
- function testScope() {
- listeners[0] = createListener(function(e) {
- assertEquals('Wrong scope with undefined scope', eventTargets[0], this);
- });
- listeners[1] = createListener(function(e) {
- assertEquals('Wrong scope with null scope', eventTargets[0], this);
- });
- var scope = {};
- listeners[2] = createListener(function(e) {
- assertEquals('Wrong scope with specific scope object', scope, this);
- });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1], false, null);
- listen(eventTargets[0], EventType.A, listeners[2], false, scope);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- }
- function testDispatchEventDoesNotThrowWithDisposedEventTarget() {
- goog.dispose(eventTargets[0]);
- assertTrue(dispatchEvent(eventTargets[0], EventType.A));
- }
- function testDispatchEventWithObjectLiteral() {
- listen(eventTargets[0], EventType.A, listeners[0]);
- assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testDispatchEventWithCustomEventObject() {
- listen(eventTargets[0], EventType.A, listeners[0]);
- var e = new TestEvent();
- assertTrue(dispatchEvent(eventTargets[0], e));
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- var actualEvent = listeners[0].getLastCall().getArgument(0);
- assertEquals(e, actualEvent);
- assertEquals(eventTargets[0], actualEvent.target);
- }
- function testDisposingEventTargetRemovesListeners() {
- if (!(listenableFactory() instanceof goog.events.EventTarget)) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0]);
- goog.dispose(eventTargets[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertNoOtherListenerIsCalled();
- }
- /**
- * Unlisten/unlistenByKey should still work after disposal. There are
- * many circumstances when this is actually necessary. For example, a
- * user may have listened to an event target and stored the key
- * (e.g. in a goog.events.EventHandler) and only unlisten after the
- * target has been disposed.
- */
- function testUnlistenWorksAfterDisposal() {
- var key = listen(eventTargets[0], EventType.A, listeners[0]);
- goog.dispose(eventTargets[0]);
- unlisten(eventTargets[0], EventType.A, listeners[1]);
- if (unlistenByKey) {
- unlistenByKey(eventTargets[0], key);
- }
- }
- function testRemovingListener() {
- var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[0]);
- var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);
- var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);
- var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);
- var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- if (unlistenReturnType ==
- goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {
- assertFalse(ret1);
- assertFalse(ret2);
- assertFalse(ret3);
- assertFalse(ret4);
- assertTrue(ret5);
- assertFalse(ret6);
- } else {
- assertUndefined(ret1);
- assertUndefined(ret2);
- assertUndefined(ret3);
- assertUndefined(ret4);
- assertUndefined(ret5);
- assertUndefined(ret6);
- }
- }
- function testCapture() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- eventTargets[9].setParentEventTarget(eventTargets[0]);
- var ordering = 0;
- listeners[0] = createListener(function(e) {
- assertEquals(eventTargets[2], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('First capture listener is not called first', 0, ordering);
- ordering++;
- });
- listeners[1] = createListener(function(e) {
- assertEquals(eventTargets[1], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('2nd capture listener is not called 2nd', 1, ordering);
- ordering++;
- });
- listeners[2] = createListener(function(e) {
- assertEquals(eventTargets[0], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('3rd capture listener is not called 3rd', 2, ordering);
- ordering++;
- });
- listen(eventTargets[2], EventType.A, listeners[0], true);
- listen(eventTargets[1], EventType.A, listeners[1], true);
- listen(eventTargets[0], EventType.A, listeners[2], true);
- // These should not be called.
- listen(eventTargets[3], EventType.A, listeners[3], true);
- listen(eventTargets[0], EventType.B, listeners[4], true);
- listen(eventTargets[0], EventType.C, listeners[5], true);
- listen(eventTargets[1], EventType.B, listeners[6], true);
- listen(eventTargets[1], EventType.C, listeners[7], true);
- listen(eventTargets[2], EventType.B, listeners[8], true);
- listen(eventTargets[2], EventType.C, listeners[9], true);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testBubble() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- eventTargets[9].setParentEventTarget(eventTargets[0]);
- var ordering = 0;
- listeners[0] = createListener(function(e) {
- assertEquals(eventTargets[0], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('First bubble listener is not called first', 0, ordering);
- ordering++;
- });
- listeners[1] = createListener(function(e) {
- assertEquals(eventTargets[1], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('2nd bubble listener is not called 2nd', 1, ordering);
- ordering++;
- });
- listeners[2] = createListener(function(e) {
- assertEquals(eventTargets[2], e.currentTarget);
- assertEquals(eventTargets[0], e.target);
- assertEquals('3rd bubble listener is not called 3rd', 2, ordering);
- ordering++;
- });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[1], EventType.A, listeners[1]);
- listen(eventTargets[2], EventType.A, listeners[2]);
- // These should not be called.
- listen(eventTargets[3], EventType.A, listeners[3]);
- listen(eventTargets[0], EventType.B, listeners[4]);
- listen(eventTargets[0], EventType.C, listeners[5]);
- listen(eventTargets[1], EventType.B, listeners[6]);
- listen(eventTargets[1], EventType.C, listeners[7]);
- listen(eventTargets[2], EventType.B, listeners[8]);
- listen(eventTargets[2], EventType.C, listeners[9]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testCaptureAndBubble() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- listen(eventTargets[0], EventType.A, listeners[0], true);
- listen(eventTargets[1], EventType.A, listeners[1], true);
- listen(eventTargets[2], EventType.A, listeners[2], true);
- listen(eventTargets[0], EventType.A, listeners[3]);
- listen(eventTargets[1], EventType.A, listeners[4]);
- listen(eventTargets[2], EventType.A, listeners[5]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- assertListenerIsCalled(listeners[3], times(1));
- assertListenerIsCalled(listeners[4], times(1));
- assertListenerIsCalled(listeners[5], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testPreventDefaultByReturningFalse() {
- listeners[0] = createListener(function(e) { return false; });
- listeners[1] = createListener(function(e) { return true; });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- var result = dispatchEvent(eventTargets[0], EventType.A);
- assertFalse(result);
- }
- function testPreventDefault() {
- listeners[0] = createListener(function(e) { e.preventDefault(); });
- listeners[1] = createListener(function(e) { return true; });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- var result = dispatchEvent(eventTargets[0], EventType.A);
- assertFalse(result);
- }
- function testPreventDefaultAtCapture() {
- listeners[0] = createListener(function(e) { e.preventDefault(); });
- listeners[1] = createListener(function(e) { return true; });
- listen(eventTargets[0], EventType.A, listeners[0], true);
- listen(eventTargets[0], EventType.A, listeners[1], true);
- var result = dispatchEvent(eventTargets[0], EventType.A);
- assertFalse(result);
- }
- function testStopPropagation() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- listeners[0] = createListener(function(e) { e.stopPropagation(); });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[1], EventType.A, listeners[2]);
- listen(eventTargets[2], EventType.A, listeners[3]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testStopPropagation2() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- listeners[1] = createListener(function(e) { e.stopPropagation(); });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[1], EventType.A, listeners[2]);
- listen(eventTargets[2], EventType.A, listeners[3]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testStopPropagation3() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- listeners[2] = createListener(function(e) { e.stopPropagation(); });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[1], EventType.A, listeners[2]);
- listen(eventTargets[2], EventType.A, listeners[3]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testStopPropagationAtCapture() {
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- eventTargets[1].setParentEventTarget(eventTargets[2]);
- listeners[0] = createListener(function(e) { e.stopPropagation(); });
- listen(eventTargets[2], EventType.A, listeners[0], true);
- listen(eventTargets[1], EventType.A, listeners[1], true);
- listen(eventTargets[0], EventType.A, listeners[2], true);
- listen(eventTargets[0], EventType.A, listeners[3]);
- listen(eventTargets[1], EventType.A, listeners[4]);
- listen(eventTargets[2], EventType.A, listeners[5]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testHandleEvent() {
- if (!objectTypeListenerSupported) {
- return;
- }
- var obj = {};
- obj.handleEvent = goog.testing.recordFunction();
- listen(eventTargets[0], EventType.A, obj);
- dispatchEvent(eventTargets[0], EventType.A);
- assertEquals(1, obj.handleEvent.getCallCount());
- }
- function testListenOnce() {
- if (!listenOnce) {
- return;
- }
- listenOnce(eventTargets[0], EventType.A, listeners[0], true);
- listenOnce(eventTargets[0], EventType.A, listeners[1]);
- listenOnce(eventTargets[0], EventType.B, listeners[2]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(0));
- assertNoOtherListenerIsCalled();
- resetListeners();
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(0));
- assertListenerIsCalled(listeners[1], times(0));
- assertListenerIsCalled(listeners[2], times(0));
- dispatchEvent(eventTargets[0], EventType.B);
- assertListenerIsCalled(listeners[2], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testUnlistenInListen() {
- listeners[1] = createListener(function(e) {
- unlisten(eventTargets[0], EventType.A, listeners[1]);
- unlisten(eventTargets[0], EventType.A, listeners[2]);
- });
- listen(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[0], EventType.A, listeners[2]);
- listen(eventTargets[0], EventType.A, listeners[3]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(0));
- assertListenerIsCalled(listeners[3], times(1));
- assertNoOtherListenerIsCalled();
- resetListeners();
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(0));
- assertListenerIsCalled(listeners[2], times(0));
- assertListenerIsCalled(listeners[3], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testUnlistenByKeyInListen() {
- if (!unlistenByKey) {
- return;
- }
- var key1, key2;
- listeners[1] = createListener(function(e) {
- unlistenByKey(eventTargets[0], key1);
- unlistenByKey(eventTargets[0], key2);
- });
- listen(eventTargets[0], EventType.A, listeners[0]);
- key1 = listen(eventTargets[0], EventType.A, listeners[1]);
- key2 = listen(eventTargets[0], EventType.A, listeners[2]);
- listen(eventTargets[0], EventType.A, listeners[3]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(0));
- assertListenerIsCalled(listeners[3], times(1));
- assertNoOtherListenerIsCalled();
- resetListeners();
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(0));
- assertListenerIsCalled(listeners[2], times(0));
- assertListenerIsCalled(listeners[3], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testSetParentEventTarget() {
- assertNull(eventTargets[0].getParentEventTarget());
- eventTargets[0].setParentEventTarget(eventTargets[1]);
- assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());
- assertNull(eventTargets[1].getParentEventTarget());
- eventTargets[0].setParentEventTarget(null);
- assertNull(eventTargets[0].getParentEventTarget());
- }
- function testListenOnceAfterListenDoesNotChangeExistingListener() {
- if (!listenOnce) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0]);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(3));
- assertNoOtherListenerIsCalled();
- }
- function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {
- if (!listenOnce) {
- return;
- }
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testListenAfterListenOnceRemoveOnceness() {
- if (!listenOnce) {
- return;
- }
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.A);
- assertListenerIsCalled(listeners[0], times(3));
- assertNoOtherListenerIsCalled();
- }
- function testUnlistenAfterListenOnce() {
- if (!listenOnce) {
- return;
- }
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- unlisten(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- listen(eventTargets[0], EventType.A, listeners[0]);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- unlisten(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- listen(eventTargets[0], EventType.A, listeners[0]);
- unlisten(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- listenOnce(eventTargets[0], EventType.A, listeners[0]);
- unlisten(eventTargets[0], EventType.A, listeners[0]);
- dispatchEvent(eventTargets[0], EventType.A);
- assertNoOtherListenerIsCalled();
- }
- function testRemoveAllWithType() {
- if (!removeAll) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0], true);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[0], EventType.C, listeners[2], true);
- listen(eventTargets[0], EventType.C, listeners[3]);
- listen(eventTargets[0], EventType.B, listeners[4], true);
- listen(eventTargets[0], EventType.B, listeners[5], true);
- listen(eventTargets[0], EventType.B, listeners[6]);
- listen(eventTargets[0], EventType.B, listeners[7]);
- assertEquals(4, removeAll(eventTargets[0], EventType.B));
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.B);
- dispatchEvent(eventTargets[0], EventType.C);
- assertListenerIsCalled(listeners[0], times(1));
- assertListenerIsCalled(listeners[1], times(1));
- assertListenerIsCalled(listeners[2], times(1));
- assertListenerIsCalled(listeners[3], times(1));
- assertNoOtherListenerIsCalled();
- }
- function testRemoveAll() {
- if (!removeAll) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0], true);
- listen(eventTargets[0], EventType.A, listeners[1]);
- listen(eventTargets[0], EventType.C, listeners[2], true);
- listen(eventTargets[0], EventType.C, listeners[3]);
- listen(eventTargets[0], EventType.B, listeners[4], true);
- listen(eventTargets[0], EventType.B, listeners[5], true);
- listen(eventTargets[0], EventType.B, listeners[6]);
- listen(eventTargets[0], EventType.B, listeners[7]);
- assertEquals(8, removeAll(eventTargets[0]));
- dispatchEvent(eventTargets[0], EventType.A);
- dispatchEvent(eventTargets[0], EventType.B);
- dispatchEvent(eventTargets[0], EventType.C);
- assertNoOtherListenerIsCalled();
- }
- function testRemoveAllCallsMarkAsRemoved() {
- if (!removeAll) {
- return;
- }
- var key0 = listen(eventTargets[0], EventType.A, listeners[0]);
- var key1 = listen(eventTargets[1], EventType.A, listeners[1]);
- assertNotNullNorUndefined(key0.listener);
- assertFalse(key0.removed);
- assertNotNullNorUndefined(key1.listener);
- assertFalse(key1.removed);
- assertEquals(1, removeAll(eventTargets[0]));
- assertNull(key0.listener);
- assertTrue(key0.removed);
- assertNotNullNorUndefined(key1.listener);
- assertFalse(key1.removed);
- assertEquals(1, removeAll(eventTargets[1]));
- assertNull(key1.listener);
- assertTrue(key1.removed);
- }
- function testGetListeners() {
- if (!getListeners) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0], true);
- listen(eventTargets[0], EventType.A, listeners[1], true);
- listen(eventTargets[0], EventType.A, listeners[2]);
- listen(eventTargets[0], EventType.A, listeners[3]);
- var l = getListeners(eventTargets[0], EventType.A, true);
- assertEquals(2, l.length);
- assertEquals(listeners[0], l[0].listener);
- assertEquals(listeners[1], l[1].listener);
- l = getListeners(eventTargets[0], EventType.A, false);
- assertEquals(2, l.length);
- assertEquals(listeners[2], l[0].listener);
- assertEquals(listeners[3], l[1].listener);
- l = getListeners(eventTargets[0], EventType.B, true);
- assertEquals(0, l.length);
- }
- function testGetListener() {
- if (!getListener) {
- return;
- }
- listen(eventTargets[0], EventType.A, listeners[0], true);
- assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));
- assertNull(getListener(eventTargets[0], EventType.A, listeners[0], true, {}));
- assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));
- assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));
- assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));
- }
- function testHasListener() {
- if (!hasListener) {
- return;
- }
- assertFalse(hasListener(eventTargets[0]));
- listen(eventTargets[0], EventType.A, listeners[0], true);
- assertTrue(hasListener(eventTargets[0]));
- assertTrue(hasListener(eventTargets[0], EventType.A));
- assertTrue(hasListener(eventTargets[0], EventType.A, true));
- assertTrue(hasListener(eventTargets[0], undefined, true));
- assertFalse(hasListener(eventTargets[0], EventType.A, false));
- assertFalse(hasListener(eventTargets[0], undefined, false));
- assertFalse(hasListener(eventTargets[0], EventType.B));
- assertFalse(hasListener(eventTargets[0], EventType.B, true));
- assertFalse(hasListener(eventTargets[1]));
- }
- function testFiringEventBeforeDisposeInternalWorks() {
- /**
- * @extends {goog.events.EventTarget}
- * @constructor
- * @final
- */
- var MockTarget = function() { MockTarget.base(this, 'constructor'); };
- goog.inherits(MockTarget, goog.events.EventTarget);
- MockTarget.prototype.disposeInternal = function() {
- dispatchEvent(this, EventType.A);
- MockTarget.base(this, 'disposeInternal');
- };
- var t = new MockTarget();
- try {
- listen(t, EventType.A, listeners[0]);
- t.dispose();
- assertListenerIsCalled(listeners[0], times(1));
- } catch (e) {
- goog.dispose(t);
- }
- }
- function testLoopDetection() {
- var target = listenableFactory();
- target.setParentEventTarget(target);
- try {
- target.dispatchEvent('string');
- fail('expected error');
- } catch (e) {
- assertContains('infinite', e.message);
- }
- }
|