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){ 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);
286 describe('$type', function(){
288 it('should return "array" for Array objects', function(){
289 expect($type([1, 2])).to.equal('array');
292 it('should return "string" for String objects', function(){
293 expect($type('ciao')).to.equal('string');
296 it('should return "regexp" for RegExp objects', function(){
297 expect($type(/_/)).to.equal('regexp');
300 it('should return "function" for Function objects', function(){
301 expect($type(function(){})).to.equal('function');
304 it('should return "number" for Number objects', function(){
305 expect($type(10)).to.equal('number');
306 expect($type(NaN)).to.not.equal('number');
309 it('should return "boolean" for Boolean objects', function(){
310 expect($type(true)).to.equal('boolean');
311 expect($type(false)).to.equal('boolean');
314 it('should return "object" for Object objects', function(){
315 expect($type({a:2})).to.equal('object');
318 it('should return "arguments" for Function arguments', function(){
319 if (window.opera){ // Seems like the Opera guys can't decide on this.
320 var type = $type(arguments);
321 expect(type == 'array' || type == 'arguments').to.equal(true);
325 expect($type(arguments)).to.equal('arguments');
328 it('should return false for null objects', function(){
329 expect($type(null)).to.equal(false);
332 it('should return false for undefined objects', function(){
333 expect($type(undefined)).to.equal(false);
336 it('should return "collection" for HTMLElements collections', function(){
337 expect($type(document.getElementsByTagName('*'))).to.equal('collection');
340 it('should return "element" for an Element', function(){
341 var div = document.createElement('div');
342 expect($type(div)).to.equal('element');
345 it('should return "array" for Elements', function(){
346 expect($type(new Elements)).to.equal('array');
349 it('should return "window" for the window object', function(){
350 expect($type(window)).to.equal('window');
353 it('should return "document" for the document object', function(){
354 expect($type(document)).to.equal('document');
359 describe('$unlink', function(){
361 it('should unlink an object recursivly', function(){
363 var obj = {a: 1, inner: inner};
364 var copy = $unlink(obj);
368 expect(obj.a).to.equal(10);
369 expect(obj.inner.b).to.equal(20);
370 expect($type(obj)).to.equal('object');
372 expect(copy.a).to.equal(1);
373 expect(copy.inner.b).to.equal(2);
374 expect($type(copy)).to.equal('object');
377 it('should unlink an Hash', function(){
378 var hash = new Hash({a: 'one'});
379 var copy = $unlink(hash);
381 expect($type(hash)).to.equal('hash');
382 expect($type(copy)).to.equal('hash');
384 copy.set('a', 'two');
386 expect(hash.get('a')).to.equal('one');
387 expect(copy.get('a')).to.equal('two');
392 describe('Hash.getLength', function(){
394 it('should return the number of items in it', function(){
395 var hash = new Hash({});
396 expect(hash.getLength()).to.equal(0);
397 hash.set('mootools', 'awesome');
399 expect(hash.getLength()).to.equal(2);
402 it('should not fail when length is set', function(){
403 var hash = new Hash({'length': 10});
404 expect(hash.getLength()).to.equal(1);
407 it('should work as a generic on objects', function(){
408 expect(Hash.getLength({})).to.equal(0);
409 expect(Hash.getLength({'': '', '0': '0', 'length': 99})).to.equal(3);
414 describe('$H', function(){
416 it('should create a new hash', function(){
418 expect($type(hash)).to.equal('hash');
424 describe('Function.prototype.overloadSetter', function(){
426 var collector, setter;
427 beforeEach(function(){
429 setter = (function(key, value){
430 collector[key] = value;
434 it('should call a specific setter', function(){
435 setter = setter.overloadSetter();
436 setter('key', 'value');
438 expect(collector).to.eql({key: 'value'});
445 expect(collector).to.eql({
454 setter('otherKey', 4);
456 expect(collector).to.eql({
463 it('should only works with objects in plural mode', function(){
464 setter = setter.overloadSetter(true);
471 expect(collector).to.eql({
479 describe('Function.prototype.overloadGetter', function(){
482 beforeEach(function(){
489 getter = (function(key){
490 return object[key] || null;
494 it('should call a getter for each argument', function(){
495 getter = getter.overloadGetter();
497 expect(getter('aa')).to.equal(1);
498 expect(getter('bb')).to.equal(2);
499 expect(getter('cc')).to.equal(3);
500 expect(getter('dd')).to.equal(null);
502 expect(getter('aa', 'bb', 'cc')).to.eql(object);
503 expect(getter(['aa', 'bb', 'cc'])).to.eql(object);
504 expect(getter(['aa', 'cc', 'dd'])).to.eql({aa: 1, cc: 3, dd: null});
507 it('should work in plural mode', function(){
508 getter = getter.overloadGetter(true);
510 expect(getter('aa')).to.eql({
514 expect(getter(['aa', 'bb'])).to.eql({
522 describe('typeOf', function(){
524 it('should return "array" for Array objects', function(){
525 expect(typeOf([1, 2])).to.equal('array');
528 it('should return "string" for String objects', function(){
529 expect(typeOf('ciao')).to.equal('string');
532 it('should return "regexp" for RegExp objects', function(){
533 expect(typeOf(/_/)).to.equal('regexp');
536 it('should return "function" for Function objects', function(){
537 expect(typeOf(function(){})).to.equal('function');
540 it('should return "number" for Number objects', function(){
541 expect(typeOf(10)).to.equal('number');
542 expect(typeOf(NaN)).to.not.equal('number');
545 it('should return "boolean" for Boolean objects', function(){
546 expect(typeOf(true)).to.equal('boolean');
547 expect(typeOf(false)).to.equal('boolean');
550 it('should return "object" for Object objects', function(){
551 expect(typeOf({a:2})).to.equal('object');
554 it('should return "arguments" for Function arguments', function(){
555 if (typeof window != 'undefined' && window.opera){ // Seems like the Opera guys can't decide on this
556 var type = typeOf(arguments);
557 expect(type == 'array' || type == 'arguments').to.equal(true);
561 expect(typeOf(arguments)).to.equal('arguments');
564 it('should return "null" for null objects', function(){
565 expect(typeOf(null)).to.equal('null');
568 it('should return "null" for undefined objects', function(){
569 expect(typeOf(undefined)).to.equal('null');
574 describe('instanceOf', function(){
576 it('should return false on null object', function(){
577 expect(instanceOf(null, null)).to.equal(false);
580 it('should return true for Arrays', function(){
581 expect(instanceOf([], Array)).to.equal(true);
584 it('should return true for Numbers', function(){
585 expect(instanceOf(1, Number)).to.equal(true);
588 it('should return true for Objects', function(){
589 expect(instanceOf({}, Object)).to.equal(true);
592 it('should return true for Dates', function(){
593 expect(instanceOf(new Date(), Date)).to.equal(true);
596 it('should return true for Booleans', function(){
597 expect(instanceOf(true, Boolean)).to.equal(true);
600 it('should return true for RegExps', function(){
601 expect(instanceOf(/_/, RegExp)).to.equal(true);
604 it('should respect the parent property of a custom object', function(){
605 var X = function(){};
607 expect(instanceOf(new X, Array)).to.equal(true);
611 var dit = typeof window != 'undefined' && window.Element && Element.set ? it : xit;
612 dit('should return true for Element instances', function(){
613 expect(instanceOf(new Element('div'), Element)).to.equal(true);
618 describe('Array.convert', function(){
620 it('should return the same array', function(){
621 var arr1 = [1, 2, 3];
622 var arr2 = Array.convert(arr1);
623 expect(arr1).to.equal(arr2);
626 it('should return an array for arguments', function(){
627 var fnTest = function(){
628 return Array.convert(arguments);
630 var arr = fnTest(1, 2, 3);
631 expect(Type.isArray(arr)).to.equal(true);
632 expect(arr.length).to.equal(3);
635 it('should transform a non array into an array', function(){
636 expect(Array.convert(1)).to.eql([1]);
639 it('should transforum an undefined or null into an empty array', function(){
640 expect(Array.convert(null)).to.eql([]);
641 expect(Array.convert(undefined)).to.eql([]);
644 it('should ignore and return an array', function(){
645 expect(Array.convert([1, 2, 3])).to.eql([1, 2, 3]);
648 it('should return a copy of arguments or the arguments if it is of type array', function(){
649 // In Opera arguments is an array so it does not return a copy
650 // This is intended. Array.convert is expected to return an Array from an array-like-object
651 // It does not make a copy when the passed in value is an array already
655 type = typeOf(arguments);
658 return Array.convert(arguments);
661 if (type === 'array'){
662 expect(copy).to.equal(args);
664 expect(copy).to.not.equal(args);
669 describe('String.convert', function(){
671 it('should convert to type string', function(){
672 expect(typeOf(String.convert('string'))).to.equal('string');
673 expect(typeOf(String.convert(1))).to.equal('string');
674 expect(typeOf(String.convert(new Date))).to.equal('string');
675 expect(typeOf(String.convert(function(){}))).to.equal('string');
680 describe('Function.convert', function(){
682 it('if a function is passed in that function should be returned', function(){
683 var fn = function(a){ return a; };
684 expect(Function.convert(fn)).to.equal(fn);
687 it('should return a function that returns the value passed when called', function(){
688 expect(Function.convert('hello world!')()).to.equal('hello world!');
693 describe('Number.convert', function(){
695 it('should return the number representation of a string', function(){
696 expect(Number.convert('10')).to.equal(10);
697 expect(Number.convert('10px')).to.equal(10);
700 it('should return null when it fails to return a number type', function(){
701 expect(Number.convert('ciao')).to.equal(null);
706 describe('Type', function(){
708 var Instrument = new Type('Instrument', function(name){
713 return 'playing ' + this.name;
718 var Car = new Type('Car', function(name){
723 return 'driving a ' + this.name;
728 it('should allow implementation over existing methods when a method is not protected', function(){
729 Instrument.implement({
731 return 'playing a guitar';
734 var myInstrument = new Instrument('Guitar');
735 expect(myInstrument.method()).to.equal('playing a guitar');
738 it('should not override a method when it is protected', function(){
744 var myCar = new Car('nice car');
745 expect(myCar.method()).to.equal('driving a nice car');
748 it('should allow generic calls', function(){
749 expect(Car.method({name: 'not so nice car'})).to.equal('driving a not so nice car');
752 it('should be a Type', function(){
753 expect(Type.isType(Instrument)).to.equal(true);
756 it('should generate and evaluate correct types', function(){
757 var myCar = new Car('nice car');
758 expect(Type.isCar(myCar)).to.equal(true);
761 it('isEnumerable method on Type should return true for arrays, arguments, objects with a numerical length property', function(){
762 expect(Type.isEnumerable([1, 2, 3])).to.equal(true);
764 expect(Type.isEnumerable(arguments)).to.equal(true);
766 expect(Type.isEnumerable({length: 2})).to.equal(true);
769 it('sould chain any function on a type', function(){
770 var MyType = new Type('MyType', function(){}.implement({
774 expect(MyType.alias('a', 'b').implement({
777 staticMethod: function(){}
778 })).to.equal(MyType);
783 describe('Object.keys', function(){
785 var object = { a: 'string', b: 233, c: {} };
787 it('keys should return an empty array', function(){
788 expect(Object.keys({})).to.eql([]);
791 it('should return an array containing the keys of the object', function(){
792 expect(Object.keys(object)).to.eql(['a', 'b', 'c']);
795 it('should return an array containing non-enum keys', function(){
796 var buggy = {constructor: 'foo', valueOf: 'bar'};
797 var keys = Object.keys(buggy).join('');
798 expect(keys.indexOf('constructor')).to.not.equal(-1);
799 expect(keys.indexOf('valueOf')).to.not.equal(-1);
804 describe('Object.each', function(){
806 it('should call the function for each item in the object', function(){
808 Object.each({first: 'Sunday', second: 'Monday', third: 'Tuesday'}, function(value, key){
809 daysObj[key] = value;
812 expect(daysObj).to.eql({first: 'Sunday', second: 'Monday', third: 'Tuesday'});
815 it('should call non-enumerable properties too', function(){
818 constructor: 'constructor',
819 hasOwnProperty: 'hasOwnProperty',
820 isPrototypeOf: 'isPrototypeOf',
821 propertyIsEnumerable: 'propertyIsEnumerable',
822 toLocaleString: 'toLocaleString',
823 toString: 'toString',
827 var keysInObject = true, iteration = 0;
828 var props = ['foo', 'hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor'].join('');
830 Object.each(obj, function(i, k){
832 if (props.indexOf(k) == -1) keysInObject = false;
835 expect(keysInObject).to.equal(true);
836 expect(iteration).to.equal(8);
841 describe('Array.each', function(){
843 it('should call the function for each item in Function arguments', function(){
846 Array.each(Array.convert(arguments), function(value, key){
847 daysArr[key] = value;
849 })('Sun', 'Mon', 'Tue');
851 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
854 it('should call the function for each item in the array', function(){
856 Array.each(['Sun', 'Mon', 'Tue'], function(value){
860 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
863 it('should not iterate over deleted elements', function(){
864 var array = [0, 1, 2, 3],
869 array.each(function(value){
870 testArray.push(value);
873 expect(testArray).to.eql([0, 3]);
878 describe('Array.clone', function(){
880 it('should recursively clone and dereference arrays and objects, while mantaining the primitive values', function(){
881 var a = [1, 2, 3, [1, 2, 3, {a: [1, 2, 3]}]];
882 var b = Array.clone(a);
883 expect(a).to.not.equal(b);
884 expect(a[3]).to.not.equal(b[3]);
885 expect(a[3][3]).to.not.equal(b[3][3]);
886 expect(a[3][3].a).to.not.equal(b[3][3].a);
888 expect(a[3]).to.eql(b[3]);
889 expect(a[3][3]).to.eql(b[3][3]);
890 expect(a[3][3].a).to.eql(b[3][3].a);
895 describe('Object.clone', function(){
897 it('should recursively clone and dereference arrays and objects, while mantaining the primitive values', function(){
898 var a = {a:[1, 2, 3, [1, 2, 3, {a: [1, 2, 3]}]]};
899 var b = Object.clone(a);
900 expect(a).to.not.equal(b);
901 expect(a.a[3]).to.not.equal(b.a[3]);
902 expect(a.a[3][3]).to.not.equal(b.a[3][3]);
903 expect(a.a[3][3].a).to.not.equal(b.a[3][3].a);
905 expect(a.a[3]).to.eql(b.a[3]);
906 expect(a.a[3][3]).to.eql(b.a[3][3]);
907 expect(a.a[3][3].a).to.eql(b.a[3][3].a);
912 describe('Object.merge', function(){
914 it('should merge any object inside the passed in object, and should return the passed in object', function(){
915 var a = {a:1, b:2, c: {a:1, b:2, c:3}};
916 var b = {c: {d:4}, d:4};
917 var c = {a: 5, c: {a:5}};
919 var merger = Object.merge(a, b);
921 expect(merger).to.eql({a:1, b:2, c:{a:1, b:2, c:3, d:4}, d:4});
922 expect(merger).to.equal(a);
924 expect(Object.merge(a, b, c)).to.eql({a:5, b:2, c:{a:5, b:2, c:3, d:4}, d:4});
927 it('should recursively clone sub objects and sub-arrays', function(){
928 var a = {a:1, b:2, c: {a:1, b:2, c:3}, d: [1, 2, 3]};
929 var b = {e: {a:1}, f: [1, 2, 3]};
933 expect(a.e).to.not.equal(b.e);
934 expect(a.f).to.not.equal(b.f);
939 describe('Object.append', function(){
941 it('should combine two objects', function(){
942 var a = {a: 1, b: 2}, b = {b: 3, c: 4};
943 expect(Object.append(a, b)).to.eql({a: 1, b: 3, c: 4});
945 a = {a: 1, b: 2}; b = {b: 3, c: 4};
946 expect(Object.append(a, b)).to.equal(a);
948 a = {a: 1, b: 2}; b = {b: 3, c: 4};
949 var c = {a: 2, d: 5};
950 expect(Object.append(a, b, c)).to.eql({a: 2, b: 3, c: 4, d: 5});
956 describe('Date.now', function(){
958 it('should return a timestamp', function(){
959 expect(Type.isNumber(Date.now())).to.equal(true);
965 describe('String.uniqueID', function(){
967 it('should be a string', function(){
968 expect(typeof String.uniqueID()).to.equal('string');
971 it('should generate unique ids', function(){
972 expect(String.uniqueID()).to.not.equal(String.uniqueID());
977 describe('typeOf Client', function(){
979 var dit = typeof document == 'undefined' ? xit : it;
980 dit('should return "collection" for HTMLElements collections', function(){
981 expect(typeOf(document.getElementsByTagName('*'))).to.equal('collection');
984 dit('should return "element" for an Element', function(){
985 var div = document.createElement('div');
986 expect(typeOf(div)).to.equal('element');
990 if (typeof window != 'undefined' && window.Elements) dit('should return "elements" for Elements', function(){
991 expect(typeOf(new Elements)).to.equal('elements');
994 if (typeof window != 'undefined' && window.Browser) dit('should return "window" for the window object', function(){
995 expect(typeOf(window)).to.equal('window');
998 if (typeof window != 'undefined' && window.Browser) dit('should return "document" for the document object', function(){
999 expect(typeOf(document)).to.equal('document');
1004 describe('Array.convert', function(){
1006 var dit = typeof document == 'undefined' ? xit : it;
1007 dit('should return an array for an Elements collection', function(){
1008 var div1 = document.createElement('div');
1009 var div2 = document.createElement('div');
1010 var div3 = document.createElement('div');
1012 div1.appendChild(div2);
1013 div1.appendChild(div3);
1015 var array = Array.convert(div1.getElementsByTagName('*'));
1016 expect(Type.isArray(array)).to.equal(true);
1019 dit('should return an array for an Options collection', function(){
1020 var div = document.createElement('div');
1021 div.innerHTML = '<select><option>a</option></select>';
1022 var select = div.firstChild;
1023 var array = Array.convert(select.options);
1024 expect(Type.isArray(array)).to.equal(true);
1029 describe('Core', function(){
1031 describe('typeOf', function(){
1033 it('should correctly report the type of arguments when using "use strict"', function(){
1035 expect(typeOf(arguments)).to.equal('arguments');