10 describe('$A', function(){
12 it('should return a copy for an array', function(){
15 expect(arr1).to.not.equal(arr2);
18 it('should return an array for an Elements collection', function(){
19 var div1 = document.createElement('div');
20 var div2 = document.createElement('div');
21 var div3 = document.createElement('div');
23 div1.appendChild(div2);
24 div1.appendChild(div3);
26 var array = $A(div1.getElementsByTagName('*'));
27 expect(Array.type(array)).to.equal(true);
30 it('should return an array for arguments', function(){
31 var fnTest = function(){
34 var arr = fnTest(1,2,3);
35 expect(Array.type(arr)).to.equal(true);
36 expect(arr.length).to.equal(3);
41 describe('$arguments', function(){
43 it('should return the argument passed according to the index', function(){
44 expect($arguments(0)('a','b','c','d')).to.equal('a');
45 expect($arguments(1)('a','b','c','d')).to.equal('b');
46 expect($arguments(2)('a','b','c','d')).to.equal('c');
47 expect($arguments(3)('a','b','c','d')).to.equal('d');
52 describe('$chk', function(){
54 it('should return false on false', function(){
55 expect($chk(false)).to.equal(false);
58 it('should return false on null', function(){
59 expect($chk(null)).to.equal(false);
62 it('should return false on undefined', function(){
63 expect($chk(undefined)).to.equal(false);
66 it('should return true on 0', function(){
67 expect($chk(0)).to.equal(true);
70 it('should return true for any truthsie', function(){
71 expect($chk(1)).to.equal(true);
72 expect($chk({})).to.equal(true);
73 expect($chk(true)).to.equal(true);
78 describe('$clear', function(){
80 it('should clear timeouts', function(){
81 var timeout = setTimeout(function(){}, 100);
82 expect($clear(timeout)).to.equal(null);
85 it('should clear intervals', function(){
86 var interval = setInterval(function(){}, 100);
87 expect($clear(interval)).to.equal(null);
92 describe('$defined', function(){
94 it('should return true on 0', function(){
95 expect($defined(0)).to.equal(true);
98 it('should return true on false', function(){
99 expect($defined(false)).to.equal(true);
102 it('should return false on null', function(){
103 expect($defined(null)).to.equal(false);
106 it('should return false on undefined', function(){
107 expect($defined(undefined)).to.equal(false);
112 describe('$each', function(){
114 it('should call the function for each item in Function arguments', function(){
117 $each(arguments, function(value, key){
118 daysArr[key] = value;
120 })('Sun','Mon','Tue');
122 expect(daysArr).to.eql(['Sun','Mon','Tue']);
125 it('should call the function for each item in the array', function(){
127 $each(['Sun','Mon','Tue'], function(value, key){
128 daysArr[key] = value;
131 expect(daysArr).to.eql(['Sun','Mon','Tue']);
134 it('should call the function for each item in the object', function(){
136 $each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
137 daysObj[key] = value;
140 expect(daysObj).to.eql({first: 'Sunday', second: 'Monday', third: 'Tuesday'});
145 describe('$extend', function(){
147 it('should extend two objects', function(){
148 var obj1 = {a: 1, b: 2};
149 var obj2 = {b: 3, c: 4};
151 expect(obj1).to.eql({a: 1, b: 3, c: 4});
154 it('should overwrite properties', function(){
155 var obj1 = {a: 1, b: 2};
156 var obj2 = {b: 3, c: 4, a: 5};
158 expect(obj1).to.eql({a: 5, b: 3, c: 4});
161 it('should not extend with null argument', function(){
162 var obj1 = {a: 1, b: 2};
164 expect(obj1).to.eql({a: 1, b: 2});
169 describe('$lambda', function(){
171 it('if a function is passed in that function should be returned', function(){
172 var fn = function(a,b){ return a; };
173 expect($lambda(fn)).to.equal(fn);
176 it('should return a function that returns the value passed when called', function(){
177 expect($lambda('hello world!')()).to.equal('hello world!');
182 describe('$merge', function(){
184 it('should dereference objects', function(){
185 var obj1 = {a: 1, b: 2};
186 var obj2 = $merge(obj1);
187 expect(obj1).to.not.equal(obj2);
190 it('should merge any arbitrary number of nested objects', function(){
191 var obj1 = {a: {a: 1, b: 2, c: 3}, b: 2};
192 var obj2 = {a: {a: 2, b: 8, c: 3, d: 8}, b: 3, c: 4};
193 var obj3 = {a: {a: 3}, b: 3, c: false};
194 expect($merge(obj1, obj2, obj3)).to.eql({a: {a: 3, b: 8, c: 3, d: 8}, b: 3, c: false});
199 describe('$pick', function(){
201 it('should return the first false argument', function(){
202 var picked1 = $pick(null, undefined, false, [1,2,3], {});
203 expect(picked1).to.equal(false);
206 it('should return the first defined argument', function(){
207 var picked1 = $pick(null, undefined, null, [1,2,3], {});
208 expect(picked1).to.eql([1,2,3]);
213 describe('$random', function(){
215 it('should return a number between two numbers specified', function(){
216 var rand = $random(1, 3);
217 expect(rand).to.be.within(1, 3);
222 describe('$splat', function(){
224 it('should transform a non array into an array', function(){
225 expect($splat(1)).to.eql([1]);
228 it('should transforum an undefined or null into an empty array', function(){
229 expect($splat(null)).to.eql([]);
230 expect($splat(undefined)).to.eql([]);
233 it('should ignore and return an array', function(){
234 expect($splat([1,2,3])).to.eql([1,2,3]);
239 describe('$time', function(){
241 it('should return a timestamp', function(){
242 expect(Number.type($time())).to.equal(true);
245 it('should be within a reasonable range', function(){
247 expect(time).to.be.greaterThan(1e12);
248 expect(time).to.be.lessThan(1e13);
253 describe('$try', function(){
255 it('should return the result of the first successful function without executing successive functions', function(){
257 var attempt = $try(function(){
259 throw new Exception();
267 expect(calls).to.equal(2);
268 expect(attempt).to.equal('success');
271 it('should return null when no function succeeded', function(){
273 var attempt = $try(function(){
275 return I_invented_this();
278 return uninstall_ie();
280 expect(calls).to.equal(2);
281 expect(attempt).to.equal(null);
287 describe('$type', function(){
289 it("should return 'array' for Array objects", function(){
290 expect($type([1,2])).to.equal('array');
293 it("should return 'string' for String objects", function(){
294 expect($type('ciao')).to.equal('string');
297 it("should return 'regexp' for RegExp objects", function(){
298 expect($type(/_/)).to.equal('regexp');
301 it("should return 'function' for Function objects", function(){
302 expect($type(function(){})).to.equal('function');
305 it("should return 'number' for Number objects", function(){
306 expect($type(10)).to.equal('number');
307 expect($type(NaN)).to.not.equal('number');
310 it("should return 'boolean' for Boolean objects", function(){
311 expect($type(true)).to.equal('boolean');
312 expect($type(false)).to.equal('boolean');
315 it("should return 'object' for Object objects", function(){
316 expect($type({a:2})).to.equal('object');
319 it("should return 'arguments' for Function arguments", function(){
320 if (window.opera){ // Seems like the Opera guys can't decide on this
321 var type = $type(arguments);
322 expect(type == 'array' || type == 'arguments').to.equal(true);
326 expect($type(arguments)).to.equal('arguments');
329 it("should return false for null objects", function(){
330 expect($type(null)).to.equal(false);
333 it("should return false for undefined objects", function(){
334 expect($type(undefined)).to.equal(false);
337 it("should return 'collection' for HTMLElements collections", function(){
338 expect($type(document.getElementsByTagName('*'))).to.equal('collection');
341 it("should return 'element' for an Element", function(){
342 var div = document.createElement('div');
343 expect($type(div)).to.equal('element');
346 it("should return 'array' for Elements", function(){
347 expect($type(new Elements)).to.equal('array');
350 it("should return 'window' for the window object", function(){
351 expect($type(window)).to.equal('window');
354 it("should return 'document' for the document object", function(){
355 expect($type(document)).to.equal('document');
360 describe('$unlink', function(){
362 it("should unlink an object recursivly", function(){
364 var obj = {a: 1, inner: inner};
365 var copy = $unlink(obj);
369 expect(obj.a).to.equal(10);
370 expect(obj.inner.b).to.equal(20);
371 expect($type(obj)).to.equal('object');
373 expect(copy.a).to.equal(1);
374 expect(copy.inner.b).to.equal(2);
375 expect($type(copy)).to.equal('object');
378 it("should unlink an Hash", function(){
379 var hash = new Hash({a: 'one'});
380 var copy = $unlink(hash);
382 expect($type(hash)).to.equal('hash');
383 expect($type(copy)).to.equal('hash');
385 copy.set('a', 'two');
387 expect(hash.get('a')).to.equal('one');
388 expect(copy.get('a')).to.equal('two');
393 describe('Hash.getLength', function(){
395 it("should return the number of items in it", function(){
396 var hash = new Hash({});
397 expect(hash.getLength()).to.equal(0);
398 hash.set('mootools', 'awesome');
400 expect(hash.getLength()).to.equal(2);
403 it("should not fail when length is set", function(){
404 var hash = new Hash({'length': 10});
405 expect(hash.getLength()).to.equal(1);
408 it("should work as a generic on objects", function(){
409 expect(Hash.getLength({})).to.equal(0);
410 expect(Hash.getLength({'': '', '0': '0', 'length': 99})).to.equal(3);
415 describe('$H', function(){
417 it("should create a new hash", function(){
419 expect($type(hash)).to.equal('hash');
427 describe('Function.prototype.overloadSetter', function(){
429 var collector, setter;
430 beforeEach(function(){
432 setter = (function(key, value){
433 collector[key] = value;
437 it('should call a specific setter', function(){
438 setter = setter.overloadSetter();
439 setter('key', 'value');
441 expect(collector).to.eql({key: 'value'});
448 expect(collector).to.eql({
457 setter('otherKey', 4);
459 expect(collector).to.eql({
466 it('should only works with objects in plural mode', function(){
467 setter = setter.overloadSetter(true);
474 expect(collector).to.eql({
482 describe('Function.prototype.overloadGetter', function(){
485 beforeEach(function(){
492 getter = (function(key){
493 return object[key] || null;
497 it('should call a getter for each argument', function(){
498 getter = getter.overloadGetter();
500 expect(getter('aa')).to.equal(1);
501 expect(getter('bb')).to.equal(2);
502 expect(getter('cc')).to.equal(3);
503 expect(getter('dd')).to.equal(null);
505 expect(getter('aa', 'bb', 'cc')).to.eql(object);
506 expect(getter(['aa', 'bb', 'cc'])).to.eql(object);
507 expect(getter(['aa', 'cc', 'dd'])).to.eql({aa: 1, cc: 3, dd: null});
510 it('should work in plural mode', function(){
511 getter = getter.overloadGetter(true);
513 expect(getter('aa')).to.eql({
517 expect(getter(['aa', 'bb'])).to.eql({
526 describe('typeOf', function(){
528 it("should return 'array' for Array objects", function(){
529 expect(typeOf([1,2])).to.equal('array');
532 it("should return 'string' for String objects", function(){
533 expect(typeOf('ciao')).to.equal('string');
536 it("should return 'regexp' for RegExp objects", function(){
537 expect(typeOf(/_/)).to.equal('regexp');
540 it("should return 'function' for Function objects", function(){
541 expect(typeOf(function(){})).to.equal('function');
544 it("should return 'number' for Number objects", function(){
545 expect(typeOf(10)).to.equal('number');
546 expect(typeOf(NaN)).to.not.equal('number');
549 it("should return 'boolean' for Boolean objects", function(){
550 expect(typeOf(true)).to.equal('boolean');
551 expect(typeOf(false)).to.equal('boolean');
554 it("should return 'object' for Object objects", function(){
555 expect(typeOf({a:2})).to.equal('object');
558 it("should return 'arguments' for Function arguments", function(){
559 if (typeof window != 'undefined' && window.opera){ // Seems like the Opera guys can't decide on this
560 var type = typeOf(arguments);
561 expect(type == 'array' || type == 'arguments').to.equal(true);
565 expect(typeOf(arguments)).to.equal('arguments');
568 it("should return 'null' for null objects", function(){
569 expect(typeOf(null)).to.equal('null');
572 it("should return 'null' for undefined objects", function(){
573 expect(typeOf(undefined)).to.equal('null');
578 describe('instanceOf', function(){
580 it("should return false on null object", function(){
581 expect(instanceOf(null, null)).to.equal(false);
584 it("should return true for Arrays", function(){
585 expect(instanceOf([], Array)).to.equal(true);
588 it("should return true for Numbers", function(){
589 expect(instanceOf(1, Number)).to.equal(true);
592 it("should return true for Objects", function(){
593 expect(instanceOf({}, Object)).to.equal(true);
596 it("should return true for Dates", function(){
597 expect(instanceOf(new Date(), Date)).to.equal(true);
600 it("should return true for Booleans", function(){
601 expect(instanceOf(true, Boolean)).to.equal(true);
604 it("should return true for RegExps", function(){
605 expect(instanceOf(/_/, RegExp)).to.equal(true);
608 it("should respect the parent property of a custom object", function(){
609 var X = function(){};
611 expect(instanceOf(new X, Array)).to.equal(true);
615 var dit = typeof window != 'undefined' && window.Element && Element.set ? it : xit;
616 dit("should return true for Element instances", function(){
617 expect(instanceOf(new Element('div'), Element)).to.equal(true);
622 describe('Array.from', function(){
624 it('should return the same array', function(){
626 var arr2 = Array.from(arr1);
627 expect(arr1).to.equal(arr2);
630 it('should return an array for arguments', function(){
631 var fnTest = function(){
632 return Array.from(arguments);
634 var arr = fnTest(1,2,3);
635 expect(Type.isArray(arr)).to.equal(true);
636 expect(arr.length).to.equal(3);
639 it('should transform a non array into an array', function(){
640 expect(Array.from(1)).to.eql([1]);
643 it('should transforum an undefined or null into an empty array', function(){
644 expect(Array.from(null)).to.eql([]);
645 expect(Array.from(undefined)).to.eql([]);
648 it('should ignore and return an array', function(){
649 expect(Array.from([1,2,3])).to.eql([1,2,3]);
652 it('should return a copy of arguments or the arguments if it is of type array', function(){
653 // In Opera arguments is an array so it does not return a copy
654 // This is intended. Array.from is expected to return an Array from an array-like-object
655 // It does not make a copy when the passed in value is an array already
656 var args, type, copy = (function(){
657 type = typeOf(arguments);
660 return Array.from(arguments);
663 if (type === 'array'){
664 expect(copy).to.equal(args);
666 expect(copy).to.not.equal(args);
672 describe('String.from', function(){
674 it('should convert to type string', function(){
675 expect(typeOf(String.from('string'))).to.equal('string');
677 expect(typeOf(String.from(1))).to.equal('string');
679 expect(typeOf(String.from(new Date))).to.equal('string');
681 expect(typeOf(String.from(function(){}))).to.equal('string');
686 describe('Function.from', function(){
688 it('if a function is passed in that function should be returned', function(){
689 var fn = function(a,b){ return a; };
690 expect(Function.from(fn)).to.equal(fn);
693 it('should return a function that returns the value passed when called', function(){
694 expect(Function.from('hello world!')()).to.equal('hello world!');
699 describe('Number.from', function(){
701 it('should return the number representation of a string', function(){
702 expect(Number.from("10")).to.equal(10);
703 expect(Number.from("10px")).to.equal(10);
706 it('should return null when it fails to return a number type', function(){
707 expect(Number.from("ciao")).to.equal(null);
712 describe('Type', function(){
714 var Instrument = new Type('Instrument', function(name){
719 return 'playing ' + this.name;
724 var Car = new Type('Car', function(name){
729 return 'driving a ' + this.name;
734 it('should allow implementation over existing methods when a method is not protected', function(){
735 Instrument.implement({
737 return 'playing a guitar';
740 var myInstrument = new Instrument('Guitar');
741 expect(myInstrument.method()).to.equal('playing a guitar');
744 it('should not override a method when it is protected', function(){
750 var myCar = new Car('nice car');
751 expect(myCar.method()).to.equal('driving a nice car');
754 it('should allow generic calls', function(){
755 expect(Car.method({name: 'not so nice car'})).to.equal('driving a not so nice car');
758 it("should be a Type", function(){
759 expect(Type.isType(Instrument)).to.equal(true);
762 it("should generate and evaluate correct types", function(){
763 var myCar = new Car('nice car');
764 expect(Type.isCar(myCar)).to.equal(true);
767 it("isEnumerable method on Type should return true for arrays, arguments, objects with a numerical length property", function(){
768 expect(Type.isEnumerable([1,2,3])).to.equal(true);
770 expect(Type.isEnumerable(arguments)).to.equal(true);
772 expect(Type.isEnumerable({length: 2})).to.equal(true);
775 it('sould chain any function on a type', function(){
776 var MyType = new Type('MyType', function(){}.implement({
780 expect(MyType.alias('a', 'b').implement({
783 staticMethod: function(){}
784 })).to.equal(MyType);
789 describe('Object.keys', function(){
791 var object = { a: 'string', b: 233, c: {} };
793 it('keys should return an empty array', function(){
794 expect(Object.keys({})).to.eql([]);
797 it('should return an array containing the keys of the object', function(){
798 expect(Object.keys(object)).to.eql(['a', 'b', 'c']);
801 it('should return an array containing non-enum keys', function(){
802 var buggy = {constructor: 'foo', valueOf: 'bar'};
803 var keys = Object.keys(buggy).join('');
804 expect(keys.indexOf('constructor')).to.not.equal(-1);
805 expect(keys.indexOf('valueOf')).to.not.equal(-1);
810 describe('Object.each', function(){
812 it('should call the function for each item in the object', function(){
814 Object.each({first: "Sunday", second: "Monday", third: "Tuesday"}, function(value, key){
815 daysObj[key] = value;
818 expect(daysObj).to.eql({first: 'Sunday', second: 'Monday', third: 'Tuesday'});
821 it('should call non-enumerable properties too', function(){
824 constructor: "constructor",
825 hasOwnProperty: "hasOwnProperty",
826 isPrototypeOf: "isPrototypeOf",
827 propertyIsEnumerable: "propertyIsEnumerable",
828 toLocaleString: "toLocaleString",
829 toString: "toString",
833 var keysInObject = true, iteration = 0;
834 var props = ['foo', 'hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'].join('');
836 Object.each(obj, function(i, k){
838 if (props.indexOf(k) == -1) keysInObject = false;
841 expect(keysInObject).to.equal(true);
842 expect(iteration).to.equal(8);
847 describe('Array.each', function(){
849 it('should call the function for each item in Function arguments', function(){
852 Array.each(Array.from(arguments), function(value, key){
853 daysArr[key] = value;
855 })('Sun','Mon','Tue');
857 expect(daysArr).to.eql(['Sun','Mon','Tue']);
860 it('should call the function for each item in the array', function(){
862 Array.each(['Sun','Mon','Tue'], function(value, i){
866 expect(daysArr).to.eql(['Sun','Mon','Tue']);
869 it('should not iterate over deleted elements', function(){
870 var array = [0, 1, 2, 3],
875 array.each(function(value){
876 testArray.push(value);
879 expect(testArray).to.eql([0, 3]);
884 describe('Array.clone', function(){
885 it('should recursively clone and dereference arrays and objects, while mantaining the primitive values', function(){
886 var a = [1,2,3, [1,2,3, {a: [1,2,3]}]];
887 var b = Array.clone(a);
888 expect(a).to.not.equal(b);
889 expect(a[3]).to.not.equal(b[3]);
890 expect(a[3][3]).to.not.equal(b[3][3]);
891 expect(a[3][3].a).to.not.equal(b[3][3].a);
893 expect(a[3]).to.eql(b[3]);
894 expect(a[3][3]).to.eql(b[3][3]);
895 expect(a[3][3].a).to.eql(b[3][3].a);
899 describe('Object.clone', function(){
900 it('should recursively clone and dereference arrays and objects, while mantaining the primitive values', function(){
901 var a = {a:[1,2,3, [1,2,3, {a: [1,2,3]}]]};
902 var b = Object.clone(a);
903 expect(a).to.not.equal(b);
904 expect(a.a[3]).to.not.equal(b.a[3]);
905 expect(a.a[3][3]).to.not.equal(b.a[3][3]);
906 expect(a.a[3][3].a).to.not.equal(b.a[3][3].a);
908 expect(a.a[3]).to.eql(b.a[3]);
909 expect(a.a[3][3]).to.eql(b.a[3][3]);
910 expect(a.a[3][3].a).to.eql(b.a[3][3].a);
914 describe('Object.merge', function(){
916 it('should merge any object inside the passed in object, and should return the passed in object', function(){
917 var a = {a:1, b:2, c: {a:1, b:2, c:3}};
918 var b = {c: {d:4}, d:4};
919 var c = {a: 5, c: {a:5}};
921 var merger = Object.merge(a, b);
923 expect(merger).to.eql({a:1, b:2, c:{a:1, b:2, c:3, d:4}, d:4});
924 expect(merger).to.equal(a);
926 expect(Object.merge(a, b, c)).to.eql({a:5, b:2, c:{a:5, b:2, c:3, d:4}, d:4});
929 it('should recursively clone sub objects and sub-arrays', function(){
930 var a = {a:1, b:2, c: {a:1, b:2, c:3}, d: [1,2,3]};
931 var b = {e: {a:1}, f: [1,2,3]};
933 var merger = Object.merge(a, b);
935 expect(a.e).to.not.equal(b.e);
936 expect(a.f).to.not.equal(b.f);
941 describe('Object.append', function(){
942 it('should combine two objects', function(){
943 var a = {a: 1, b: 2}, b = {b: 3, c: 4};
944 expect(Object.append(a, b)).to.eql({a: 1, b: 3, c: 4});
946 a = {a: 1, b: 2}; b = {b: 3, c: 4};
947 expect(Object.append(a, b)).to.equal(a);
949 a = {a: 1, b: 2}; b = {b: 3, c: 4};
950 var c = {a: 2, d: 5};
951 expect(Object.append(a, b, c)).to.eql({a: 2, b: 3, c: 4, d: 5});
955 describe('Date.now', function(){
957 it('should return a timestamp', function(){
958 expect(Type.isNumber(Date.now())).to.equal(true);
963 describe('String.uniqueID', function(){
965 it('should be a string', function(){
966 expect(typeof String.uniqueID()).to.equal('string');
969 it("should generate unique ids", function(){
970 expect(String.uniqueID()).to.not.equal(String.uniqueID());
975 describe('typeOf Client', function(){
977 var dit = typeof document == 'undefined' ? xit : it;
978 dit("should return 'collection' for HTMLElements collections", function(){
979 expect(typeOf(document.getElementsByTagName('*'))).to.equal('collection');
982 dit("should return 'element' for an Element", function(){
983 var div = document.createElement('div');
984 expect(typeOf(div)).to.equal('element');
988 if (typeof window != 'undefined' && window.Elements) dit("should return 'elements' for Elements", function(){
989 expect(typeOf(new Elements)).to.equal('elements');
992 if (typeof window != 'undefined' && window.Browser) dit("should return 'window' for the window object", function(){
993 expect(typeOf(window)).to.equal('window');
996 if (typeof window != 'undefined' && window.Browser) dit("should return 'document' for the document object", function(){
997 expect(typeOf(document)).to.equal('document');
1002 describe('Array.from', function(){
1004 var dit = typeof document == 'undefined' ? xit : it;
1005 dit('should return an array for an Elements collection', function(){
1006 var div1 = document.createElement('div');
1007 var div2 = document.createElement('div');
1008 var div3 = document.createElement('div');
1010 div1.appendChild(div2);
1011 div1.appendChild(div3);
1013 var array = Array.from(div1.getElementsByTagName('*'));
1014 expect(Type.isArray(array)).to.equal(true);
1017 dit('should return an array for an Options collection', function(){
1018 var div = document.createElement('div');
1019 div.innerHTML = '<select><option>a</option></select>';
1020 var select = div.firstChild;
1021 var array = Array.from(select.options);
1022 expect(Type.isArray(array)).to.equal(true);
1028 describe('Core', function(){
1030 describe('typeOf', function(){
1031 it('should correctly report the type of arguments when using "use strict"', function(){
1033 expect(typeOf(arguments)).to.equal('arguments');