Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / test / unit / spec / EventManager.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 describe("Ext.EventManager", function() {
16     var element,
17         elementWithId,
18         elementWithoutId;
19     
20     beforeEach(function() {
21         // add global variable in whitelist
22         addGlobal("id");
23         addGlobal("ExtBox1");
24         element = document.body;
25         
26         elementWithId = document.createElement("DIV");
27         elementWithId.id = 'element-with-id';
28         element.appendChild(elementWithId);
29         
30         elementWithoutId = document.createElement("DIV");
31         element.appendChild(elementWithoutId);
32     });
33     
34     afterEach(function() {
35         var el = Ext.get(elementWithId);
36         if (el) {
37             el.remove();
38         }
39         el = Ext.get(elementWithoutId);
40         if (el) {
41             el.remove();
42         }
43     });
44     
45     describe("event binding", function() {
46         describe("getId", function() {
47             describe("if element has an id", function() {
48                 it("should return element id", function() {
49                     expect(elementWithId.id).toBe(Ext.EventManager.getId(elementWithId));
50                 });
51             });
52             
53             describe("if element hasn't an id", function() {
54                 var id, result;
55                 beforeEach(function() {
56                     id = 'nf-42';
57                     spyOn(Ext, "id").andCallFake(function(dom) {
58                         return (dom.id = id);
59                     });
60                     result = Ext.EventManager.getId(elementWithoutId);
61                 });
62                 
63
64                 it("should add an id to element with Ext.id", function() {
65                     expect(elementWithoutId.id).toBe(id);
66                 });
67                 
68                 it("should return the element id", function() {
69                     expect(result).toBe(id);
70                 });
71                 
72                 it("should add element to Ext.cache", function() {
73                    expect(Ext.cache[id].el.dom).toBe(elementWithoutId);
74                 });
75             });
76             
77             describe("document and window", function() {
78                 describe("document", function() {
79                     var result;
80                     beforeEach(function() {
81                         result = Ext.EventManager.getId(document);
82                     });
83                     
84                     afterEach(function() {
85                         delete Ext.cache[Ext.documentId];
86                     });
87                     it("should add document Ext.Element to cache", function() {
88                         expect(Ext.cache[Ext.documentId].el.dom).toBe(document);
89                     });
90                     
91                     it("should enable skipGarbageCollection flag", function() {
92                         expect(Ext.cache[Ext.documentId].skipGarbageCollection).toBe(true);
93                     });
94                     
95                     it("should return Ext.documentId", function() {
96                         expect(result).toBe(Ext.documentId);
97                     });
98                 });
99                 
100                 describe("window", function() {
101                     var result;
102                     beforeEach(function() {
103                         result = Ext.EventManager.getId(window);
104                     });
105                     
106                     afterEach(function() {
107                         delete Ext.cache[Ext.windowId];
108                     });
109                     it("should add window Ext.Element to cache", function() {
110                         expect(Ext.cache[Ext.windowId].el.dom).toBe(window);
111                     });
112                     
113                     it("should enable skipGarbageCollection flag", function() {
114                         expect(Ext.cache[Ext.windowId].skipGarbageCollection).toBe(true);
115                     });
116                     
117                     it("should return Ext.windowId", function() {
118                         expect(result).toBe(Ext.windowId);
119                     });
120                 });
121             });
122         });
123         
124         describe("prepareListenerConfig", function() {
125             var config, configWithFn;
126             
127             beforeEach(function() {
128                 config = {
129                     click: Ext.emptyFn,
130                     scope: fakeScope
131                 };
132                 
133                 configWithFn = {
134                     click: {
135                        fn: Ext.emptyFn, 
136                        scope: fakeScope
137                     }
138                 };
139                 spyOn(Ext.EventManager, "removeListener");
140                 spyOn(Ext.EventManager, "addListener");
141             });
142             
143             describe("if remove", function() {
144                 describe("with an object like click: function(){}, scope: this", function() {
145                     it("should call removeListener", function() {
146                         Ext.EventManager.prepareListenerConfig(element, config, true);
147                         expect(Ext.EventManager.removeListener).toHaveBeenCalledWith(element, 'click', Ext.emptyFn, fakeScope, config);
148                     });
149                 });
150                 
151                 describe("with an object like click: {fn: function(){}, scope: this}", function() {
152                     it("should call removeListener", function() {
153                         Ext.EventManager.prepareListenerConfig(element, configWithFn, true);
154                         expect(Ext.EventManager.removeListener).toHaveBeenCalledWith(element, 'click', Ext.emptyFn, fakeScope, configWithFn.click);
155                     });                    
156                 });
157             });
158             
159             describe("if add", function() {
160                 describe("with an object like click: function(){}, scope: this", function() {
161                     it("should call addListener", function() {
162                         Ext.EventManager.prepareListenerConfig(element, config);
163                         expect(Ext.EventManager.addListener).toHaveBeenCalledWith(element, 'click', Ext.emptyFn, fakeScope, config);
164                     });
165                 });
166                 
167                 describe("with an object like click: {fn: function(){}, scope: this}", function() {
168                     it("should call addListener", function() {
169                         Ext.EventManager.prepareListenerConfig(element, configWithFn);
170                         expect(Ext.EventManager.addListener).toHaveBeenCalledWith(element, 'click', Ext.emptyFn, fakeScope, configWithFn.click);
171                     });                    
172                 });
173             });
174         });
175         
176         describe("addListener", function() {
177             describe("if eventName is an object", function() {
178                 var eventName;
179                 
180                 beforeEach(function() {
181                     eventName = {};    
182                 });
183                 
184                 it("should call prepareListenerConfig", function() {
185                     spyOn(Ext.EventManager, "prepareListenerConfig");
186                     Ext.EventManager.addListener(element, eventName);
187                     expect(Ext.EventManager.prepareListenerConfig).toHaveBeenCalledWith(element, eventName);
188                 });
189                 
190                 it("should throw an error if the element doesn't exist", function() {
191                     expect(function() {
192                         Ext.EventManager.addListener(undefined, "click");
193                     }).toRaiseExtError();
194                 });
195             });
196             
197             it("should throw an error if the element doesn't exist", function() {
198                 expect(function() {
199                     Ext.EventManager.addListener(undefined, "click");
200                 }).toRaiseExtError();
201             });
202             
203             describe("event firing", function() {
204                 var config;
205    
206                 beforeEach(function() {
207                     config = {
208                         click: {
209                            fn: jasmine.createSpy(), 
210                            scope: fakeScope
211                         }
212                     };
213                     
214                     Ext.EventManager.addListener(element, config);
215                 });
216                 
217                 afterEach(function() {
218                     Ext.EventManager.removeListener(element, config);
219                 });
220                                 
221                 it("should call the listener", function() {
222                     jasmine.fireMouseEvent(element, "click", 1, 1);
223                     
224                     expect(config.click.fn).toHaveBeenCalled();
225                 });
226                 
227
228             });
229             
230             describe("options", function() {
231                 var config;
232                 
233                 afterEach(function() {
234                     Ext.EventManager.removeListener(element, config);
235                 });
236                 
237                 describe("scope", function() {
238                     it("should call the listener with the correct scope", function() {
239                         config = {
240                             click: {
241                                fn: jasmine.createSpy(), 
242                                scope: fakeScope
243                             }
244                         };     
245                         
246                         Ext.EventManager.addListener(element, config);
247
248                         jasmine.fireMouseEvent(element, "click", 1, 1);
249                         expect(config.click.fn.calls[0].object).toBe(fakeScope);                   
250                     });
251                 });
252                 
253                 describe("delegate", function() {
254                     var child;
255                     beforeEach(function() {
256                         config = {
257                             click: {
258                                fn: jasmine.createSpy(),
259                                delegate: ".something",
260                                scope: fakeScope
261                             }
262                         };
263                         
264                         child = Ext.get(element).createChild({
265                             cls: "child"
266                         }).dom;
267                     });
268                     
269                     afterEach(function() {
270                         var elChild = Ext.get(child);
271                         if (elChild) {
272                             elChild.remove();
273                         }
274                     });
275                     
276                     describe("if filter found nothing", function() {
277                         it("should not call the listener", function() {
278                             Ext.EventManager.addListener(element, config);
279                             jasmine.fireMouseEvent(child, "click", 1, 1);
280                             
281                             expect(config.click.fn).not.toHaveBeenCalled();                 
282                         });
283                     });
284                     
285                     describe("if filter found something", function() {
286                         it("should call the listener", function() {
287                             Ext.get(child).addCls("something");
288                             Ext.EventManager.addListener(element, config);
289                             jasmine.fireMouseEvent(child, "click", 1, 1);
290                             
291                             expect(config.click.fn).toHaveBeenCalled();                 
292                         });
293                     });
294                     
295                     describe("stopevent", function() {
296                         var checkbox;
297                         
298                         beforeEach(function() {
299                             config = {
300                                 click: {
301                                    fn: jasmine.createSpy(),
302                                    stopEvent: true,
303                                    scope: fakeScope
304                                 }
305                             };
306                             
307                             checkbox = Ext.get(element).createChild({
308                                 tag: "input",
309                                 type: "checkbox"
310                             }).dom;
311                                                  
312                             Ext.EventManager.addListener(element, config);
313                             Ext.EventManager.addListener(checkbox, config);
314                             if (jasmine.browser.isIE) {
315                                 checkbox.click();
316                             } else {
317                                 jasmine.fireMouseEvent(checkbox, "click", 1, 1);
318                             }
319                         });
320                         
321                         afterEach(function() {
322                             var checkBoxEl = Ext.get(checkbox);
323                             if (checkBoxEl) {
324                                 checkBoxEl.remove();
325                             }
326                             Ext.EventManager.removeListener(checkbox, config);
327                         });
328                         
329                         it("should stop propagation to parent elements", function() {
330                             expect(config.click.fn.calls.length).toEqual(1);
331                         });
332                         
333                         it("should prevent default browser handling of the event", function() {
334                             expect(checkbox.checked).toBe(false);
335                         });
336                     });
337                     
338                     describe("preventDefault", function() {
339                         var checkbox;
340                         
341                         beforeEach(function() {
342                             config = {
343                                 click: {
344                                    fn: jasmine.createSpy(),
345                                    preventDefault: true,
346                                    scope: fakeScope
347                                 }
348                             };
349                             
350                             checkbox = Ext.get(element).createChild({
351                                 tag: "input",
352                                 type: "checkbox"
353                             }).dom;
354                                                  
355                             Ext.EventManager.addListener(element, config);
356                             Ext.EventManager.addListener(checkbox, config);
357                             if (jasmine.browser.isIE) {
358                                 checkbox.click();
359                             } else {
360                                 jasmine.fireMouseEvent(checkbox, "click", 1, 1);
361                             }
362                         });
363                         
364                         afterEach(function() {
365                             var checkBoxEl = Ext.get(checkbox);
366                             if (checkBoxEl) {
367                                 checkBoxEl.remove();
368                             }
369                             Ext.EventManager.removeListener(checkbox, config);
370                         });
371                                                 
372                         it("should prevent default browser handling of the event", function() {
373                             expect(checkbox.checked).toBe(false);
374                         });  
375                         
376                         it("should not stop the propagation of the event", function() {
377                             expect(config.click.fn.calls.length).toEqual(2);
378                         });
379                     });
380                                         
381                     describe("stopPropagation", function() {
382                         var checkbox;
383                         
384                         beforeEach(function() {
385                             config = {
386                                 click: {
387                                    fn: jasmine.createSpy(),
388                                    stopPropagation: true,
389                                    scope: fakeScope
390                                 }
391                             };
392                             
393                             checkbox = Ext.getBody().createChild({
394                                 tag: "input",
395                                 type: "checkbox"
396                             }).dom;
397                                                  
398                             Ext.EventManager.addListener(element, config);
399                             Ext.EventManager.addListener(checkbox, config);
400                             if (jasmine.browser.isIE) {
401                                 checkbox.click();
402                             } else {
403                                 jasmine.fireMouseEvent(checkbox, "click", 1, 1);
404                             }
405         
406                         });
407                         
408                         afterEach(function() {
409                             var checkBoxEl = Ext.get(checkbox);
410                             if (checkBoxEl) {
411                                 checkBoxEl.remove();
412                             }
413                             Ext.EventManager.removeListener(checkbox, config);
414                         });
415                         
416                         it("should stop propagation to parent elements", function() {
417                             expect(config.click.fn.calls.length).toEqual(1);
418                         });
419                         
420                         it("should not prevent default browser handling of the event", function() {
421                             expect(checkbox.checked).toBe(true);
422                         });
423                     });
424                     
425                     describe("normalized", function() {
426                         var event;
427                         beforeEach(function() {
428                             config = {
429                                 click: {
430                                    fn: jasmine.createSpy(),
431                                    normalized: false,
432                                    scope: fakeScope
433                                 }
434                             };
435                                                  
436                             Ext.EventManager.addListener(element, config);
437
438                             event = jasmine.fireMouseEvent(element, "click", 1, 1);
439                         });
440                         
441                         it("should pass a browser event instead of an Ext.EventObject", function() {
442                             expect(config.click.fn).toHaveBeenCalledWith(event, element, config.click);
443                         });
444                     });
445                     
446                     describe("delay", function() {
447                          beforeEach(function() {
448                             config = {
449                                 click: {
450                                    fn: jasmine.createSpy(),
451                                    delay: 1,
452                                    scope: fakeScope
453                                 }
454                             };
455                                                  
456                             Ext.EventManager.addListener(element, config);
457                         });
458                         
459                         it("should not call listener before 1 ms", function() {
460                             jasmine.fireMouseEvent(element, "click", 1, 1);
461                             expect(config.click.fn).not.toHaveBeenCalled();
462                         });
463                         
464                         it("should call listener after 1 ms", function() {
465                             runs(function() {
466                                 jasmine.fireMouseEvent(element, "click", 1, 1);
467                             });
468                             
469                             waits(1);
470                             
471                             runs(function() {
472                                 expect(config.click.fn).toHaveBeenCalled();
473                             });
474                         });
475                     });
476                     
477                     describe("single", function() {
478                          beforeEach(function() {
479                             config = {
480                                 click: {
481                                    fn: jasmine.createSpy(),
482                                    single: true,
483                                    scope: fakeScope
484                                 }
485                             };
486                                                  
487                             Ext.EventManager.addListener(element, config);
488                             jasmine.fireMouseEvent(element, "click", 1, 1);
489                             jasmine.fireMouseEvent(element, "click", 1, 1);
490                         });
491                         
492                         it("should call listener only one time", function() {
493                             expect(config.click.fn.calls.length).toEqual(1);
494                         });
495                     });
496                     
497                     describe("buffer", function() {
498                         beforeEach(function() {
499                             config = {
500                                 click: {
501                                    fn: jasmine.createSpy(),
502                                    buffer: 1,
503                                    scope: fakeScope
504                                 }
505                             };
506                                                  
507                             Ext.EventManager.addListener(element, config);
508                             jasmine.fireMouseEvent(element, "click", 1, 1);
509                             jasmine.fireMouseEvent(element, "click", 1, 1);
510                         });
511                         
512                         it("should call listener only one time", function() {
513                             waits(1);
514                             runs(function() {
515                                 expect(config.click.fn.calls.length).toEqual(1);
516                             });
517                         });                       
518                     });
519                     
520                     describe("target", function() {
521                         var child;
522                         beforeEach(function() {
523                             child = Ext.get(element).createChild({
524                             }).dom;
525                             
526                             config = {
527                                 click: {
528                                    fn: jasmine.createSpy(),
529                                    target: element,
530                                    scope: fakeScope
531                                 }
532                             };
533                                                  
534                             Ext.EventManager.addListener(element, config);                            
535                         });
536                         
537                         afterEach(function() {
538                             var childEl = Ext.get(child);
539                             if (childEl) {
540                                 childEl.remove();
541                             }
542                         });
543                         
544                         it("should call listener if element event is fired", function() {
545                             jasmine.fireMouseEvent(element, "click", 1, 1);
546                             expect(config.click.fn).toHaveBeenCalled();
547                         });
548                         
549                         it("should not call listener if child event is fired (no bubbling)", function() {
550                             jasmine.fireMouseEvent(child, "click", 1, 1);
551                             expect(config.click.fn).not.toHaveBeenCalled();
552                         });
553                     });
554                 });
555             });
556         });
557         
558         describe("removeListener", function() {
559             describe("if eventName is an object", function() {
560                 it("should call prepareListenerConfig", function() {
561                     var eventName = {};
562                     spyOn(Ext.EventManager, "prepareListenerConfig");
563                     Ext.EventManager.removeListener(element, eventName);
564                     expect(Ext.EventManager.prepareListenerConfig).toHaveBeenCalledWith(element, eventName, true);
565                 });
566             });            
567             
568             describe("event firing", function() {
569                 var config;
570    
571                 beforeEach(function() {
572                     config = {
573                         click: {
574                            fn: jasmine.createSpy(), 
575                            scope: fakeScope
576                         }
577                     };
578                     
579                     Ext.EventManager.addListener(element, config);
580                     Ext.EventManager.removeListener(element, config);
581                 });
582                 
583                 it("should not call the listener", function() {
584                     jasmine.fireMouseEvent(element, "click", 1, 1);
585                     
586                     expect(config.click.fn).not.toHaveBeenCalled();
587                 });
588             });
589         });
590     
591         describe("removeAll", function() {
592             var config;
593
594             beforeEach(function() {
595                 config = {
596                     click: {
597                        fn: jasmine.createSpy(), 
598                        scope: fakeScope
599                     },
600                     mouseover: {
601                         fn: jasmine.createSpy(),
602                         scope: fakeScope
603                     }
604                 };
605                 
606                 Ext.EventManager.addListener(element, config);
607                 Ext.EventManager.removeAll(element, config);
608             });
609             
610             it("should should not call click listener", function() {
611                 jasmine.fireMouseEvent(element, "click", 1, 1);
612                 
613                 expect(config.click.fn).not.toHaveBeenCalled();
614             });
615             
616             it("should not call mouseover listener", function() {
617                 jasmine.fireMouseEvent(element, "mouseover", 1, 1);
618                 
619                 expect(config.mouseover.fn).not.toHaveBeenCalled();
620             });
621         });
622         
623         describe("purgeElement", function() {
624             var child, config;
625             
626             beforeEach(function() {
627                 child = Ext.get(element).createChild({
628                     cls: "child"
629                 }).dom;
630                 
631                 config = {
632                     mouseover: {
633                         fn: jasmine.createSpy(),
634                         scope: fakeScope
635                     }
636                 };  
637                               
638                 Ext.EventManager.addListener(element, config);
639                 Ext.EventManager.addListener(child, config);
640                 Ext.EventManager.purgeElement(element);
641             });
642             
643             afterEach(function() {
644                 var childEl = Ext.get(child);
645                 if (childEl) {
646                     childEl.remove();
647                 }
648             });
649             
650             it("should remove all listeners from element", function() {
651                 jasmine.fireMouseEvent(element, "mouseover", 1, 1);
652
653                 expect(config.mouseover.fn).not.toHaveBeenCalled();                
654             });
655             
656             it("should remove all listeners from element children", function() {
657                 jasmine.fireMouseEvent(child, "mouseover", 1, 1);
658                                
659                 expect(config.mouseover.fn).not.toHaveBeenCalled(); 
660             });
661         });
662         
663         describe("methods alias", function() {
664             it("should alias addListener with on", function() {
665                 expect(Ext.EventManager.on).toBe(Ext.EventManager.addListener);
666             });
667             
668             it("should alias removeListener with un", function() {
669                 expect(Ext.EventManager.un).toBe(Ext.EventManager.removeListener);
670             });
671         });
672     });
673 });
674