Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / core / test / unit / spec / dom / Element.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.Element", function() {
16     var domEl,
17         element;
18         
19     afterEach(function() {
20         if (element) {
21             element.remove();
22         }
23
24         if (domEl && domEl.parentNode === document.body) {
25             document.body.removeChild(domEl);
26         }
27     });
28     
29     describe("instantiation", function() {
30         beforeEach(function() {
31             domEl = document.createElement("div");
32             Ext.getBody().appendChild(domEl);
33         });
34         
35
36         
37         it("should set dom element id if it hasn't already one", function() {
38             element = new Ext.Element(domEl);
39
40             expect(domEl.id).toBeDefined();
41         });
42
43         it("should not set dom element id if it has already one", function() {
44             var id = Ext.id();
45
46             domEl.id = id;
47             element = new Ext.Element(domEl);
48
49             expect(domEl.id).toEqual(id);
50         });
51
52         it("should set dom property to dom element", function() {
53             element = new Ext.Element(domEl);
54
55             expect(element.dom).toBe(domEl);
56         });
57
58         it("should set id property to dom id", function() {
59             var id = Ext.id();
60
61             domEl.id = id;
62             element = new Ext.Element(domEl);
63
64             expect(element.id).toEqual(id);
65         });
66
67         it("should not set dom or id property if first argument is undefined", function() {
68             element = new Ext.Element();
69
70             expect(element.id).toBeUndefined();
71             expect(element.dom).toBeUndefined();
72         });
73
74         it("should find a dom element if a string corresponding to it's id is passed as first argument", function() {
75             var id = Ext.id();
76
77             domEl.id = id;
78
79             element = new Ext.Element(id);
80
81             expect(element.dom).toBe(domEl);
82         });
83     });
84
85     describe("methods", function() {
86         beforeEach(function() {
87             element = Ext.getBody().createChild({tag: "div"});
88             domEl = element.dom;
89         });
90
91         describe("set", function() {
92             it("should call Ext.DomHelper.applyStyles if object passed as first argument has style property", function() {
93                 var style = {width:'100px'};
94
95                 spyOn(Ext.DomHelper, "applyStyles");
96
97                 element.set({style: style});
98
99                 expect(Ext.DomHelper.applyStyles).toHaveBeenCalledWith(element.dom, style);
100             });
101
102             it("should set dom element className if object passed as first argument has cls property", function() {
103                 var cls = "x-test-class";
104
105                 element.set({cls: cls});
106
107                 expect(element.dom.className).toEqual(cls);
108             });
109
110             it("should use setAttribute by default", function() {
111                 spyOn(element.dom, "setAttribute");
112
113                 element.set({align: "center"});
114
115                 expect(element.dom.setAttribute).toHaveBeenCalledWith("align", "center");
116             });
117
118             it("should be able to use expandos", function() {
119                 spyOn(element.dom, "setAttribute");
120
121                 element.set({align: "center"}, false);
122
123
124                 expect(element.dom.align).toEqual("center");
125             });
126
127         });
128
129         describe("is", function() {
130             it("Returns true if this element matches the passed simple selector", function() {
131                 element.set({cls: "x-test-class"});
132
133                 expect(element.is("div.x-test-class")).toBe(true);
134             });
135         });
136
137         describe("focus", function() {
138             it("should focus dom element", function() {
139                 spyOn(element.dom, "focus");
140
141                 element.focus();
142
143                 expect(element.dom.focus).toHaveBeenCalled();
144             });
145
146             it("should be able to defer dom element focus", function() {
147                 spyOn(element.dom, "focus");
148                 element.focus(1);
149
150                 waitsFor(function(){
151                     return element.dom.focus.calls.length === 1;
152                 }, "element.dom.focus was never called");
153
154                 runs(function() {
155                     expect(element.dom.focus).toHaveBeenCalled();
156                 });
157             });
158
159             it("should ignore any exception", function() {
160                 element.dom.focus = function() {
161                     throw "error";
162                 };
163
164                 expect(element.focus).not.toThrow("error");
165             });
166         });
167
168         describe("blur", function() {
169             it("should blur dom element", function() {
170                 spyOn(element.dom, "blur");
171
172                 element.blur();
173
174                 expect(element.dom.blur).toHaveBeenCalled();
175             });
176
177
178             it("should ignore any exception", function() {
179                 element.dom.blur = function() {
180                     throw "error";
181                 };
182
183                 expect(element.blur).not.toThrow("error");
184             });
185         });
186
187         describe("getValue", function() {
188             beforeEach(function() {
189                 element.dom.value = "10";
190             });
191
192             it("should return the dom value", function() {
193                 expect(element.getValue()).toEqual("10");
194             });
195
196             it("should return the dom value as Number", function() {
197                 expect(element.getValue(true)).toEqual(10);
198             });
199         });
200
201         describe("listeners", function() {
202             var options;
203
204             beforeEach(function() {
205                 options = {delay: 10};
206             });
207
208             describe("addListener", function() {
209                 it("should call Ext.EventManager.on", function() {
210                     spyOn(Ext.EventManager, "on");
211
212                     element.addListener("click", Ext.emptyFn, fakeScope, options);
213
214                     expect(Ext.EventManager.on).toHaveBeenCalledWith(element.dom, "click", Ext.emptyFn, fakeScope, options);
215                 });
216             });
217
218             describe("removeListener", function() {
219                 it("should call Ext.EventManager.un", function() {
220                     spyOn(Ext.EventManager, "un");
221
222                     element.removeListener("click", Ext.emptyFn, fakeScope);
223
224                     expect(Ext.EventManager.un).toHaveBeenCalledWith(element.dom, "click", Ext.emptyFn, fakeScope);
225                 });
226             });
227
228             describe("removeAllListener", function() {
229                 it("should call Ext.EventManager.removeAll", function() {
230                     spyOn(Ext.EventManager, "removeAll");
231
232                     element.removeAllListeners();
233
234                     expect(Ext.EventManager.removeAll).toHaveBeenCalledWith(element.dom);
235                 });
236             });
237
238             describe("purgeAllListener", function() {
239                 it("should call Ext.EventManager.purgeElement", function() {
240                     spyOn(Ext.EventManager, "purgeElement");
241
242                     element.purgeAllListeners();
243
244                     expect(Ext.EventManager.purgeElement).toHaveBeenCalledWith(element);
245                 });
246             });
247         });
248         
249         describe("addUnits", function() {
250             it("should return an empty string if size passed is an empty string", function() {
251                 expect(element.addUnits("")).toEqual("");
252             });
253
254             it("should return auto if size passed is 'auto' string", function() {
255                 expect(element.addUnits("auto")).toEqual("auto");
256             });
257
258             it("should return an empty string if size passed is undefined", function() {
259                 expect(element.addUnits(undefined)).toEqual("");
260             });
261
262             it("should return an empty string if size passed is null", function() {
263                 expect(element.addUnits(null)).toEqual("");
264             });
265         });
266
267         describe("remove", function() {
268             beforeEach(function() {
269                 spyOn(Ext, "removeNode").andCallThrough();
270                 element.remove();
271             });
272
273             it("should remove dom property", function() {
274                 expect(element.dom).toBeUndefined();
275             });
276
277             it("should call Ext.removeNode", function() {
278                 expect(Ext.removeNode).toHaveBeenCalledWith(domEl);
279             });
280         });
281
282         describe("hover", function() {
283             var overFn, outFn, options;
284             beforeEach(function() {
285                 overFn = function() {
286                     return 1;
287                 };
288
289                 outFn = function() {
290                     return 2;
291                 };
292
293                 options = {
294                     foo: true
295                 };
296
297                 spyOn(element, "on");
298             });
299
300             describe("mouseenter event", function() {
301                 it("should add a listener on mouseenter", function() {
302                     element.hover(overFn, outFn, fakeScope, options);
303
304                     expect(element.on).toHaveBeenCalledWith("mouseenter", overFn, fakeScope, options);
305                 });
306
307                 it("should set scope to element.dom if it is not passed in arguments", function() {
308                     element.hover(overFn, outFn, null, options);
309
310                     expect(element.on).toHaveBeenCalledWith("mouseenter", overFn, element.dom, options);
311                 });
312             });
313
314             describe("mouseleave event", function() {
315                 it("should add a listener on mouseleave", function() {
316                     element.hover(overFn, outFn, fakeScope, options);
317
318                     expect(element.on).toHaveBeenCalledWith("mouseleave", outFn, fakeScope, options);
319                 });
320
321                 it("should set scope to element.dom if it is not passed in arguments", function() {
322                     element.hover(overFn, outFn, null, options);
323
324                     expect(element.on).toHaveBeenCalledWith("mouseleave", outFn, element.dom, options);
325                 });
326             });
327         });
328
329         describe("contains", function() {
330             /*
331              * TODO: Removed tests for now, need to reinstate once the refactoring is done.
332              */
333         });
334
335         describe("getAttributeNs", function() {
336             it("should call element getAttribute", function() {
337                 spyOn(element, "getAttribute");
338
339                 element.getAttributeNS("ns1", "align");
340
341                 expect(element.getAttribute).toHaveBeenCalledWith("align", "ns1");
342             });
343         });
344
345         describe("getAttribute", function() {
346             var element2, element3;
347             beforeEach(function() {
348                 element2 = Ext.getBody().createChild({tag: "div"});
349                 
350
351                 if (element.dom.setAttribute) {
352                     element.dom.setAttribute("qtip", "bar");
353                     element2.dom.setAttribute("ext:qtip", "foo");
354                 } else {
355                     element.dom["qtip"] = "bar";
356                     element2.dom["ext:qtip"] = "foo";               
357                 }
358
359                 if (element.dom.setAttributeNS) {
360                     element3 = Ext.getBody().createChild({tag: "div"});
361                     element3.dom.setAttributeNS("ext", "qtip", "foobar");
362                 }
363             });
364             
365             afterEach(function() {
366                 if (element2) {
367                     element2.remove();
368                 }
369                 
370                 if (element3) {
371                     element3.remove();
372                 }
373             });
374             
375             describe("without namespace", function() {
376                 it("should return the attribute value if it exists", function() {
377                     expect(element.getAttribute("qtip")).toEqual("bar");
378                 });
379
380                 it("should return null if the attribute does not exist", function() {
381                     expect(element.getAttribute("nothing")).toBeNull();
382                 });
383             });
384
385             describe("with namespace", function() {
386                 it("should return null on a non-namespaced attribute", function() {
387                     expect(element.getAttribute("qtip", "ext")).toBeNull();
388                 });
389
390                 it("should return null if the attribute belong to another namespace", function() {
391                     expect(element2.getAttribute("qtip", "nothing")).toBeNull();
392                 });
393
394                 it("should return the attribute value if it belongs to the namespace", function() {
395                     if (element3) {
396                         expect(element3.getAttribute("qtip", "ext")).toEqual("foobar");
397                     }
398                 });
399                 
400                 it("should handle xml namespace", function() {
401                     expect(element2.getAttribute("qtip", "ext")).toEqual("foo");
402                 });
403             });
404         });
405
406         describe("update", function() {
407             beforeEach(function() {
408                 element.dom.innerHTML = "hello world";
409             });
410
411             it("should update dom element innerHTML", function() {
412                 element.update("foobar");
413
414                 expect(element.dom).hasHTML("foobar");
415             });
416
417             it("should return element", function() {
418                 expect(element.update("foobar")).toBe(element);
419             });
420         });
421
422         describe("prototype aliases", function() {
423             it("should aliases addListener with on", function() {
424                 expect(element.on).toBe(element.addListener);
425             });
426
427             it("should aliases removeListener with un", function() {
428                 expect(element.un).toBe(element.removeListener);
429             });
430
431             it("should aliases removeAllListeners with clearListeners", function() {
432                 expect(element.clearListeners).toBe(element.removeAllListeners);
433             });
434         });
435     });
436
437     describe("class methods", function() {
438         var element2, domEl2, id;
439
440         beforeEach(function() {
441             element = Ext.getBody().createChild({tag: "div"});
442             domEl = element.dom;
443
444             id = Ext.id();
445             domEl2 = document.createElement("div");
446             domEl2.id = id;
447             document.body.appendChild(domEl2);
448
449             spyOn(Ext.Element, "addToCache").andCallThrough();
450         });
451
452         afterEach(function() {
453             if (element2) {
454                 element2.remove();
455             }
456             if (domEl2 && domEl2.parentNode === document.body) {
457                 document.body.removeChild(domEl2);
458             }
459         });
460         
461         describe("get", function() {
462             describe("alias", function() {
463                 it("should alias Ext.Element.get with Ext.get", function() {
464                     expect(Ext.get).toBe(Ext.Element.get);
465                 });
466             });
467
468             describe("passing string id as first argument", function() {
469                 describe("with a dom element which is not already encapsulated", function() {
470                     it("should return a new Ext.Element", function() {
471                         element2 = Ext.get(id);
472
473                         expect(element2 instanceof Ext.Element).toBe(true);
474                     });
475
476                     it("should encapsulate the dom element in the Ext.Element", function() {
477                         element2 = Ext.get(id);
478
479                         expect(element2.dom).toBe(domEl2);
480                     });
481
482                     it("should add element to Ext.cache", function() {
483                         element2 = Ext.get(id);
484          
485                         expect(Ext.Element.addToCache).toHaveBeenCalledWith(element2);
486                     });
487                 });
488
489                 describe("with a dom element which is already encapsulated", function() {
490                     it("should return the corresponding Ext.element", function() {
491                         expect(Ext.get(domEl)).toBe(element);
492                     });
493
494                     it("should not add element to Ext.cache if it is already in", function() {
495                         Ext.get(domEl);
496
497                         expect(Ext.Element.addToCache).not.toHaveBeenCalled();
498                     });
499                 });
500             });
501
502             describe("passing dom element as first argument", function() {
503                 describe("with a dom element which is not already encapsulated", function() {
504                     it("should return a new Ext.Element", function() {
505                         element2 = Ext.get(domEl2);
506
507                         expect(element2 instanceof Ext.Element).toBe(true);
508                     });
509
510                     it("should encapsulate the dom element in the Ext.Element", function() {
511                         element2 = Ext.get(domEl2);
512
513                         expect(element2.dom).toBe(domEl2);
514                     });
515
516                     it("should add element to Ext.cache", function() {
517                         element2 = Ext.get(domEl2);
518
519                         expect(Ext.Element.addToCache).toHaveBeenCalledWith(element2);
520                     });
521                 });
522
523                 describe("with a dom element which is already encapsulated", function() {
524                     it("should return the corresponding Ext.element", function() {
525                         expect(Ext.get(domEl.id)).toBe(element);
526                     });
527
528                     it("should not add element to Ext.cache if it is already in", function() {
529                         Ext.get(domEl.id);
530
531                         expect(Ext.Element.addToCache).not.toHaveBeenCalled();
532                     });
533                 });
534             });
535
536             describe("passing an Ext.Element as first argument", function() {
537                 it("should return Ext.Element", function() {
538                     expect(Ext.get(element)).toBe(element);
539                 });
540             });
541
542             describe("passing a CompositeElement as first argument", function() {
543                 var compositeElement;
544
545                 beforeEach(function() {
546                     compositeElement = Ext.select("div");
547                 });
548
549                 it("should return Ext.Element", function() {
550                     expect(Ext.get(compositeElement)).toBe(compositeElement);
551                 });
552             });
553
554             describe("passing an array as first argument", function() {
555                 it("should call Ext.Element.select", function() {
556                     var arr = [domEl, domEl2];
557                     spyOn(Ext.Element, "select");
558
559                     Ext.get(arr);
560
561                     expect(Ext.Element.select).toHaveBeenCalledWith(arr);
562                 });
563             });
564
565             describe("passing document as first argument", function() {
566                 it("should return an Ext.Element", function() {
567                     expect(Ext.get(document) instanceof Ext.Element).toBe(true);
568                 });
569
570                 it("should return a bogus Ext.Element", function() {
571                     expect(Ext.get(document).id).not.toBeDefined();
572                 });
573
574                 it("should return an Ext.Element that encapsulate document", function() {
575                     expect(Ext.get(document).dom).toBe(document);
576                 });
577             });
578         });
579
580         xdescribe("garbageCollector", function() {
581
582         });
583
584         describe("fly", function() {
585             var flyWeight;
586
587             beforeEach(function() {
588                 spyOn(Ext, "getDom").andCallThrough();
589
590             });
591
592             describe("global flyweight", function() {
593                 beforeEach(function() {
594                     flyWeight = Ext.fly(domEl2);
595                 });
596
597                 it("should return an Ext.Element.Flyweight", function() {
598                     expect(flyWeight instanceof Ext.Element.Flyweight).toBe(true);
599                 });
600
601                 it("should not cache a dom element", function() {
602                     expect(Ext.cache[domEl2.id]).toBeUndefined();
603                 });
604
605                 it("should call Ext.getDom", function() {
606                     expect(Ext.getDom).toHaveBeenCalledWith(domEl2);
607                 });
608
609                 it("should create a one time reference", function() {
610                     expect(Ext.Element._flyweights._global).toEqual(flyWeight);
611                 });
612             });
613
614             describe("named reusable flyweight", function() {
615                 beforeEach(function() {
616                     flyWeight = Ext.fly(domEl2, "myflyweight");
617                 });
618
619                 it("should return an Ext.Element.Flyweight", function() {
620                     expect(flyWeight instanceof Ext.Element.Flyweight).toBe(true);
621                 });
622
623                 it("should not cache a dom element", function() {
624                     expect(Ext.cache[domEl2.id]).toBeUndefined();
625                 });
626
627                 it("should call Ext.getDom", function() {
628                     expect(Ext.getDom).toHaveBeenCalledWith(domEl2);
629                 });
630
631                 it("should create a one time reference", function() {
632                     expect(Ext.Element._flyweights.myflyweight).toEqual(flyWeight);
633                 });
634             });
635         });
636
637         describe("aliases", function() {
638             it("should aliases Ext.Element.get with Ext.get", function() {
639                 expect(Ext.get).toBe(Ext.Element.get);
640             });
641
642             it("should aliases Ext.element.fly with Ext.fly", function() {
643                 expect(Ext.fly).toBe(Ext.Element.fly);
644             });
645         });
646     });
647 }, "/src/dom/Element.js");
648