Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / core / test / unit / spec / lang / Function.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.Function", function() {
16     describe("bind", function() {
17         var fn,
18             bind;
19
20         beforeEach(function() {
21             fn = jasmine.createSpy("bindSpy");
22         });
23
24         it("should return a function if a function is passed as first argument", function() {
25             bind = Ext.Function.bind(fn, this);
26
27             expect(typeof bind === "function").toBe(true);
28         });
29
30         it("should use the correct scope", function() {
31             bind = Ext.Function.bind(fn, fakeScope);
32
33             bind();
34
35             expect(fn.calls[0].object).toBe(fakeScope);
36         });
37
38         it("should call the first function when it is executed", function() {
39             bind = Ext.Function.bind(fn, this);
40
41             bind();
42
43             expect(fn).toHaveBeenCalled();
44         });
45
46         describe("argument passing", function() {
47
48             it("should use default args if none are passed", function() {
49                 bind = Ext.Function.bind(fn, this, ['a', 'b']);
50
51                 bind();
52
53                 expect(fn).toHaveBeenCalledWith('a', 'b');
54             });
55
56             it("should use passed args if they are present", function() {
57                 bind = Ext.Function.bind(fn, this);
58
59                 bind('c', 'd');
60
61                 expect(fn).toHaveBeenCalledWith('c', 'd');
62             });
63
64             it("should append args", function() {
65                 bind = Ext.Function.bind(fn, this, ['a', 'b'], true);
66
67                 bind('c', 'd');
68
69                 expect(fn).toHaveBeenCalledWith('c', 'd', 'a', 'b');
70             });
71
72             it("should append args at the given index", function() {
73                 bind = Ext.Function.bind(fn, this, ['a', 'b'], 0);
74
75                 bind('c', 'd');
76
77                 expect(fn).toHaveBeenCalledWith('a', 'b', 'c', 'd');
78             });
79         });
80     });
81
82     describe("createInterceptor", function() {
83         var interceptor,
84             interceptorFn,
85             interceptedFn,
86             interceptorIsRunFirst,
87             interceptedIsRunAfter;
88
89         beforeEach(function() {
90             interceptorIsRunFirst = false;
91             interceptedIsRunAfter = false;
92
93             interceptorFn = jasmine.createSpy("interceptorSpy").andCallFake(function() {
94                 interceptorIsRunFirst = true;
95             });
96             interceptedFn = jasmine.createSpy("interceptedSpy").andCallFake(function() {
97                 interceptedIsRunAfter = interceptorIsRunFirst;
98             });
99         });
100
101         describe("if no function is passed", function() {
102             it("should return the same function", function() {
103                 expect(Ext.Function.createInterceptor(interceptedFn)).toEqual(interceptedFn);
104             });
105         });
106
107         describe("if a function is passed", function() {
108             beforeEach(function() {
109                 interceptor = Ext.Function.createInterceptor(interceptedFn, interceptorFn, fakeScope);
110                 interceptor();
111             });
112
113             it("should return a new function", function() {
114                 expect(typeof interceptor === "function").toBe(true);
115                 expect(interceptor).not.toEqual(interceptedFn);
116             });
117
118             it("should set the correct scope for the interceptor function", function() {
119                 expect(interceptorFn.calls[0].object).toBe(fakeScope);
120             });
121
122             it("should call the interceptor function first", function() {
123                 expect(interceptedIsRunAfter).toBe(true);
124             });
125
126         });
127
128         describe("if the interceptor function returns false", function() {
129             it("should not execute the original function", function() {
130                 interceptor = Ext.Function.createInterceptor(interceptedFn, function() {
131                     return false;
132                 });
133
134                 interceptor();
135                 expect(interceptedFn).not.toHaveBeenCalled();
136             });
137         });
138     });
139
140     describe("defer", function() {
141         var fn;
142
143         beforeEach(function(){
144             fn = jasmine.createSpy("deferSpy");
145         });
146
147         it("should execute the function after the specified number of milliseconds", function() {
148             Ext.defer(fn, 10);
149
150             waitsFor(function(){
151                 return fn.calls.length === 1;
152             }, "fn was never called");
153
154             runs(function() {
155                 expect(fn).toHaveBeenCalled();
156             });
157         });
158
159         it("should execute the function directly if the specified number of milliseconds is <= 0", function() {
160             Ext.defer(fn, 0);
161
162             expect(fn).toHaveBeenCalled();
163         });
164
165         it("should set the correct scope", function() {
166             Ext.defer(fn, 10, fakeScope);
167
168             waitsFor(function(){
169                 return fn.calls.length === 1;
170             }, "fn was never called");
171
172             runs(function() {
173                 expect(fn.calls[0].object).toBe(fakeScope);
174             });
175         });
176
177         it("should pass the correct arguments", function() {
178             Ext.defer(fn, 10, this, [1, 2, 3]);
179
180             waitsFor(function(){
181                 return fn.calls.length === 1;
182             }, "fn was never called");
183
184             runs(function() {
185                 expect(fn).toHaveBeenCalledWith(1,2,3);
186             });
187         });
188
189         it("should return a timeout number", function() {
190             expect(typeof Ext.defer(function() {}, 10) === 'number').toBe(true);
191         });
192     });
193
194     describe("createSequence", function() {
195         var sequence,
196             newFn,
197             origFn,
198             origFnIsRunFirst,
199             newFnIsRunAfter;
200
201         beforeEach(function() {
202             origFnIsRunFirst = false;
203             newFnIsRunAfter = false;
204
205             origFn = jasmine.createSpy("interceptedSpy").andCallFake(function() {
206                 origFnIsRunFirst = true;
207             });
208
209             newFn = jasmine.createSpy("sequenceSpy").andCallFake(function() {
210                 newFnIsRunAfter = origFnIsRunFirst;
211             });
212         });
213
214         describe("if no function is passed", function() {
215             it("should return the same function", function() {
216                 expect(Ext.Function.createSequence(origFn)).toEqual(origFn);
217             });
218         });
219
220         describe("if a function is passed", function() {
221             beforeEach(function() {
222                 sequence = Ext.Function.createSequence(origFn, newFn, fakeScope);
223                 sequence();
224             });
225
226             it("should return a new function", function() {
227                 expect(typeof sequence === "function").toBe(true);
228                 expect(sequence).not.toEqual(origFn);
229             });
230
231             it("should set the correct scope for the sequence function", function() {
232                 expect(newFn.calls[0].object).toBe(fakeScope);
233             });
234
235             it("should call the sequence function first", function() {
236                 expect(newFnIsRunAfter).toBe(true);
237             });
238
239         });
240     });
241 });
242