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