9 var dit = /*<1.2compat>*/xit || /*</1.2compat>*/it; // don't run unless no compat
13 var MooTools = new String('MooTools');
16 return Array.from(arguments).slice();
19 var Rules = function(){
20 return this + ' rules';
23 var Args = function(){
24 return [this].concat(Array.prototype.slice.call(arguments));
27 describe("Function Methods", function(){
31 it('should return a new function', function(){
32 var fnc = $empty.create();
33 expect($empty).to.not.equal(fnc);
36 it('should return a new function with specified argument', function(){
37 var fnc = fn.create({'arguments': 'rocks'});
38 expect(fnc()).to.deep.equal(['rocks']);
41 it('should return a new function with multiple arguments', function(){
42 var fnc = fn.create({'arguments': ['MooTools', 'rocks']});
43 expect(fnc()).to.deep.equal(['MooTools', 'rocks']);
46 it('should return a new function bound to an object', function(){
47 var fnc = Rules.create({'bind': 'MooTools'});
48 expect(fnc()).to.equal('MooTools rules');
51 it('should return a new function as an event', function(){
52 var fnc = fn.create({'arguments': [0, 1], 'event': true});
53 expect(fnc('an Event occurred')).to.deep.equal(['an Event occurred', 0, 1]);
59 it('should return the function bound to an object', function(){
60 var fnc = Rules.bind('MooTools');
61 expect(fnc()).to.equal('MooTools rules');
64 it('should return the function bound to an object with specified argument', function(){
65 var results = Args.bind(MooTools, 'rocks')();
66 expect(results[0]).to.equal(MooTools);
67 expect(results[1]).to.equal('rocks');
70 dit('should return the function bound to an object with multiple arguments', function(){
71 var results = Args.bind(MooTools, ['rocks', 'da house'])();
72 expect(results[0]).to.equal(MooTools);
73 expect(results[1]).to.deep.equal(['rocks', 'da house']);
77 it('should return the function bound to an object with specified argument', function(){
78 var fnc = Args.bind(MooTools, 'rocks');
80 expect(result[0]).to.equal(MooTools);
81 expect(result).to.deep.equal([MooTools, 'rocks']);
84 it('should return the function bound to an object with multiple arguments', function(){
85 var fnc = Args.bind(MooTools, ['rocks', 'da house']);
87 expect(result[0]).to.equal(MooTools);
88 expect(result).to.deep.equal([MooTools, 'rocks', 'da house']);
91 it('should return the function bound to an object and make the function an event listener', function(){
92 var fnc = Args.bindWithEvent(MooTools);
93 var result = fnc('an Event occurred');
94 expect(result[0]).to.equal(MooTools);
95 expect(result).to.deep.equal([MooTools, 'an Event occurred']);
98 it('should return the function bound to an object and make the function event listener with multiple arguments', function(){
99 var fnc = Args.bindWithEvent(MooTools, ['rocks', 'da house']);
100 var result = fnc('an Event occurred');
101 expect(result[0]).to.equal(MooTools);
102 expect(result).to.deep.equal([MooTools, 'an Event occurred', 'rocks', 'da house']);
108 it('should return a function that when called passes the specified arguments to the original function', function(){
109 var fnc = fn.pass('MooTools is beautiful and elegant');
110 expect(fnc()).to.deep.equal(['MooTools is beautiful and elegant']);
113 it('should pass multiple arguments and bind the function to a specific object when it is called', function(){
114 var fnc = Args.pass(['rocks', 'da house'], MooTools);
116 expect(result[0]).to.equal(MooTools);
117 expect(result).to.deep.equal([MooTools, 'rocks', 'da house']);
122 it('should run the function', function(){
123 var result = fn.run();
124 expect(result).to.deep.equal([]);
127 it('should run the function with multiple arguments', function(){
128 var result = fn.run(['MooTools', 'beautiful', 'elegant']);
129 expect(result).to.deep.equal(['MooTools', 'beautiful', 'elegant']);
132 it('should run the function with multiple arguments and bind the function to an object', function(){
133 var result = Args.run(['beautiful', 'elegant'], MooTools);
134 expect(result[0]).to.equal(MooTools);
135 expect(result).to.deep.equal([MooTools, 'beautiful', 'elegant']);
141 it("should extend the function's properties", function(){
142 var fnc = (function(){}).extend({a: 1, b: 'c'});
143 expect(fnc.a).to.equal(1);
144 expect(fnc.b).to.equal('c');
150 it('should call the function without raising an exception', function(){
151 var fnc = function(){
152 this_should_not_work();
157 it("should return the function's return value", function(){
158 var fnc = Function.from('hello world!');
159 expect(fnc.attempt()).to.equal('hello world!');
162 it('should return null if the function raises an exception', function(){
163 var fnc = function(){
164 this_should_not_work();
166 expect(fnc.attempt()).to.equal(null);
171 it('delay should return a timer pointer', function(){
172 var referenceTimer = setTimeout(function(){}, 10000);
173 var timer = (function(){}).delay(10000);
174 expect(typeOf(timer)).to.equal(typeOf(referenceTimer));
176 clearTimeout(referenceTimer);
179 // Function.periodical
181 it('periodical should return a timer pointer', function(){
182 var referenceTimer = setInterval(function(){}, 10000);
183 var timer = (function(){}).periodical(10000);
184 expect(typeOf(timer)).to.equal(typeOf(referenceTimer));
185 clearInterval(timer);
186 clearInterval(referenceTimer);
191 describe('Function.attempt', function(){
193 it('should return the result of the first successful function without executing successive functions', function(){
195 var attempt = Function.attempt(function(){
197 throw new Exception();
205 expect(calls).to.equal(2);
206 expect(attempt).to.equal('success');
209 it('should return null when no function succeeded', function(){
211 var attempt = Function.attempt(function(){
213 return I_invented_this();
216 return uninstall_ie();
218 expect(calls).to.equal(2);
219 expect(attempt).to.equal(null);
226 describe('Function.bind', function(){
228 it('should return the function bound to an object', function(){
229 var spy = sinon.spy();
230 var f = spy.bind('MooTools');
231 expect(spy.called).to.equal(false);
233 expect(spy.calledWith()).to.equal(true);
235 expect(spy.calledWith('foo', 'bar')).to.equal(true);
238 it('should return the function bound to an object with specified argument', function(){
239 var binding = {some: 'binding'};
240 var spy = sinon.stub().returns('something');
241 var f = spy.bind(binding, 'arg');
243 expect(spy.called).to.equal(false);
244 expect(f('additional', 'arguments')).to.equal('something');
245 expect(spy.lastCall.thisValue).to.equal(binding);
248 it('should return the function bound to an object with multiple arguments', function(){
249 var binding = {some: 'binding'};
250 var spy = sinon.stub().returns('something');
251 var f = spy.bind(binding, ['foo', 'bar']);
253 expect(spy.called).to.equal(false);
254 expect(f('additional', 'arguments')).to.equal('something');
255 expect(spy.lastCall.thisValue).to.equal(binding);
258 dit('should still be possible to use it as constructor', function(){
259 function Alien(type) {
264 var Tribble = Alien.bind(thisArg, 'Polygeminus grex');
266 // `thisArg` should **not** be used for the `this` binding when called as a constructor
267 var fuzzball = new Tribble('Klingon');
268 expect(fuzzball.type).to.equal('Polygeminus grex');
271 dit('when using .call(thisArg) on a bound function, it should ignore the thisArg of .call', function(){
273 return [this.foo].concat(Array.slice(arguments));
276 expect(fn.bind({foo: 'bar'})()).to.deep.equal(['bar']);
277 expect(fn.bind({foo: 'bar'}, 'first').call({foo: 'yeah!'}, 'yooo')).to.deep.equal(['bar', 'first', 'yooo']);
279 var bound = fn.bind({foo: 'bar'});
280 var bound2 = fn.bind({foo: 'yep'});
281 var inst = new bound;
283 expect(bound2.call(inst, 'yoo', 'howdy')).to.deep.equal(['yep', 'yoo', 'howdy']);
288 describe('Function.pass', function(){
290 it('should return a function that when called passes the specified arguments to the original function', function(){
291 var spy = sinon.stub().returns('the result');
292 var fnc = spy.pass('an argument');
293 expect(spy.called).to.equal(false);
294 expect(fnc('additional', 'arguments')).to.equal('the result');
295 expect(spy.calledWith('an argument')).to.equal(true);
296 expect(spy.callCount).to.equal(1);
299 it('should pass multiple arguments and bind the function to a specific object when it is called', function(){
300 var spy = sinon.stub().returns('the result');
301 var binding = {some: 'binding'};
302 var fnc = spy.pass(['multiple', 'arguments'], binding);
303 expect(spy.called).to.equal(false);
304 expect(fnc('additional', 'arguments')).to.equal('the result');
305 expect(spy.lastCall.thisValue).to.equal(binding);
306 expect(spy.calledWith('multiple', 'arguments')).to.equal(true);
311 describe('Function.extend', function(){
313 it("should extend the function's properties", function(){
314 var fnc = (function(){}).extend({a: 1, b: 'c'});
315 expect(fnc.a).to.equal(1);
316 expect(fnc.b).to.equal('c');
321 describe('Function.attempt', function(){
323 it('should call the function without raising an exception', function(){
324 var fnc = function(){
330 it("should return the function's return value", function(){
331 var spy = sinon.stub().returns('hello world!');
332 expect(spy.attempt()).to.equal('hello world!');
335 it('should return null if the function raises an exception', function(){
336 var fnc = function(){
339 expect(fnc.attempt()).to.equal(null);
344 describe('Function.delay', function(){
346 beforeEach(function(){
347 this.clock = sinon.useFakeTimers();
350 afterEach(function(){
352 this.clock.restore();
355 it('should return a timer pointer', function(){
356 var spyA = sinon.spy();
357 var spyB = sinon.spy();
359 var timerA = spyA.delay(200);
360 var timerB = spyB.delay(200);
362 this.clock.tick(100);
364 expect(spyA.called).to.equal(false);
365 expect(spyB.called).to.equal(false);
366 clearTimeout(timerB);
368 this.clock.tick(250);
369 expect(spyA.callCount).to.equal(1);
370 expect(spyB.callCount).to.equal(0);
373 it('should pass parameter 0', function(){
374 var spy = sinon.spy();
375 spy.delay(50, null, 0);
377 this.clock.tick(100);
378 expect(spy.calledWith(0)).to.equal(true);
381 it('should not pass any argument when no arguments passed', function(){
382 var argumentCount = null;
383 var spy = function(){
384 argumentCount = arguments.length;
387 this.clock.tick(100);
388 expect(argumentCount).to.equal(0);
393 describe('Function.periodical', function(){
395 beforeEach(function(){
396 this.clock = sinon.useFakeTimers();
399 afterEach(function(){
401 this.clock.restore();
404 it('should return an interval pointer', function(){
405 var spy = sinon.spy();
407 var interval = spy.periodical(10);
408 expect(spy.called).to.equal(false);
410 this.clock.tick(100);
412 expect(spy.callCount).to.be.greaterThan(2);
413 expect(spy.callCount).to.be.lessThan(15);
414 clearInterval(interval);
416 expect(spy.called).to.equal(false);
418 this.clock.tick(100);
420 expect(spy.called).to.equal(false);
423 it('should pass parameter 0', function(){
424 var spy = sinon.spy();
425 var timer = spy.periodical(10, null, 0);
427 this.clock.tick(100);
429 expect(spy.calledWith(0)).to.equal(true);
430 clearInterval(timer);
433 it('should not pass any argument when no arguments passed', function(){
434 var argumentCount = null;
435 var spy = function(){
436 argumentCount = arguments.length;
438 var timer = spy.periodical(50);
439 this.clock.tick(100);
441 expect(argumentCount).to.equal(0);
442 clearInterval(timer);