Merge pull request #2789 from SergioCrisostomo/upgrade-karma-sauce-launcher
[mootools.git] / Specs / Core / Core.js
blob9e368c4321764eda65d9c1bb7b4b4783536db35c
1 /*
2 ---
3 name: Core
4 requires: ~
5 provides: ~
6 ...
7 */
9 //<1.2compat>
10 describe('$A', function(){
12         it('should return a copy for an array', function(){
13                 var arr1 = [1, 2, 3];
14                 var arr2 = $A(arr1);
15                 expect(arr1).to.not.equal(arr2);
16         });
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);
28         });
30         it('should return an array for arguments', function(){
31                 var fnTest = function(){
32                         return $A(arguments);
33                 };
34                 var arr = fnTest(1, 2, 3);
35                 expect(Array.type(arr)).to.equal(true);
36                 expect(arr.length).to.equal(3);
37         });
39 });
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');
48         });
50 });
52 describe('$chk', function(){
54         it('should return false on false', function(){
55                 expect($chk(false)).to.equal(false);
56         });
58         it('should return false on null', function(){
59                 expect($chk(null)).to.equal(false);
60         });
62         it('should return false on undefined', function(){
63                 expect($chk(undefined)).to.equal(false);
64         });
66         it('should return true on 0', function(){
67                 expect($chk(0)).to.equal(true);
68         });
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);
74         });
76 });
78 describe('$clear', function(){
80         it('should clear timeouts', function(){
81                 var timeout = setTimeout(function(){}, 100);
82                 expect($clear(timeout)).to.equal(null);
83         });
85         it('should clear intervals', function(){
86                 var interval = setInterval(function(){}, 100);
87                 expect($clear(interval)).to.equal(null);
88         });
90 });
92 describe('$defined', function(){
94         it('should return true on 0', function(){
95                 expect($defined(0)).to.equal(true);
96         });
98         it('should return true on false', function(){
99                 expect($defined(false)).to.equal(true);
100         });
102         it('should return false on null', function(){
103                 expect($defined(null)).to.equal(false);
104         });
106         it('should return false on undefined', function(){
107                 expect($defined(undefined)).to.equal(false);
108         });
112 describe('$each', function(){
114         it('should call the function for each item in Function arguments', function(){
115                 var daysArr = [];
116                 (function(){
117                         $each(arguments, function(value, key){
118                                 daysArr[key] = value;
119                         });
120                 })('Sun', 'Mon', 'Tue');
122                 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
123         });
125         it('should call the function for each item in the array', function(){
126                 var daysArr = [];
127                 $each(['Sun', 'Mon', 'Tue'], function(value, key){
128                         daysArr[key] = value;
129                 });
131                 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
132         });
134         it('should call the function for each item in the object', function(){
135                 var daysObj = {};
136                 $each({first: 'Sunday', second: 'Monday', third: 'Tuesday'}, function(value, key){
137                         daysObj[key] = value;
138                 });
140                 expect(daysObj).to.eql({first: 'Sunday', second: 'Monday', third: 'Tuesday'});
141         });
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};
150                 $extend(obj1, obj2);
151                 expect(obj1).to.eql({a: 1, b: 3, c: 4});
152         });
154         it('should overwrite properties', function(){
155                 var obj1 = {a: 1, b: 2};
156                 var obj2 = {b: 3, c: 4, a: 5};
157                 $extend(obj1, obj2);
158                 expect(obj1).to.eql({a: 5, b: 3, c: 4});
159         });
161         it('should not extend with null argument', function(){
162                 var obj1 = {a: 1, b: 2};
163                 $extend(obj1);
164                 expect(obj1).to.eql({a: 1, b: 2});
165         });
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);
174         });
176         it('should return a function that returns the value passed when called', function(){
177                 expect($lambda('hello world!')()).to.equal('hello world!');
178         });
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);
188         });
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});
195         });
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);
204         });
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]);
209         });
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);
218         });
222 describe('$splat', function(){
224         it('should transform a non array into an array', function(){
225                 expect($splat(1)).to.eql([1]);
226         });
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([]);
231         });
233         it('should ignore and return an array', function(){
234                 expect($splat([1, 2, 3])).to.eql([1, 2, 3]);
235         });
239 describe('$time', function(){
241         it('should return a timestamp', function(){
242                 expect(Number.type($time())).to.equal(true);
243         });
245         it('should be within a reasonable range', function(){
246                 var time = $time();
247                 expect(time).to.be.greaterThan(1e12);
248                 expect(time).to.be.lessThan(1e13);
249         });
253 describe('$try', function(){
255         it('should return the result of the first successful function without executing successive functions', function(){
256                 var calls = 0;
257                 var attempt = $try(function(){
258                         calls++;
259                         throw new Exception();
260                 }, function(){
261                         calls++;
262                         return 'success';
263                 }, function(){
264                         calls++;
265                         return 'moo';
266                 });
267                 expect(calls).to.equal(2);
268                 expect(attempt).to.equal('success');
269         });
271         it('should return null when no function succeeded', function(){
272                 var calls = 0;
273                 var attempt = $try(function(){
274                         calls++;
275                         return I_invented_this();
276                 }, function(){
277                         calls++;
278                         return uninstall_ie();
279                 });
280                 expect(calls).to.equal(2);
281                 expect(attempt).to.equal(null);
282         });
286 describe('$type', function(){
288         it('should return "array" for Array objects', function(){
289                 expect($type([1, 2])).to.equal('array');
290         });
292         it('should return "string" for String objects', function(){
293                 expect($type('ciao')).to.equal('string');
294         });
296         it('should return "regexp" for RegExp objects', function(){
297                 expect($type(/_/)).to.equal('regexp');
298         });
300         it('should return "function" for Function objects', function(){
301                 expect($type(function(){})).to.equal('function');
302         });
304         it('should return "number" for Number objects', function(){
305                 expect($type(10)).to.equal('number');
306                 expect($type(NaN)).to.not.equal('number');
307         });
309         it('should return "boolean" for Boolean objects', function(){
310                 expect($type(true)).to.equal('boolean');
311                 expect($type(false)).to.equal('boolean');
312         });
314         it('should return "object" for Object objects', function(){
315                 expect($type({a:2})).to.equal('object');
316         });
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);
322                         return;
323                 }
325                 expect($type(arguments)).to.equal('arguments');
326         });
328         it('should return false for null objects', function(){
329                 expect($type(null)).to.equal(false);
330         });
332         it('should return false for undefined objects', function(){
333                 expect($type(undefined)).to.equal(false);
334         });
336         it('should return "collection" for HTMLElements collections', function(){
337                 expect($type(document.getElementsByTagName('*'))).to.equal('collection');
338         });
340         it('should return "element" for an Element', function(){
341                 var div = document.createElement('div');
342                 expect($type(div)).to.equal('element');
343         });
345         it('should return "array" for Elements', function(){
346                 expect($type(new Elements)).to.equal('array');
347         });
349         it('should return "window" for the window object', function(){
350                 expect($type(window)).to.equal('window');
351         });
353         it('should return "document" for the document object', function(){
354                 expect($type(document)).to.equal('document');
355         });
359 describe('$unlink', function(){
361         it('should unlink an object recursivly', function(){
362                 var inner = {b: 2};
363                 var obj = {a: 1, inner: inner};
364                 var copy = $unlink(obj);
365                 obj.a = 10;
366                 inner.b = 20;
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');
375         });
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');
388         });
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');
398                 hash.milk = 'yummy';
399                 expect(hash.getLength()).to.equal(2);
400         });
402         it('should not fail when length is set', function(){
403                 var hash = new Hash({'length': 10});
404                 expect(hash.getLength()).to.equal(1);
405         });
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);
410         });
414 describe('$H', function(){
416         it('should create a new hash', function(){
417                 var hash = $H({});
418                 expect($type(hash)).to.equal('hash');
419         });
422 //</1.2compat>
424 describe('Function.prototype.overloadSetter', function(){
426         var collector, setter;
427         beforeEach(function(){
428                 collector = {};
429                 setter = (function(key, value){
430                         collector[key] = value;
431                 });
432         });
434         it('should call a specific setter', function(){
435                 setter = setter.overloadSetter();
436                 setter('key', 'value');
438                 expect(collector).to.eql({key: 'value'});
440                 setter({
441                         otherKey: 1,
442                         property: 2
443                 });
445                 expect(collector).to.eql({
446                         key: 'value',
447                         otherKey: 1,
448                         property: 2
449                 });
451                 setter({
452                         key: 3
453                 });
454                 setter('otherKey', 4);
456                 expect(collector).to.eql({
457                         key: 3,
458                         otherKey: 4,
459                         property: 2
460                 });
461         });
463         it('should only works with objects in plural mode', function(){
464                 setter = setter.overloadSetter(true);
466                 setter({
467                         a: 'b',
468                         c: 'd'
469                 });
471                 expect(collector).to.eql({
472                         a: 'b',
473                         c: 'd'
474                 });
475         });
479 describe('Function.prototype.overloadGetter', function(){
481         var object, getter;
482         beforeEach(function(){
483                 object = {
484                         aa: 1,
485                         bb: 2,
486                         cc: 3
487                 };
489                 getter = (function(key){
490                         return object[key] || null;
491                 });
492         });
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});
505         });
507         it('should work in plural mode', function(){
508                 getter = getter.overloadGetter(true);
510                 expect(getter('aa')).to.eql({
511                         aa: 1
512                 });
514                 expect(getter(['aa', 'bb'])).to.eql({
515                         aa: 1,
516                         bb: 2
517                 });
518         });
522 describe('typeOf', function(){
524         it('should return "array" for Array objects', function(){
525                 expect(typeOf([1, 2])).to.equal('array');
526         });
528         it('should return "string" for String objects', function(){
529                 expect(typeOf('ciao')).to.equal('string');
530         });
532         it('should return "regexp" for RegExp objects', function(){
533                 expect(typeOf(/_/)).to.equal('regexp');
534         });
536         it('should return "function" for Function objects', function(){
537                 expect(typeOf(function(){})).to.equal('function');
538         });
540         it('should return "number" for Number objects', function(){
541                 expect(typeOf(10)).to.equal('number');
542                 expect(typeOf(NaN)).to.not.equal('number');
543         });
545         it('should return "boolean" for Boolean objects', function(){
546                 expect(typeOf(true)).to.equal('boolean');
547                 expect(typeOf(false)).to.equal('boolean');
548         });
550         it('should return "object" for Object objects', function(){
551                 expect(typeOf({a:2})).to.equal('object');
552         });
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);
558                         return;
559                 }
561                 expect(typeOf(arguments)).to.equal('arguments');
562         });
564         it('should return "null" for null objects', function(){
565                 expect(typeOf(null)).to.equal('null');
566         });
568         it('should return "null" for undefined objects', function(){
569                 expect(typeOf(undefined)).to.equal('null');
570         });
574 describe('instanceOf', function(){
576         it('should return false on null object', function(){
577                 expect(instanceOf(null, null)).to.equal(false);
578         });
580         it('should return true for Arrays', function(){
581                 expect(instanceOf([], Array)).to.equal(true);
582         });
584         it('should return true for Numbers', function(){
585                 expect(instanceOf(1, Number)).to.equal(true);
586         });
588         it('should return true for Objects', function(){
589                 expect(instanceOf({}, Object)).to.equal(true);
590         });
592         it('should return true for Dates', function(){
593                 expect(instanceOf(new Date(), Date)).to.equal(true);
594         });
596         it('should return true for Booleans', function(){
597                 expect(instanceOf(true, Boolean)).to.equal(true);
598         });
600         it('should return true for RegExps', function(){
601                 expect(instanceOf(/_/, RegExp)).to.equal(true);
602         });
604         it('should respect the parent property of a custom object', function(){
605                 var X = function(){};
606                 X.parent = Array;
607                 expect(instanceOf(new X, Array)).to.equal(true);
608         });
610         // todo(ibolmo)
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);
614         });
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);
624         });
626         it('should return an array for arguments', function(){
627                 var fnTest = function(){
628                         return Array.convert(arguments);
629                 };
630                 var arr = fnTest(1, 2, 3);
631                 expect(Type.isArray(arr)).to.equal(true);
632                 expect(arr.length).to.equal(3);
633         });
635         it('should transform a non array into an array', function(){
636                 expect(Array.convert(1)).to.eql([1]);
637         });
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([]);
642         });
644         it('should ignore and return an array', function(){
645                 expect(Array.convert([1, 2, 3])).to.eql([1, 2, 3]);
646         });
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
652                 var args,
653                         type,
654                         copy = (function(){
655                                 type = typeOf(arguments);
656                                 args = arguments;
658                                 return Array.convert(arguments);
659                         })(1, 2);
661                 if (type === 'array'){
662                         expect(copy).to.equal(args);
663                 } else {
664                         expect(copy).to.not.equal(args);
665                 }
666         });
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');
676         });
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);
685         });
687         it('should return a function that returns the value passed when called', function(){
688                 expect(Function.convert('hello world!')()).to.equal('hello world!');
689         });
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);
698         });
700         it('should return null when it fails to return a number type', function(){
701                 expect(Number.convert('ciao')).to.equal(null);
702         });
706 describe('Type', function(){
708         var Instrument = new Type('Instrument', function(name){
709                 this.name = name;
710         }).implement({
712                 method: function(){
713                         return 'playing ' + this.name;
714                 }
716         });
718         var Car = new Type('Car', function(name){
719                 this.name = name;
720         }).implement({
722                 method: (function(){
723                         return 'driving a ' + this.name;
724                 }).protect()
726         });
728         it('should allow implementation over existing methods when a method is not protected', function(){
729                 Instrument.implement({
730                         method: function(){
731                                 return 'playing a guitar';
732                         }
733                 });
734                 var myInstrument = new Instrument('Guitar');
735                 expect(myInstrument.method()).to.equal('playing a guitar');
736         });
738         it('should not override a method when it is protected', function(){
739                 Car.implement({
740                         method: function(){
741                                 return 'hell no!';
742                         }
743                 });
744                 var myCar = new Car('nice car');
745                 expect(myCar.method()).to.equal('driving a nice car');
746         });
748         it('should allow generic calls', function(){
749                 expect(Car.method({name: 'not so nice car'})).to.equal('driving a not so nice car');
750         });
752         it('should be a Type', function(){
753                 expect(Type.isType(Instrument)).to.equal(true);
754         });
756         it('should generate and evaluate correct types', function(){
757                 var myCar = new Car('nice car');
758                 expect(Type.isCar(myCar)).to.equal(true);
759         });
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);
763                 (function(){
764                         expect(Type.isEnumerable(arguments)).to.equal(true);
765                 })(1, 2, 3);
766                 expect(Type.isEnumerable({length: 2})).to.equal(true);
767         });
769         it('sould chain any function on a type', function(){
770                 var MyType = new Type('MyType', function(){}.implement({
771                         a: function(){}
772                 }));
774                 expect(MyType.alias('a', 'b').implement({
775                         method: function(){}
776                 }).extend({
777                         staticMethod: function(){}
778                 })).to.equal(MyType);
779         });
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([]);
789         });
791         it('should return an array containing the keys of the object', function(){
792                 expect(Object.keys(object)).to.eql(['a', 'b', 'c']);
793         });
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);
800         });
804 describe('Object.each', function(){
806         it('should call the function for each item in the object', function(){
807                 var daysObj = {};
808                 Object.each({first: 'Sunday', second: 'Monday', third: 'Tuesday'}, function(value, key){
809                         daysObj[key] = value;
810                 });
812                 expect(daysObj).to.eql({first: 'Sunday', second: 'Monday', third: 'Tuesday'});
813         });
815         it('should call non-enumerable properties too', function(){
816                 var obj = {
817                         foo: 'bar',
818                         constructor: 'constructor',
819                         hasOwnProperty: 'hasOwnProperty',
820                         isPrototypeOf: 'isPrototypeOf',
821                         propertyIsEnumerable: 'propertyIsEnumerable',
822                         toLocaleString: 'toLocaleString',
823                         toString: 'toString',
824                         valueOf: 'valueOf'
825                 };
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){
831                         iteration++;
832                         if (props.indexOf(k) == -1) keysInObject = false;
833                 });
835                 expect(keysInObject).to.equal(true);
836                 expect(iteration).to.equal(8);
837         });
841 describe('Array.each', function(){
843         it('should call the function for each item in Function arguments', function(){
844                 var daysArr = [];
845                 (function(){
846                         Array.each(Array.convert(arguments), function(value, key){
847                                 daysArr[key] = value;
848                         });
849                 })('Sun', 'Mon', 'Tue');
851                 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
852         });
854         it('should call the function for each item in the array', function(){
855                 var daysArr = [];
856                 Array.each(['Sun', 'Mon', 'Tue'], function(value){
857                         daysArr.push(value);
858                 });
860                 expect(daysArr).to.eql(['Sun', 'Mon', 'Tue']);
861         });
863         it('should not iterate over deleted elements', function(){
864                 var array = [0, 1, 2, 3],
865                         testArray = [];
866                 delete array[1];
867                 delete array[2];
869                 array.each(function(value){
870                         testArray.push(value);
871                 });
873                 expect(testArray).to.eql([0, 3]);
874         });
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);
891         });
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);
908         });
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});
925         });
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]};
931                 Object.merge(a, b);
933                 expect(a.e).to.not.equal(b.e);
934                 expect(a.f).to.not.equal(b.f);
935         });
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});
951         });
955 /*<!ES5>*/
956 describe('Date.now', function(){
958         it('should return a timestamp', function(){
959                 expect(Type.isNumber(Date.now())).to.equal(true);
960         });
963 /*</!ES5>*/
965 describe('String.uniqueID', function(){
967         it('should be a string', function(){
968                 expect(typeof String.uniqueID()).to.equal('string');
969         });
971         it('should generate unique ids', function(){
972                 expect(String.uniqueID()).to.not.equal(String.uniqueID());
973         });
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');
982         });
984         dit('should return "element" for an Element', function(){
985                 var div = document.createElement('div');
986                 expect(typeOf(div)).to.equal('element');
987         });
989         // todo(ibolmo)
990         if (typeof window != 'undefined' && window.Elements) dit('should return "elements" for Elements', function(){
991                 expect(typeOf(new Elements)).to.equal('elements');
992         });
994         if (typeof window != 'undefined' && window.Browser) dit('should return "window" for the window object', function(){
995                 expect(typeOf(window)).to.equal('window');
996         });
998         if (typeof window != 'undefined' && window.Browser) dit('should return "document" for the document object', function(){
999                 expect(typeOf(document)).to.equal('document');
1000         });
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);
1017         });
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);
1025         });
1029 describe('Core', function(){
1031         describe('typeOf', function(){
1033                 it('should correctly report the type of arguments when using "use strict"', function(){
1034                         'use strict';
1035                         expect(typeOf(arguments)).to.equal('arguments');
1036                 });
1038         });