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