Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / core / test / unit / spec / Ext-more.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-more", function() {
16     describe("Ext.id", function(){
17         var el;
18         describe("if element passed as first argument is different of document or window", function() {
19             beforeEach(function() {
20                 el = document.createElement("div");
21                 document.body.appendChild(el);
22             });
23
24             afterEach(function(){
25                 Ext.getBody().dom.removeChild(el);
26             });
27
28             it("should generate an unique id for the element with default prefix ext-gen", function() {
29                 expect(Ext.id(el)).toEqual("ext-gen" + Ext.idSeed);
30             });
31
32             it("should generate an unique id for the element with custom prefix", function() {
33                 var prefix = "nico-yhwh";
34                 expect(Ext.id(el, prefix)).toEqual(prefix + Ext.idSeed);
35             });
36
37             it("should not override existing id", function() {
38                 var id = "unchanged";
39                 el.id = id;
40                 expect(Ext.id(el)).toEqual(id);
41             });
42         });
43
44         describe("if element passed as first argument is document", function() {
45             it("should return Ext.documentId", function() {
46                 expect(Ext.id(document)).toEqual(Ext.documentId);
47             });
48         });
49
50         describe("if element passed as first argument is window", function() {
51             it("should return Ext.windowId", function() {
52                 expect(Ext.id(window)).toEqual(Ext.windowId);
53             });
54         });
55     });
56
57     describe("Ext.getBody", function() {
58         it("should return current document body as an Ext.core.Element", function() {
59             expect(Ext.getBody()).toEqual(Ext.get(document.body)); 
60         });
61     });
62
63     describe("Ext.getHead", function() {
64         it("should return current document head as an Ext.core.Element", function() {
65             expect(Ext.getHead()).toEqual(Ext.get(document.getElementsByTagName("head")[0]));
66         });
67     });
68
69     describe("Ext.getDoc", function() {
70         it("should return the current HTML document object as an Ext.element", function() {
71             expect(Ext.getDoc()).toEqual(Ext.get(document));
72         });
73     });
74
75     describe("Ext.getCmp", function() {
76         it("should return a component", function() {
77             var cmp = new Ext.Component({id: 'foobar'});
78             expect(Ext.getCmp('foobar')).toBe(cmp);
79             cmp.destroy();
80         });
81     });
82     if (!Ext.isWindows && !Ext.isMac && !Ext.isLinux) {
83         describe("Ext.getOrientation", function() {
84             it("should return the current orientation of the mobile device", function() {
85                 if (window.innerHeight <= window.innerWidth) {
86                     expect(Ext.getOrientation()).toEqual("landscape");
87                 } else {
88                     expect(Ext.getOrientation()).toEqual("portrait");
89                 }
90             });
91         });
92     }
93
94     describe("Ext.callback", function() {
95         var cfn;
96
97         beforeEach(function() {
98             cfn = jasmine.createSpy();
99         });
100
101         afterEach(function() {
102             cfn = undefined; 
103         });
104
105         it("should execute the passed function in the specified scope", function() {
106             Ext.callback(cfn, fakeScope);
107             expect(cfn.calls[0].object).toBe(fakeScope);
108         });
109
110         it("should pass arguments to the callback function", function() {
111             Ext.callback(cfn, fakeScope, [1, 2, 3, 4, 6]);
112             expect(cfn).toHaveBeenCalledWith(1, 2, 3, 4,6); 
113         });
114
115         it("should be able to defer function call", function() {
116             runs(function() {
117                 Ext.callback(cfn, fakeScope, [1, 2, 3, 4, 6], 1);
118                 expect(cfn).not.toHaveBeenCalled();
119             });
120             waits(1);
121             runs(function() {
122                 expect(cfn).toHaveBeenCalledWith(1, 2, 3, 4, 6);
123                 expect(cfn.calls[0].object).toBe(fakeScope);
124             });
125
126         });
127     });
128
129     describe("Ext.destroy", function() {
130         var o1, o2, o3;
131
132         beforeEach(function() {
133             o1 = jasmine.createSpyObj("o1", ["destroy"]);
134
135             o2 = jasmine.createSpyObj("o2", ["destroy"]);
136
137             o3 = jasmine.createSpyObj("o3", ["dest"]);
138
139         });
140
141         it("should destroy an object", function() {
142             Ext.destroy(o1);
143
144             expect(o1.destroy).toHaveBeenCalled();
145         });
146
147         it("should no destroy an object without a destroy method", function() {
148             Ext.destroy(o3);
149
150             expect(o3.dest).not.toHaveBeenCalled();
151         });
152
153         it("should destroy an array of objects", function() {
154             Ext.destroy([o1, o2, o3]);
155
156             expect(o1.destroy).toHaveBeenCalled();
157             expect(o2.destroy).toHaveBeenCalled();
158             expect(o3.dest).not.toHaveBeenCalled();
159         });
160
161         it("should destroy multiple objects", function() {
162             Ext.destroy(o1, o2, o3);
163
164             expect(o1.destroy).toHaveBeenCalled();
165             expect(o2.destroy).toHaveBeenCalled();
166             expect(o3.dest).not.toHaveBeenCalled();
167         });
168
169         it("should remove dom if object is an Ext.element", function() {
170             var el = Ext.getBody().createChild({id: "to_destroy"});
171
172             Ext.destroy(el);
173
174             expect(Ext.fly("to_destroy")).toBeNull();
175         });
176     });
177
178     describe("Ext.htmlEncode", function() {
179         var htmlEncode = Ext.String.htmlEncode,
180         str;
181
182         it("should replace ampersands", function() {
183             str = "Fish & Chips";
184
185             expect(htmlEncode(str)).toEqual("Fish &amp; Chips");
186         });
187
188         it("should replace less than", function() {
189             str = "Fish > Chips";
190
191             expect(htmlEncode(str)).toEqual("Fish &gt; Chips");
192         });
193
194         it("should replace greater than", function() {
195             str = "Fish < Chips";
196
197             expect(htmlEncode(str)).toEqual("Fish &lt; Chips");
198         });
199
200         it("should replace double quote", function() {
201             str = 'Fish " Chips';
202
203             expect(htmlEncode(str)).toEqual("Fish &quot; Chips");
204         });
205     });
206
207     describe("Ext.htmlEncode", function() {
208         var htmlDecode = Ext.String.htmlDecode,
209         str;
210
211         it("should replace ampersands", function() {
212             str = "Fish &amp; Chips";
213
214             expect(htmlDecode(str)).toEqual("Fish & Chips");
215         });
216
217         it("should replace less than", function() {
218             str = "Fish &gt; Chips";
219
220             expect(htmlDecode(str)).toEqual("Fish > Chips");
221         });
222
223         it("should replace greater than", function() {
224             str = "Fish &lt; Chips";
225
226             expect(htmlDecode(str)).toEqual("Fish < Chips");
227         });
228
229         it("should replace double quote", function() {
230             str = 'Fish &quot; Chips';
231
232             expect(htmlDecode(str)).toEqual('Fish " Chips');
233         });
234     });
235
236     describe("Ext.urlAppend", function() {
237         var url = "http://example.com/";
238
239         it("should manage question mark", function() {
240             expect(Ext.urlAppend(url, "test=1")).toEqual("http://example.com/?test=1");
241         });
242
243         it("should manage ampersand", function() {
244             expect(Ext.urlAppend(url + "?test=1","foo=2")).toEqual("http://example.com/?test=1&foo=2");
245         });
246
247         it("should return directly url if content is empty", function() {
248             expect(Ext.urlAppend(url)).toEqual(url);
249         });
250     });
251
252     describe("Ext.getDom", function() {
253         var el1;
254
255         beforeEach(function() {
256             el1 = Ext.getBody().createChild({id: "elone"});
257         });
258
259         afterEach(function() {
260             el1.remove();
261         });
262
263         it("should return a dom element if an Ext.element is passed as first argument", function() {
264             expect(Ext.getDom(el1)).toEqual(el1.dom);
265         });
266
267         it("should return a dom element if the string (id) passed as first argument", function() {
268             expect(Ext.getDom("elone")).toEqual(el1.dom);
269         });
270     });
271
272     describe("Ext.removeNode", function(){
273         describe("if passed element isn't body", function() {
274             var el, id;
275             beforeEach(function() {
276                 el = Ext.getBody().createChild({
277                     tag: 'span',
278                     html: 'foobar'
279                 });
280                 id = el.id;
281
282             });
283
284             it("should remove a dom element from document", function(){
285                 Ext.removeNode(el.dom);
286                 expect(document.body.childNodes[0]).toBeUndefined();
287             });
288
289             it("should delete the cache reference", function() {
290                 Ext.removeNode(el.dom);
291                 expect(Ext.cache[id]).toBeUndefined();
292             });
293             if (!Ext.isIE6 && !Ext.isIE7) {
294                 it("should remove all listeners from the dom element", function() {
295                         var listener = jasmine.createSpy();
296                         el.on('mouseup', listener);
297                         Ext.removeNode(el.dom);
298                         jasmine.fireMouseEvent(el.dom, 'mouseup');
299                         expect(listener).not.toHaveBeenCalled();
300
301                 });
302             }
303         });
304
305         describe("if passed element is body", function() {
306             it("should not delete the cache reference", function() {
307                 Ext.removeNode(document.body);
308                 expect(Ext.cache[Ext.getBody().id]).toBeDefined();
309             });
310
311             it("should not remove listeners from body", function() {
312                 var listener = jasmine.createSpy();
313                 Ext.getBody().on('mouseup', listener);
314                 Ext.removeNode(document.body);
315                 jasmine.fireMouseEvent(document.body, 'mouseup');
316                 expect(listener).toHaveBeenCalled();
317                 Ext.getBody().un('mouseup', listener);
318             });
319         });
320         
321         if (!Ext.isIE6 && !Ext.isIE7) {
322             describe("if enableNestedListenerRemoval is true", function() {
323                 var el, child;
324
325                 beforeEach(function(){
326                     Ext.enableNestedListenerRemoval = true;
327                     el = Ext.getBody().createChild();
328                     child = el.createChild();
329                 });
330
331                 afterEach(function(){
332                     Ext.enableNestedListenerRemoval = false;
333                 });
334
335                     it("should remove listener on children", function() {
336                         var listener = jasmine.createSpy();
337                         child.on('mouseup', listener); 
338                         Ext.removeNode(el.dom);
339                         jasmine.fireMouseEvent(child.dom, 'mouseup');
340                         expect(listener).not.toHaveBeenCalled();
341                     });
342
343
344             });
345         }
346         if (!Ext.isIE6 && !Ext.isIE7) {
347             describe("if enableNestedListenerRemoval is false (default)", function() {
348                 var el, child;
349
350                 beforeEach(function(){
351                     el = Ext.getBody().createChild();
352                     child = el.createChild();
353                 });
354
355                 it("should not remove listener on children", function() {
356                     var listener = jasmine.createSpy();
357                     child.on('mouseup', listener); 
358                     Ext.removeNode(el.dom);
359                     jasmine.fireMouseEvent(child.dom, 'mouseup');
360                     expect(listener).toHaveBeenCalled();
361                     Ext.EventManager.purgeElement(child.dom);
362                 });
363             });
364         }
365     });
366
367     describe("Ext.addBehaviors", function() {
368         var listener, span1, span2, div1;
369
370         beforeEach(function() {
371             span1 = Ext.getBody().createChild({
372                 tag: 'span' 
373             });
374
375             span2 = Ext.getBody().createChild({
376                 tag: 'span'
377             });
378
379             div1 = Ext.getBody().createChild({
380                 cls: 'foo'
381             });
382
383             listener = jasmine.createSpy();
384         });
385
386         afterEach(function() {
387             span1.remove();
388             span2.remove();
389             div1.remove();
390         });
391
392         it("should apply event listeners to elements by selectors", function() {
393             Ext.addBehaviors({
394                 'span @mouseup': listener
395             });
396
397             jasmine.fireMouseEvent(span1.dom, 'mouseup');
398             jasmine.fireMouseEvent(span2.dom, 'mouseup');
399             jasmine.fireMouseEvent(div1.dom, 'mouseup');
400
401             expect(listener.calls.length).toEqual(2);
402
403         });
404
405         it("should manage multiple selectors", function() {
406             Ext.addBehaviors({
407                 'span, div.foo @mouseup': listener
408             });
409
410             jasmine.fireMouseEvent(span1.dom, 'mouseup');
411             jasmine.fireMouseEvent(span2.dom, 'mouseup');
412             jasmine.fireMouseEvent(div1.dom, 'mouseup');
413
414             expect(listener.calls.length).toEqual(3);
415
416         });
417     });
418
419     describe("Ext.getScrollBarWidth", function() {
420         it("should return a number between 10 and 40 (we assume that document is loaded)", function() {
421             expect(Ext.getScrollBarWidth() > 10).toBe(true);
422             expect(Ext.getScrollBarWidth() < 40).toBe(true);
423         }); 
424     });
425
426     describe("Ext.copyTo", function(){
427         var src, dest;
428
429         beforeEach(function() {
430             src = {
431                 a: 1,
432                 b: 2,
433                 c: 3,
434                 d: 4
435             };
436
437             dest = {};
438         });
439
440         afterEach(function(){
441             src = null;
442             dest = null;
443         });
444
445         describe("with an array of named properties", function() {
446             it("should copy a set of named properties fom the source object to the destination object.", function() {
447                 Ext.copyTo(dest, src, ['a', 'b', 'e']);
448
449                 expect(dest).toEqual({
450                     a: 1,
451                     b: 2 
452                 });
453             });
454         });
455
456         describe("with a string list of named properties", function() {
457             it("should copy a set of named properties fom the source object to the destination object.", function() {
458                 Ext.copyTo(dest, src, 'c,b,e');
459                 expect(dest).toEqual({
460                     b: 2,
461                     c: 3 
462                 });
463             });
464         });
465     });
466
467     describe("Ext.destroyMembers", function() {
468         var obj, destroyable;
469
470         beforeEach(function(){
471             destroyable = {
472                 destroy: jasmine.createSpy()
473             };
474             obj = {
475                 a: 1,
476                 b: 2,
477                 c: 3,
478                 d: 4,
479                 me : destroyable
480             };
481         });
482
483         it("should remove named properties from a passed object", function() {
484             Ext.destroyMembers(obj, 'a', 'c', 'i');
485             expect(obj).toEqual({
486                 b: 2,
487                 d: 4,
488                 me: destroyable
489             });
490         });
491
492         it("should attempt to destroy passed properties", function() {
493             Ext.destroyMembers(obj, 'a', 'c', 'me');
494
495             expect(destroyable.destroy).toHaveBeenCalled();
496         });
497     });
498
499     describe("Ext.partition", function() {
500         describe("with an array of boolean", function() {
501             it("should partition the set into two sets: a true and a false set", function() {
502                 expect(Ext.partition([true, true, false, false, true])).toEqual([[true,true,true], [false,false]]);
503             });
504         });
505         
506         describe("with an array to partition and a function to determine truth", function() {
507             it("should partition the set into two sets: a true and a false set", function() {
508                 var array = [
509                     'a',
510                     'b',
511                     'c',
512                     'a'
513                 ];
514                  expect(Ext.partition(array, function(item){
515                         return item == "a";
516                 })).toEqual([
517                     ['a', 'a'], 
518                     ['b', 'c']
519                 ]);
520             });
521         });
522         
523         describe("with a NodeList to partition and a function to determine truth", function() {
524             it("should partition the set into two sets: a true and a false set", function() {
525                 var p = [];
526                 
527                 p[0] = Ext.getBody().createChild({
528                     tag: "p",
529                     cls: "class1"
530                 });
531                 p[1] = Ext.getBody().createChild({
532                     tag: "p",
533                     cls: "class2"
534                 });
535                 p[2] = Ext.getBody().createChild({
536                     tag: "p",
537                     cls: "class1"
538                 });
539                 p[3] = Ext.getBody().createChild({
540                     tag: "p",
541                     cls: "class4"
542                 });
543                 p[4] = Ext.getBody().createChild({
544                     tag: "p",
545                     cls: "class5"
546                 });
547                 p[5] = Ext.getBody().createChild({
548                     tag: "p",
549                     cls: "class1"
550                 });                    
551                 
552                 expect(Ext.partition(Ext.query("p"), function(val){
553                         return val.className == "class1";
554                 })).toEqual([
555                     [p[0].dom, p[2].dom, p[5].dom], 
556                     [p[1].dom, p[3].dom, p[4].dom]
557                 ]);
558                 
559                 Ext.Array.each(p, function(el) {
560                     el.remove();
561                 });
562             });
563         });
564     });
565 });
566