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