Path: blob/trunk/third_party/closure/goog/events/eventtargettester.js
2868 views
// Copyright 2012 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview goog.events.EventTarget tester.16* @author [email protected] (Chris Henry)17*/1819goog.provide('goog.events.eventTargetTester');20goog.setTestOnly('goog.events.eventTargetTester');21goog.provide('goog.events.eventTargetTester.KeyType');22goog.setTestOnly('goog.events.eventTargetTester.KeyType');23goog.provide('goog.events.eventTargetTester.UnlistenReturnType');24goog.setTestOnly('goog.events.eventTargetTester.UnlistenReturnType');2526goog.require('goog.array');27goog.require('goog.events');28goog.require('goog.events.Event');29goog.require('goog.events.EventTarget');30goog.require('goog.testing.asserts');31goog.require('goog.testing.recordFunction');323334/**35* Setup step for the test functions. This needs to be called from the36* test setUp.37* @param {function():!goog.events.Listenable} listenableFactoryFn Function38* that will return a new Listenable instance each time it is called.39* @param {Function} listenFn Function that, given the same signature40* as goog.events.listen, will add listener to the given event41* target.42* @param {Function} unlistenFn Function that, given the same43* signature as goog.events.unlisten, will remove listener from44* the given event target.45* @param {Function} unlistenByKeyFn Function that, given 246* parameters: src and key, will remove the corresponding47* listener.48* @param {Function} listenOnceFn Function that, given the same49* signature as goog.events.listenOnce, will add a one-time50* listener to the given event target.51* @param {Function} dispatchEventFn Function that, given the same52* signature as goog.events.dispatchEvent, will dispatch the event53* on the given event target.54* @param {Function} removeAllFn Function that, given the same55* signature as goog.events.removeAll, will remove all listeners56* according to the contract of goog.events.removeAll.57* @param {Function} getListenersFn Function that, given the same58* signature as goog.events.getListeners, will retrieve listeners.59* @param {Function} getListenerFn Function that, given the same60* signature as goog.events.getListener, will retrieve the61* listener object.62* @param {Function} hasListenerFn Function that, given the same63* signature as goog.events.hasListener, will determine whether64* listeners exist.65* @param {goog.events.eventTargetTester.KeyType} listenKeyType The66* key type returned by listen call.67* @param {goog.events.eventTargetTester.UnlistenReturnType}68* unlistenFnReturnType69* Whether we should check return value from70* unlisten call. If unlisten does not return a value, this should71* be set to false.72* @param {boolean} objectListenerSupported Whether listener of type73* Object is supported.74*/75goog.events.eventTargetTester.setUp = function(76listenableFactoryFn, listenFn, unlistenFn, unlistenByKeyFn, listenOnceFn,77dispatchEventFn, removeAllFn, getListenersFn, getListenerFn, hasListenerFn,78listenKeyType, unlistenFnReturnType, objectListenerSupported) {79listenableFactory = listenableFactoryFn;80listen = listenFn;81unlisten = unlistenFn;82unlistenByKey = unlistenByKeyFn;83listenOnce = listenOnceFn;84dispatchEvent = dispatchEventFn;85removeAll = removeAllFn;86getListeners = getListenersFn;87getListener = getListenerFn;88hasListener = hasListenerFn;89keyType = listenKeyType;90unlistenReturnType = unlistenFnReturnType;91objectTypeListenerSupported = objectListenerSupported;9293listeners = [];94for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {95listeners[i] = createListener();96}9798eventTargets = [];99for (i = 0; i < goog.events.eventTargetTester.MAX_; i++) {100eventTargets[i] = listenableFactory();101}102};103104105/**106* Teardown step for the test functions. This needs to be called from107* test teardown.108*/109goog.events.eventTargetTester.tearDown = function() {110for (var i = 0; i < goog.events.eventTargetTester.MAX_; i++) {111goog.dispose(eventTargets[i]);112}113};114115116/**117* The type of key returned by key-returning functions (listen).118* @enum {number}119*/120goog.events.eventTargetTester.KeyType = {121/**122* Returns number for key.123*/124NUMBER: 0,125126/**127* Returns undefined (no return value).128*/129UNDEFINED: 1130};131132133/**134* The type of unlisten function's return value.135* @enum {number}136*/137goog.events.eventTargetTester.UnlistenReturnType = {138/**139* Returns boolean indicating whether unlisten is successful.140*/141BOOLEAN: 0,142143/**144* Returns undefind (no return value).145*/146UNDEFINED: 1147};148149150/**151* Expando property used on "listener" function to determine if a152* listener has already been checked. This is what allows us to153* implement assertNoOtherListenerIsCalled.154* @type {string}155*/156goog.events.eventTargetTester.ALREADY_CHECKED_PROP = '__alreadyChecked';157158159/**160* Expando property used on "listener" function to record the number161* of times it has been called the last time assertListenerIsCalled is162* done. This allows us to verify that it has not been called more163* times in assertNoOtherListenerIsCalled.164*/165goog.events.eventTargetTester.NUM_CALLED_PROP = '__numCalled';166167168/**169* The maximum number of initialized event targets (in eventTargets170* array) and listeners (in listeners array).171* @type {number}172* @private173*/174goog.events.eventTargetTester.MAX_ = 10;175176177/**178* Contains test event types.179* @enum {string}180*/181var EventType = {182A: goog.events.getUniqueId('a'),183B: goog.events.getUniqueId('b'),184C: goog.events.getUniqueId('c')185};186187188var listenableFactory, listen, unlisten, unlistenByKey, listenOnce;189var dispatchEvent, removeAll, getListeners, getListener, hasListener;190var keyType, unlistenReturnType, objectTypeListenerSupported;191var eventTargets, listeners;192193194195/**196* Custom event object for testing.197* @constructor198* @extends {goog.events.Event}199* @final200*/201var TestEvent = function() {202TestEvent.base(this, 'constructor', EventType.A);203};204goog.inherits(TestEvent, goog.events.Event);205206207/**208* Creates a listener that executes the given function (optional).209* @param {!Function=} opt_listenerFn The optional function to execute.210* @return {!Function} The listener function.211*/212function createListener(opt_listenerFn) {213return goog.testing.recordFunction(opt_listenerFn);214}215216217/**218* Asserts that the given listener is called numCount number of times.219* @param {!Function} listener The listener to check.220* @param {number} numCount The number of times. See also the times()221* function below.222*/223function assertListenerIsCalled(listener, numCount) {224assertEquals(225'Listeners is not called the correct number of times.', numCount,226listener.getCallCount());227listener[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = true;228listener[goog.events.eventTargetTester.NUM_CALLED_PROP] = numCount;229}230231232/**233* Asserts that no other listeners, other than those verified via234* assertListenerIsCalled, have been called since the last235* resetListeners().236*/237function assertNoOtherListenerIsCalled() {238goog.array.forEach(listeners, function(l, index) {239if (!l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP]) {240assertEquals(241'Listeners ' + index + ' is unexpectedly called.', 0,242l.getCallCount());243} else {244assertEquals(245'Listeners ' + index + ' is unexpectedly called.',246l[goog.events.eventTargetTester.NUM_CALLED_PROP], l.getCallCount());247}248});249}250251252/**253* Resets all listeners call count to 0.254*/255function resetListeners() {256goog.array.forEach(listeners, function(l) {257l.reset();258l[goog.events.eventTargetTester.ALREADY_CHECKED_PROP] = false;259});260}261262263/**264* The number of times a listener should have been executed. This265* exists to make assertListenerIsCalled more readable. This is used266* like so: assertListenerIsCalled(listener, times(2));267* @param {number} n The number of times a listener should have been268* executed.269* @return {number} The number n.270*/271function times(n) {272return n;273}274275276function testNoListener() {277dispatchEvent(eventTargets[0], EventType.A);278assertNoOtherListenerIsCalled();279}280281282function testOneListener() {283listen(eventTargets[0], EventType.A, listeners[0]);284dispatchEvent(eventTargets[0], EventType.A);285assertListenerIsCalled(listeners[0], times(1));286assertNoOtherListenerIsCalled();287288resetListeners();289290dispatchEvent(eventTargets[0], EventType.B);291dispatchEvent(eventTargets[0], EventType.C);292assertNoOtherListenerIsCalled();293}294295296function testTwoListenersOfSameType() {297var key1 = listen(eventTargets[0], EventType.A, listeners[0]);298var key2 = listen(eventTargets[0], EventType.A, listeners[1]);299300if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {301assertNotEquals(key1, key2);302} else {303assertUndefined(key1);304assertUndefined(key2);305}306307dispatchEvent(eventTargets[0], EventType.A);308assertListenerIsCalled(listeners[0], times(1));309assertListenerIsCalled(listeners[1], times(1));310assertNoOtherListenerIsCalled();311}312313314function testInstallingSameListeners() {315var key1 = listen(eventTargets[0], EventType.A, listeners[0]);316var key2 = listen(eventTargets[0], EventType.A, listeners[0]);317var key3 = listen(eventTargets[0], EventType.B, listeners[0]);318319if (keyType == goog.events.eventTargetTester.KeyType.NUMBER) {320assertEquals(key1, key2);321assertNotEquals(key1, key3);322} else {323assertUndefined(key1);324assertUndefined(key2);325assertUndefined(key3);326}327328dispatchEvent(eventTargets[0], EventType.A);329assertListenerIsCalled(listeners[0], times(1));330331dispatchEvent(eventTargets[0], EventType.B);332assertListenerIsCalled(listeners[0], times(2));333334assertNoOtherListenerIsCalled();335}336337338function testScope() {339listeners[0] = createListener(function(e) {340assertEquals('Wrong scope with undefined scope', eventTargets[0], this);341});342listeners[1] = createListener(function(e) {343assertEquals('Wrong scope with null scope', eventTargets[0], this);344});345var scope = {};346listeners[2] = createListener(function(e) {347assertEquals('Wrong scope with specific scope object', scope, this);348});349listen(eventTargets[0], EventType.A, listeners[0]);350listen(eventTargets[0], EventType.A, listeners[1], false, null);351listen(eventTargets[0], EventType.A, listeners[2], false, scope);352353dispatchEvent(eventTargets[0], EventType.A);354assertListenerIsCalled(listeners[0], times(1));355assertListenerIsCalled(listeners[1], times(1));356assertListenerIsCalled(listeners[2], times(1));357}358359360function testDispatchEventDoesNotThrowWithDisposedEventTarget() {361goog.dispose(eventTargets[0]);362assertTrue(dispatchEvent(eventTargets[0], EventType.A));363}364365366function testDispatchEventWithObjectLiteral() {367listen(eventTargets[0], EventType.A, listeners[0]);368369assertTrue(dispatchEvent(eventTargets[0], {type: EventType.A}));370assertListenerIsCalled(listeners[0], times(1));371assertNoOtherListenerIsCalled();372}373374375function testDispatchEventWithCustomEventObject() {376listen(eventTargets[0], EventType.A, listeners[0]);377378var e = new TestEvent();379assertTrue(dispatchEvent(eventTargets[0], e));380assertListenerIsCalled(listeners[0], times(1));381assertNoOtherListenerIsCalled();382383var actualEvent = listeners[0].getLastCall().getArgument(0);384385assertEquals(e, actualEvent);386assertEquals(eventTargets[0], actualEvent.target);387}388389390function testDisposingEventTargetRemovesListeners() {391if (!(listenableFactory() instanceof goog.events.EventTarget)) {392return;393}394listen(eventTargets[0], EventType.A, listeners[0]);395goog.dispose(eventTargets[0]);396dispatchEvent(eventTargets[0], EventType.A);397398assertNoOtherListenerIsCalled();399}400401402/**403* Unlisten/unlistenByKey should still work after disposal. There are404* many circumstances when this is actually necessary. For example, a405* user may have listened to an event target and stored the key406* (e.g. in a goog.events.EventHandler) and only unlisten after the407* target has been disposed.408*/409function testUnlistenWorksAfterDisposal() {410var key = listen(eventTargets[0], EventType.A, listeners[0]);411goog.dispose(eventTargets[0]);412unlisten(eventTargets[0], EventType.A, listeners[1]);413if (unlistenByKey) {414unlistenByKey(eventTargets[0], key);415}416}417418419function testRemovingListener() {420var ret1 = unlisten(eventTargets[0], EventType.A, listeners[0]);421listen(eventTargets[0], EventType.A, listeners[0]);422var ret2 = unlisten(eventTargets[0], EventType.A, listeners[1]);423var ret3 = unlisten(eventTargets[0], EventType.B, listeners[0]);424var ret4 = unlisten(eventTargets[1], EventType.A, listeners[0]);425426dispatchEvent(eventTargets[0], EventType.A);427assertListenerIsCalled(listeners[0], times(1));428429var ret5 = unlisten(eventTargets[0], EventType.A, listeners[0]);430var ret6 = unlisten(eventTargets[0], EventType.A, listeners[0]);431432dispatchEvent(eventTargets[0], EventType.A);433assertListenerIsCalled(listeners[0], times(1));434435assertNoOtherListenerIsCalled();436437if (unlistenReturnType ==438goog.events.eventTargetTester.UnlistenReturnType.BOOLEAN) {439assertFalse(ret1);440assertFalse(ret2);441assertFalse(ret3);442assertFalse(ret4);443assertTrue(ret5);444assertFalse(ret6);445} else {446assertUndefined(ret1);447assertUndefined(ret2);448assertUndefined(ret3);449assertUndefined(ret4);450assertUndefined(ret5);451assertUndefined(ret6);452}453}454455456function testCapture() {457eventTargets[0].setParentEventTarget(eventTargets[1]);458eventTargets[1].setParentEventTarget(eventTargets[2]);459460eventTargets[9].setParentEventTarget(eventTargets[0]);461462var ordering = 0;463listeners[0] = createListener(function(e) {464assertEquals(eventTargets[2], e.currentTarget);465assertEquals(eventTargets[0], e.target);466assertEquals('First capture listener is not called first', 0, ordering);467ordering++;468});469listeners[1] = createListener(function(e) {470assertEquals(eventTargets[1], e.currentTarget);471assertEquals(eventTargets[0], e.target);472assertEquals('2nd capture listener is not called 2nd', 1, ordering);473ordering++;474});475listeners[2] = createListener(function(e) {476assertEquals(eventTargets[0], e.currentTarget);477assertEquals(eventTargets[0], e.target);478assertEquals('3rd capture listener is not called 3rd', 2, ordering);479ordering++;480});481482listen(eventTargets[2], EventType.A, listeners[0], true);483listen(eventTargets[1], EventType.A, listeners[1], true);484listen(eventTargets[0], EventType.A, listeners[2], true);485486// These should not be called.487listen(eventTargets[3], EventType.A, listeners[3], true);488489listen(eventTargets[0], EventType.B, listeners[4], true);490listen(eventTargets[0], EventType.C, listeners[5], true);491listen(eventTargets[1], EventType.B, listeners[6], true);492listen(eventTargets[1], EventType.C, listeners[7], true);493listen(eventTargets[2], EventType.B, listeners[8], true);494listen(eventTargets[2], EventType.C, listeners[9], true);495496dispatchEvent(eventTargets[0], EventType.A);497assertListenerIsCalled(listeners[0], times(1));498assertListenerIsCalled(listeners[1], times(1));499assertListenerIsCalled(listeners[2], times(1));500assertNoOtherListenerIsCalled();501}502503504function testBubble() {505eventTargets[0].setParentEventTarget(eventTargets[1]);506eventTargets[1].setParentEventTarget(eventTargets[2]);507508eventTargets[9].setParentEventTarget(eventTargets[0]);509510var ordering = 0;511listeners[0] = createListener(function(e) {512assertEquals(eventTargets[0], e.currentTarget);513assertEquals(eventTargets[0], e.target);514assertEquals('First bubble listener is not called first', 0, ordering);515ordering++;516});517listeners[1] = createListener(function(e) {518assertEquals(eventTargets[1], e.currentTarget);519assertEquals(eventTargets[0], e.target);520assertEquals('2nd bubble listener is not called 2nd', 1, ordering);521ordering++;522});523listeners[2] = createListener(function(e) {524assertEquals(eventTargets[2], e.currentTarget);525assertEquals(eventTargets[0], e.target);526assertEquals('3rd bubble listener is not called 3rd', 2, ordering);527ordering++;528});529530listen(eventTargets[0], EventType.A, listeners[0]);531listen(eventTargets[1], EventType.A, listeners[1]);532listen(eventTargets[2], EventType.A, listeners[2]);533534// These should not be called.535listen(eventTargets[3], EventType.A, listeners[3]);536537listen(eventTargets[0], EventType.B, listeners[4]);538listen(eventTargets[0], EventType.C, listeners[5]);539listen(eventTargets[1], EventType.B, listeners[6]);540listen(eventTargets[1], EventType.C, listeners[7]);541listen(eventTargets[2], EventType.B, listeners[8]);542listen(eventTargets[2], EventType.C, listeners[9]);543544dispatchEvent(eventTargets[0], EventType.A);545assertListenerIsCalled(listeners[0], times(1));546assertListenerIsCalled(listeners[1], times(1));547assertListenerIsCalled(listeners[2], times(1));548assertNoOtherListenerIsCalled();549}550551552function testCaptureAndBubble() {553eventTargets[0].setParentEventTarget(eventTargets[1]);554eventTargets[1].setParentEventTarget(eventTargets[2]);555556listen(eventTargets[0], EventType.A, listeners[0], true);557listen(eventTargets[1], EventType.A, listeners[1], true);558listen(eventTargets[2], EventType.A, listeners[2], true);559560listen(eventTargets[0], EventType.A, listeners[3]);561listen(eventTargets[1], EventType.A, listeners[4]);562listen(eventTargets[2], EventType.A, listeners[5]);563564dispatchEvent(eventTargets[0], EventType.A);565assertListenerIsCalled(listeners[0], times(1));566assertListenerIsCalled(listeners[1], times(1));567assertListenerIsCalled(listeners[2], times(1));568assertListenerIsCalled(listeners[3], times(1));569assertListenerIsCalled(listeners[4], times(1));570assertListenerIsCalled(listeners[5], times(1));571assertNoOtherListenerIsCalled();572}573574575function testPreventDefaultByReturningFalse() {576listeners[0] = createListener(function(e) { return false; });577listeners[1] = createListener(function(e) { return true; });578listen(eventTargets[0], EventType.A, listeners[0]);579listen(eventTargets[0], EventType.A, listeners[1]);580581var result = dispatchEvent(eventTargets[0], EventType.A);582assertFalse(result);583}584585586function testPreventDefault() {587listeners[0] = createListener(function(e) { e.preventDefault(); });588listeners[1] = createListener(function(e) { return true; });589listen(eventTargets[0], EventType.A, listeners[0]);590listen(eventTargets[0], EventType.A, listeners[1]);591592var result = dispatchEvent(eventTargets[0], EventType.A);593assertFalse(result);594}595596597function testPreventDefaultAtCapture() {598listeners[0] = createListener(function(e) { e.preventDefault(); });599listeners[1] = createListener(function(e) { return true; });600listen(eventTargets[0], EventType.A, listeners[0], true);601listen(eventTargets[0], EventType.A, listeners[1], true);602603var result = dispatchEvent(eventTargets[0], EventType.A);604assertFalse(result);605}606607608function testStopPropagation() {609eventTargets[0].setParentEventTarget(eventTargets[1]);610eventTargets[1].setParentEventTarget(eventTargets[2]);611612listeners[0] = createListener(function(e) { e.stopPropagation(); });613listen(eventTargets[0], EventType.A, listeners[0]);614listen(eventTargets[0], EventType.A, listeners[1]);615listen(eventTargets[1], EventType.A, listeners[2]);616listen(eventTargets[2], EventType.A, listeners[3]);617618dispatchEvent(eventTargets[0], EventType.A);619620assertListenerIsCalled(listeners[0], times(1));621assertListenerIsCalled(listeners[1], times(1));622assertNoOtherListenerIsCalled();623}624625626function testStopPropagation2() {627eventTargets[0].setParentEventTarget(eventTargets[1]);628eventTargets[1].setParentEventTarget(eventTargets[2]);629630listeners[1] = createListener(function(e) { e.stopPropagation(); });631listen(eventTargets[0], EventType.A, listeners[0]);632listen(eventTargets[0], EventType.A, listeners[1]);633listen(eventTargets[1], EventType.A, listeners[2]);634listen(eventTargets[2], EventType.A, listeners[3]);635636dispatchEvent(eventTargets[0], EventType.A);637638assertListenerIsCalled(listeners[0], times(1));639assertListenerIsCalled(listeners[1], times(1));640assertNoOtherListenerIsCalled();641}642643644function testStopPropagation3() {645eventTargets[0].setParentEventTarget(eventTargets[1]);646eventTargets[1].setParentEventTarget(eventTargets[2]);647648listeners[2] = createListener(function(e) { e.stopPropagation(); });649listen(eventTargets[0], EventType.A, listeners[0]);650listen(eventTargets[0], EventType.A, listeners[1]);651listen(eventTargets[1], EventType.A, listeners[2]);652listen(eventTargets[2], EventType.A, listeners[3]);653654dispatchEvent(eventTargets[0], EventType.A);655656assertListenerIsCalled(listeners[0], times(1));657assertListenerIsCalled(listeners[1], times(1));658assertListenerIsCalled(listeners[2], times(1));659assertNoOtherListenerIsCalled();660}661662663function testStopPropagationAtCapture() {664eventTargets[0].setParentEventTarget(eventTargets[1]);665eventTargets[1].setParentEventTarget(eventTargets[2]);666667listeners[0] = createListener(function(e) { e.stopPropagation(); });668listen(eventTargets[2], EventType.A, listeners[0], true);669listen(eventTargets[1], EventType.A, listeners[1], true);670listen(eventTargets[0], EventType.A, listeners[2], true);671listen(eventTargets[0], EventType.A, listeners[3]);672listen(eventTargets[1], EventType.A, listeners[4]);673listen(eventTargets[2], EventType.A, listeners[5]);674675dispatchEvent(eventTargets[0], EventType.A);676677assertListenerIsCalled(listeners[0], times(1));678assertNoOtherListenerIsCalled();679}680681682function testHandleEvent() {683if (!objectTypeListenerSupported) {684return;685}686687var obj = {};688obj.handleEvent = goog.testing.recordFunction();689690listen(eventTargets[0], EventType.A, obj);691dispatchEvent(eventTargets[0], EventType.A);692693assertEquals(1, obj.handleEvent.getCallCount());694}695696697function testListenOnce() {698if (!listenOnce) {699return;700}701702listenOnce(eventTargets[0], EventType.A, listeners[0], true);703listenOnce(eventTargets[0], EventType.A, listeners[1]);704listenOnce(eventTargets[0], EventType.B, listeners[2]);705706dispatchEvent(eventTargets[0], EventType.A);707708assertListenerIsCalled(listeners[0], times(1));709assertListenerIsCalled(listeners[1], times(1));710assertListenerIsCalled(listeners[2], times(0));711assertNoOtherListenerIsCalled();712resetListeners();713714dispatchEvent(eventTargets[0], EventType.A);715716assertListenerIsCalled(listeners[0], times(0));717assertListenerIsCalled(listeners[1], times(0));718assertListenerIsCalled(listeners[2], times(0));719720dispatchEvent(eventTargets[0], EventType.B);721assertListenerIsCalled(listeners[2], times(1));722assertNoOtherListenerIsCalled();723}724725726function testUnlistenInListen() {727listeners[1] = createListener(function(e) {728unlisten(eventTargets[0], EventType.A, listeners[1]);729unlisten(eventTargets[0], EventType.A, listeners[2]);730});731listen(eventTargets[0], EventType.A, listeners[0]);732listen(eventTargets[0], EventType.A, listeners[1]);733listen(eventTargets[0], EventType.A, listeners[2]);734listen(eventTargets[0], EventType.A, listeners[3]);735736dispatchEvent(eventTargets[0], EventType.A);737738assertListenerIsCalled(listeners[0], times(1));739assertListenerIsCalled(listeners[1], times(1));740assertListenerIsCalled(listeners[2], times(0));741assertListenerIsCalled(listeners[3], times(1));742assertNoOtherListenerIsCalled();743resetListeners();744745dispatchEvent(eventTargets[0], EventType.A);746assertListenerIsCalled(listeners[0], times(1));747assertListenerIsCalled(listeners[1], times(0));748assertListenerIsCalled(listeners[2], times(0));749assertListenerIsCalled(listeners[3], times(1));750assertNoOtherListenerIsCalled();751}752753754function testUnlistenByKeyInListen() {755if (!unlistenByKey) {756return;757}758759var key1, key2;760listeners[1] = createListener(function(e) {761unlistenByKey(eventTargets[0], key1);762unlistenByKey(eventTargets[0], key2);763});764listen(eventTargets[0], EventType.A, listeners[0]);765key1 = listen(eventTargets[0], EventType.A, listeners[1]);766key2 = listen(eventTargets[0], EventType.A, listeners[2]);767listen(eventTargets[0], EventType.A, listeners[3]);768769dispatchEvent(eventTargets[0], EventType.A);770771assertListenerIsCalled(listeners[0], times(1));772assertListenerIsCalled(listeners[1], times(1));773assertListenerIsCalled(listeners[2], times(0));774assertListenerIsCalled(listeners[3], times(1));775assertNoOtherListenerIsCalled();776resetListeners();777778dispatchEvent(eventTargets[0], EventType.A);779assertListenerIsCalled(listeners[0], times(1));780assertListenerIsCalled(listeners[1], times(0));781assertListenerIsCalled(listeners[2], times(0));782assertListenerIsCalled(listeners[3], times(1));783assertNoOtherListenerIsCalled();784}785786787function testSetParentEventTarget() {788assertNull(eventTargets[0].getParentEventTarget());789790eventTargets[0].setParentEventTarget(eventTargets[1]);791assertEquals(eventTargets[1], eventTargets[0].getParentEventTarget());792assertNull(eventTargets[1].getParentEventTarget());793794eventTargets[0].setParentEventTarget(null);795assertNull(eventTargets[0].getParentEventTarget());796}797798799function testListenOnceAfterListenDoesNotChangeExistingListener() {800if (!listenOnce) {801return;802}803804listen(eventTargets[0], EventType.A, listeners[0]);805listenOnce(eventTargets[0], EventType.A, listeners[0]);806807dispatchEvent(eventTargets[0], EventType.A);808dispatchEvent(eventTargets[0], EventType.A);809dispatchEvent(eventTargets[0], EventType.A);810811assertListenerIsCalled(listeners[0], times(3));812assertNoOtherListenerIsCalled();813}814815816function testListenOnceAfterListenOnceDoesNotChangeExistingListener() {817if (!listenOnce) {818return;819}820821listenOnce(eventTargets[0], EventType.A, listeners[0]);822listenOnce(eventTargets[0], EventType.A, listeners[0]);823824dispatchEvent(eventTargets[0], EventType.A);825dispatchEvent(eventTargets[0], EventType.A);826dispatchEvent(eventTargets[0], EventType.A);827828assertListenerIsCalled(listeners[0], times(1));829assertNoOtherListenerIsCalled();830}831832833function testListenAfterListenOnceRemoveOnceness() {834if (!listenOnce) {835return;836}837838listenOnce(eventTargets[0], EventType.A, listeners[0]);839listen(eventTargets[0], EventType.A, listeners[0]);840841dispatchEvent(eventTargets[0], EventType.A);842dispatchEvent(eventTargets[0], EventType.A);843dispatchEvent(eventTargets[0], EventType.A);844845assertListenerIsCalled(listeners[0], times(3));846assertNoOtherListenerIsCalled();847}848849850function testUnlistenAfterListenOnce() {851if (!listenOnce) {852return;853}854855listenOnce(eventTargets[0], EventType.A, listeners[0]);856unlisten(eventTargets[0], EventType.A, listeners[0]);857dispatchEvent(eventTargets[0], EventType.A);858859listen(eventTargets[0], EventType.A, listeners[0]);860listenOnce(eventTargets[0], EventType.A, listeners[0]);861unlisten(eventTargets[0], EventType.A, listeners[0]);862dispatchEvent(eventTargets[0], EventType.A);863864listenOnce(eventTargets[0], EventType.A, listeners[0]);865listen(eventTargets[0], EventType.A, listeners[0]);866unlisten(eventTargets[0], EventType.A, listeners[0]);867dispatchEvent(eventTargets[0], EventType.A);868869listenOnce(eventTargets[0], EventType.A, listeners[0]);870listenOnce(eventTargets[0], EventType.A, listeners[0]);871unlisten(eventTargets[0], EventType.A, listeners[0]);872dispatchEvent(eventTargets[0], EventType.A);873874assertNoOtherListenerIsCalled();875}876877878function testRemoveAllWithType() {879if (!removeAll) {880return;881}882883listen(eventTargets[0], EventType.A, listeners[0], true);884listen(eventTargets[0], EventType.A, listeners[1]);885listen(eventTargets[0], EventType.C, listeners[2], true);886listen(eventTargets[0], EventType.C, listeners[3]);887listen(eventTargets[0], EventType.B, listeners[4], true);888listen(eventTargets[0], EventType.B, listeners[5], true);889listen(eventTargets[0], EventType.B, listeners[6]);890listen(eventTargets[0], EventType.B, listeners[7]);891892assertEquals(4, removeAll(eventTargets[0], EventType.B));893894dispatchEvent(eventTargets[0], EventType.A);895dispatchEvent(eventTargets[0], EventType.B);896dispatchEvent(eventTargets[0], EventType.C);897898assertListenerIsCalled(listeners[0], times(1));899assertListenerIsCalled(listeners[1], times(1));900assertListenerIsCalled(listeners[2], times(1));901assertListenerIsCalled(listeners[3], times(1));902assertNoOtherListenerIsCalled();903}904905906function testRemoveAll() {907if (!removeAll) {908return;909}910911listen(eventTargets[0], EventType.A, listeners[0], true);912listen(eventTargets[0], EventType.A, listeners[1]);913listen(eventTargets[0], EventType.C, listeners[2], true);914listen(eventTargets[0], EventType.C, listeners[3]);915listen(eventTargets[0], EventType.B, listeners[4], true);916listen(eventTargets[0], EventType.B, listeners[5], true);917listen(eventTargets[0], EventType.B, listeners[6]);918listen(eventTargets[0], EventType.B, listeners[7]);919920assertEquals(8, removeAll(eventTargets[0]));921922dispatchEvent(eventTargets[0], EventType.A);923dispatchEvent(eventTargets[0], EventType.B);924dispatchEvent(eventTargets[0], EventType.C);925926assertNoOtherListenerIsCalled();927}928929930function testRemoveAllCallsMarkAsRemoved() {931if (!removeAll) {932return;933}934935var key0 = listen(eventTargets[0], EventType.A, listeners[0]);936var key1 = listen(eventTargets[1], EventType.A, listeners[1]);937938assertNotNullNorUndefined(key0.listener);939assertFalse(key0.removed);940assertNotNullNorUndefined(key1.listener);941assertFalse(key1.removed);942943assertEquals(1, removeAll(eventTargets[0]));944assertNull(key0.listener);945assertTrue(key0.removed);946assertNotNullNorUndefined(key1.listener);947assertFalse(key1.removed);948949assertEquals(1, removeAll(eventTargets[1]));950assertNull(key1.listener);951assertTrue(key1.removed);952}953954955function testGetListeners() {956if (!getListeners) {957return;958}959960listen(eventTargets[0], EventType.A, listeners[0], true);961listen(eventTargets[0], EventType.A, listeners[1], true);962listen(eventTargets[0], EventType.A, listeners[2]);963listen(eventTargets[0], EventType.A, listeners[3]);964965var l = getListeners(eventTargets[0], EventType.A, true);966assertEquals(2, l.length);967assertEquals(listeners[0], l[0].listener);968assertEquals(listeners[1], l[1].listener);969970l = getListeners(eventTargets[0], EventType.A, false);971assertEquals(2, l.length);972assertEquals(listeners[2], l[0].listener);973assertEquals(listeners[3], l[1].listener);974975l = getListeners(eventTargets[0], EventType.B, true);976assertEquals(0, l.length);977}978979980function testGetListener() {981if (!getListener) {982return;983}984985listen(eventTargets[0], EventType.A, listeners[0], true);986987assertNotNull(getListener(eventTargets[0], EventType.A, listeners[0], true));988assertNull(getListener(eventTargets[0], EventType.A, listeners[0], true, {}));989assertNull(getListener(eventTargets[1], EventType.A, listeners[0], true));990assertNull(getListener(eventTargets[0], EventType.B, listeners[0], true));991assertNull(getListener(eventTargets[0], EventType.A, listeners[1], true));992}993994995function testHasListener() {996if (!hasListener) {997return;998}9991000assertFalse(hasListener(eventTargets[0]));10011002listen(eventTargets[0], EventType.A, listeners[0], true);10031004assertTrue(hasListener(eventTargets[0]));1005assertTrue(hasListener(eventTargets[0], EventType.A));1006assertTrue(hasListener(eventTargets[0], EventType.A, true));1007assertTrue(hasListener(eventTargets[0], undefined, true));1008assertFalse(hasListener(eventTargets[0], EventType.A, false));1009assertFalse(hasListener(eventTargets[0], undefined, false));1010assertFalse(hasListener(eventTargets[0], EventType.B));1011assertFalse(hasListener(eventTargets[0], EventType.B, true));1012assertFalse(hasListener(eventTargets[1]));1013}101410151016function testFiringEventBeforeDisposeInternalWorks() {1017/**1018* @extends {goog.events.EventTarget}1019* @constructor1020* @final1021*/1022var MockTarget = function() { MockTarget.base(this, 'constructor'); };1023goog.inherits(MockTarget, goog.events.EventTarget);10241025MockTarget.prototype.disposeInternal = function() {1026dispatchEvent(this, EventType.A);1027MockTarget.base(this, 'disposeInternal');1028};10291030var t = new MockTarget();1031try {1032listen(t, EventType.A, listeners[0]);1033t.dispose();1034assertListenerIsCalled(listeners[0], times(1));1035} catch (e) {1036goog.dispose(t);1037}1038}103910401041function testLoopDetection() {1042var target = listenableFactory();1043target.setParentEventTarget(target);10441045try {1046target.dispatchEvent('string');1047fail('expected error');1048} catch (e) {1049assertContains('infinite', e.message);1050}1051}105210531054