UNPKG

sugar

Version:

A Javascript library for working with native objects.

862 lines (664 loc) 42.9 kB
test('Object', function () { var count,result; var Person = function() {}; var p = new Person(); equal(Object.isObject({}), true, 'Object.isObject | {}'); equal(Object.isObject(Object.extended()), true, 'Object.isObject | extended object'); equal(Object.isObject(new Object({})), true, 'Object.isObject | new Object()'); equal(Object.isObject([]), false, 'Object.isObject | []'); equal(Object.isObject(new Array(1,2,3)), false, 'Object.isObject | new Array(1,2,3)'); equal(Object.isObject(new RegExp()), false, 'Object.isObject | new RegExp()'); equal(Object.isObject(new Date()), false, 'Object.isObject | new Date()'); equal(Object.isObject(function() {}), false, 'Object.isObject | function() {}'); equal(Object.isObject(1), false, 'Object.isObject | 1'); equal(Object.isObject('wasabi'), false, 'Object.isObject | "wasabi"'); equal(Object.isObject(null), false, 'Object.isObject | null'); equal(Object.isObject(undefined), false, 'Object.isObject | undefined'); equal(Object.isObject(NaN), false, 'Object.isObject | NaN'); equal(Object.isObject(), false, 'Object.isObject | blank'); equal(Object.isObject(false), false, 'Object.isObject | false'); equal(Object.isObject(true), false, 'Object.isObject | true'); equal(Object.isObject(p), true, 'Object.isObject | {}'); equal(Object.isArray({}), false, 'Object.isArray | {}'); equal(Object.isArray([]), true, 'Object.isArray | []'); equal(Object.isArray(new Array(1,2,3)), true, 'Object.isArray | new Array(1,2,3)'); equal(Object.isArray(new RegExp()), false, 'Object.isArray | new RegExp()'); equal(Object.isArray(new Date()), false, 'Object.isArray | new Date()'); equal(Object.isArray(function() {}), false, 'Object.isArray | function() {}'); equal(Object.isArray(1), false, 'Object.isArray | 1'); equal(Object.isArray('wasabi'), false, 'Object.isArray | "wasabi"'); equal(Object.isArray(null), false, 'Object.isArray | null'); equal(Object.isArray(undefined), false, 'Object.isArray | undefined'); equal(Object.isArray(NaN), false, 'Object.isArray | NaN'); equal(Object.isArray(), false, 'Object.isArray | blank'); equal(Object.isArray(false), false, 'Object.isArray | false'); equal(Object.isArray(true), false, 'Object.isArray | true'); equal(Object.isBoolean({}), false, 'Object.isBoolean | {}'); equal(Object.isBoolean([]), false, 'Object.isBoolean | []'); equal(Object.isBoolean(new RegExp()), false, 'Object.isBoolean | new RegExp()'); equal(Object.isBoolean(new Date()), false, 'Object.isBoolean | new Date()'); equal(Object.isBoolean(function() {}), false, 'Object.isBoolean | function() {}'); equal(Object.isBoolean(1), false, 'Object.isBoolean | 1'); equal(Object.isBoolean('wasabi'), false, 'Object.isBoolean | "wasabi"'); equal(Object.isBoolean(null), false, 'Object.isBoolean | null'); equal(Object.isBoolean(undefined), false, 'Object.isBoolean | undefined'); equal(Object.isBoolean(NaN), false, 'Object.isBoolean | NaN'); equal(Object.isBoolean(), false, 'Object.isBoolean | blank'); equal(Object.isBoolean(false), true, 'Object.isBoolean | false'); equal(Object.isBoolean(true), true, 'Object.isBoolean | true'); equal(Object.isDate({}), false, 'Object.isDate | {}'); equal(Object.isDate([]), false, 'Object.isDate | []'); equal(Object.isDate(new RegExp()), false, 'Object.isDate | new RegExp()'); equal(Object.isDate(new Date()), true, 'Object.isDate | new Date()'); equal(Object.isDate(function() {}), false, 'Object.isDate | function() {}'); equal(Object.isDate(1), false, 'Object.isDate | 1'); equal(Object.isDate('wasabi'), false, 'Object.isDate | "wasabi"'); equal(Object.isDate(null), false, 'Object.isDate | null'); equal(Object.isDate(undefined), false, 'Object.isDate | undefined'); equal(Object.isDate(NaN), false, 'Object.isDate | NaN'); equal(Object.isDate(), false, 'Object.isDate | blank'); equal(Object.isDate(false), false, 'Object.isDate | false'); equal(Object.isDate(true), false, 'Object.isDate | true'); equal(Object.isFunction({}), false, 'Object.isFunction | {}'); equal(Object.isFunction([]), false, 'Object.isFunction | []'); equal(Object.isFunction(new RegExp()), false, 'Object.isFunction | new RegExp()'); equal(Object.isFunction(new Date()), false, 'Object.isFunction | new Date()'); equal(Object.isFunction(function() {}), true, 'Object.isFunction | function() {}'); equal(Object.isFunction(new Function()), true, 'Object.isFunction | new Function()'); equal(Object.isFunction(1), false, 'Object.isFunction | 1'); equal(Object.isFunction('wasabi'), false, 'Object.isFunction | "wasabi"'); equal(Object.isFunction(null), false, 'Object.isFunction | null'); equal(Object.isFunction(undefined), false, 'Object.isFunction | undefined'); equal(Object.isFunction(NaN), false, 'Object.isFunction | NaN'); equal(Object.isFunction(), false, 'Object.isFunction | blank'); equal(Object.isFunction(false), false, 'Object.isFunction | false'); equal(Object.isFunction(true), false, 'Object.isFunction | true'); equal(Object.isNumber({}), false, 'Object.isNumber | {}'); equal(Object.isNumber([]), false, 'Object.isNumber | []'); equal(Object.isNumber(new RegExp()), false, 'Object.isNumber | new RegExp()'); equal(Object.isNumber(new Date()), false, 'Object.isNumber | new Date()'); equal(Object.isNumber(function() {}), false, 'Object.isNumber | function() {}'); equal(Object.isNumber(new Function()), false, 'Object.isNumber | new Function()'); equal(Object.isNumber(1), true, 'Object.isNumber | 1'); equal(Object.isNumber(0), true, 'Object.isNumber | 0'); equal(Object.isNumber(-1), true, 'Object.isNumber | -1'); equal(Object.isNumber(new Number('3')), true, 'Object.isNumber | new Number("3")'); equal(Object.isNumber('wasabi'), false, 'Object.isNumber | "wasabi"'); equal(Object.isNumber(null), false, 'Object.isNumber | null'); equal(Object.isNumber(undefined), false, 'Object.isNumber | undefined'); equal(Object.isNumber(NaN), true, 'Object.isNumber | NaN'); equal(Object.isNumber(), false, 'Object.isNumber | blank'); equal(Object.isNumber(false), false, 'Object.isNumber | false'); equal(Object.isNumber(true), false, 'Object.isNumber | true'); equal(Object.isString({}), false, 'Object.isString | {}'); equal(Object.isString([]), false, 'Object.isString | []'); equal(Object.isString(new RegExp()), false, 'Object.isString | new RegExp()'); equal(Object.isString(new Date()), false, 'Object.isString | new Date()'); equal(Object.isString(function() {}), false, 'Object.isString | function() {}'); equal(Object.isString(new Function()), false, 'Object.isString | new Function()'); equal(Object.isString(1), false, 'Object.isString | 1'); equal(Object.isString('wasabi'), true, 'Object.isString | "wasabi"'); equal(Object.isString(new String('wasabi')), true, 'Object.isString | new String("wasabi")'); equal(Object.isString(null), false, 'Object.isString | null'); equal(Object.isString(undefined), false, 'Object.isString | undefined'); equal(Object.isString(NaN), false, 'Object.isString | NaN'); equal(Object.isString(), false, 'Object.isString | blank'); equal(Object.isString(false), false, 'Object.isString | false'); equal(Object.isString(true), false, 'Object.isString | true'); equal(Object.isRegExp({}), false, 'Object.isRegExp | {}'); equal(Object.isRegExp([]), false, 'Object.isRegExp | []'); equal(Object.isRegExp(new RegExp()), true, 'Object.isRegExp | new RegExp()'); equal(Object.isRegExp(/afda/), true, 'Object.isRegExp | /afda/'); equal(Object.isRegExp(new Date()), false, 'Object.isRegExp | new Date()'); equal(Object.isRegExp(function() {}), false, 'Object.isRegExp | function() {}'); equal(Object.isRegExp(new Function()), false, 'Object.isRegExp | new Function()'); equal(Object.isRegExp(1), false, 'Object.isRegExp | 1'); equal(Object.isRegExp('wasabi'), false, 'Object.isRegExp | "wasabi"'); equal(Object.isRegExp(null), false, 'Object.isRegExp | null'); equal(Object.isRegExp(undefined), false, 'Object.isRegExp | undefined'); equal(Object.isRegExp(NaN), false, 'Object.isRegExp | NaN'); equal(Object.isRegExp(), false, 'Object.isRegExp | blank'); equal(Object.isRegExp(false), false, 'Object.isRegExp | false'); equal(Object.isRegExp(true), false, 'Object.isRegExp | true'); equal(Object.isNaN({}), false, 'Object.isNaN | {}'); equal(Object.isNaN([]), false, 'Object.isNaN | []'); equal(Object.isNaN(new RegExp()), false, 'Object.isNaN | new RegExp()'); equal(Object.isNaN(/afda/), false, 'Object.isNaN | /afda/'); equal(Object.isNaN(new Date()), false, 'Object.isNaN | new Date()'); equal(Object.isNaN(function() {}), false, 'Object.isNaN | function() {}'); equal(Object.isNaN(new Function()), false, 'Object.isNaN | new Function()'); equal(Object.isNaN(1), false, 'Object.isNaN | 1'); equal(Object.isNaN('wasabi'), false, 'Object.isNaN | "wasabi"'); equal(Object.isNaN(null), false, 'Object.isNaN | null'); equal(Object.isNaN(undefined), false, 'Object.isNaN | undefined'); equal(Object.isNaN(NaN), true, 'Object.isNaN | NaN'); equal(Object.isNaN(), false, 'Object.isNaN | blank'); equal(Object.isNaN(false), false, 'Object.isNaN | false'); equal(Object.isNaN(true), false, 'Object.isNaN | true'); equal(({}).keys, undefined, 'Object | native objects are not wrapped by default'); equal(Object.extended(), Object.extended({}), 'Object.extended | null argument same as empty object'); var keys,values; var d = new Date(); var obj = Object.extended({ number: 3, person: 'jim', date: d }); keys = ['number','person','date']; values = [3,'jim',d]; equal(obj.keys(), keys, "Object#keys | returns object's keys"); count = 0; obj.keys(function(key, value) { equal(key, keys[count], 'Object#keys | accepts a block'); equal(value, values[count], 'Object#keys | value is also passed'); equal(this, obj, 'Object#keys | "this" is the object'); count++; }); equal(count, 3, 'Object#keys | accepts a block | iterated properly'); equal(Object.extended().keys(), [], 'Object#keys | empty object'); equal(Object.keys(Object.extended()), [], 'Object#keys | empty object'); keys = ['number','person','date']; values = [3,'jim',d]; equal(Object.keys(obj), keys, "Object.keys | returns object's keys"); count = 0; Object.keys(obj, function(key) { equal(key, keys[count], 'Object.keys | accepts a block'); count++; }); equal(count, 3, 'Object.keys | accepts a block | iterated properly'); var strippedValues; strippedValues = obj.values().filter(function(m) { return typeof m != 'function'; }); equal(strippedValues, values, "Object#values | returns object's values", { prototype: values }); count = 0; obj.values(function(value) { equal(value, values[count], 'Object#values | accepts a block'); count++; }); equal(count, 3, 'Object#values | accepts a block | iterated properly', { prototype: 0, mootools: 0 }); strippedValues = Object.values(obj).filter(function(m) { return typeof m != 'function'; }); equal(strippedValues, values, "Object.values | returns object's values", { prototype: values }); count = 0; Object.values(obj, function(value) { equal(value, values[count], 'Object.values | accepts a block'); count++; }); equal(count, 3, 'Object.values | accepts a block | iterated properly', { prototype: 0, mootools: 0 }); strippedValues = Object.extended().values().filter(function(m) { return typeof m != 'function'; }); equal(strippedValues, [], 'Object#values | empty object'); strippedValues = Object.values(Object.extended()).filter(function(m) { return typeof m != 'function'; }); equal(strippedValues, [], 'Object#values | empty object'); equal(Object.merge({ foo: 'bar' }, { broken: 'wear' }), { foo: 'bar', broken: 'wear' }, 'Object.merge | basic'); equal(Object.merge({ foo: 'bar' }, 'aha'), { foo: 'bar' }, 'Object.merge | will not merge a string', { mootools: { foo: 'bar', aha: undefined } }); equal(Object.merge({ foo: 'bar' }, null), { foo: 'bar' }, 'Object.merge | merge null'); equal(Object.merge({}, {}), {}, 'Object.merge | merge multi empty'); equal(Object.merge({ foo: 'bar' }, 8), { foo: 'bar' }, 'Object.merge | merge number', { mootools: (function() { var s = Object.clone(8); s.foo = 'bar'; return s; })() }); equal(Object.merge({ foo:'bar' }, 'wear', 8, null), { foo:'bar' }, 'Object.merge | merge multi invalid', { mootools: { foo: 'bar', wear: 7 } }); equal(Object.merge([1,2,3,4], [4,5,6]), [4,5,6,4], 'Object.merge | arrays should also be mergeable'); equal(Object.merge({ foo: { one: 'two' }}, { foo: { two: 'three' }}, true, true), { foo: { one: 'two', two: 'three' }}, 'Object.merge | accepts deep merges'); equal(Object.merge('foo', 'bar'), 'foo', 'Object.merge | two strings'); equal(Object.merge({ a:1 }, { a:2 }), { a:2 }, 'Object.merge | incoming wins'); equal(Object.merge({ a:1 }, { a:2 }), { a:2 }, 'Object.merge | incoming wins | params true'); equal(Object.merge({ a:1 }, { a:2 }, false, false), { a:1 }, 'Object.merge | target wins'); equal(Object.merge({ a:undefined }, { a:2 }), { a:2 }, 'Object.merge | existing but undefined properties are overwritten'); equal(Object.merge({ a:null }, { a:2 }), { a:2 }, 'Object.merge | null properties are not overwritten'); equal(Object.merge({ a:undefined }, { a:2 }, false, false), { a:2 }, 'Object.merge | false |existing but undefined properties are overwritten'); equal(Object.merge({ a:null }, { a:2 }, false, false), { a:null }, 'Object.merge | false | null properties are not overwritten'); equal(Object.merge([{ foo:'bar' }], [{ moo:'car' }], true, true), [{ foo:'bar',moo:'car' }], 'Object.merge | can merge arrays as well'); var fn1 = function() {}; fn1.foo = 'bar'; equal(Object.merge(function(){}, fn1).foo, 'bar', 'Object.merge | retains properties'); var fn = function(key, a, b) { equal(key, 'a', 'Object.merge | resolve function | first argument is the key'); equal(a, 1, 'Object.merge | resolve function | second argument is the target val'); equal(b, 2, 'Object.merge | resolve function | third argument is the source val'); equal(this, { a:2 }, 'Object.merge | resolve function | context is the source object'); return a + b; }; equal(Object.merge({ a:1 }, { a:2 }, false, fn), { a:3 }, 'Object.merge | function resolves'); var fn1 = function() { return 'joe' }; var fn2 = function() { return 'moe' }; var date1 = new Date(2001, 1, 6); var date2 = new Date(2005, 1, 6); var inner1 = { foo: 'bar', hee: 'haw' } var inner2 = { foo: 'car', mee: 'maw' } var obj1 = { str: 'oolala', num: 18, fn: fn1, date: date1, prop1: 'next', inner: inner1, arr: [1,2,3,4] } var obj2 = { str: 'foofy', num: 67, fn: fn2, date: date2, prop2: 'beebop', inner: inner2, arr: [4,5,6] } var fn = function(key, a, b) { if(key == 'str') { return 'conflict!'; } else if(key == 'num') { return a + b; } else { return b; } } var expected = { str: 'conflict!', num: 85, fn: fn2, date: date2, prop1: 'next', prop2: 'beebop', inner: { foo: 'car', hee: 'haw', mee: 'maw' }, arr: [4,5,6,4] } equal(Object.merge(obj1, obj2, true, fn), expected, 'Object.merge | complex objects with resolve function'); equal(obj1.fn(), 'moe', 'Object.merge | fn conflict resolved'); equal(obj1.date.getTime(), new Date(2005, 1, 6).getTime(), 'Object.merge | date conflict resolved'); equal(Object.extended({ foo: 'bar' }).merge({ broken: 'wear' }), { foo: 'bar', broken: 'wear' }, 'Object#merge | basic'); equal(Object.extended({ foo: 'bar' }).merge('aha'), { foo: 'bar' }, 'Object#merge | will not merge a string', { mootools: { foo: 'bar', aha: undefined } }); equal(Object.extended({ foo: 'bar' }).merge(null), { foo: 'bar' }, 'Object#merge | merge null'); equal(Object.extended({}).merge({}, {}, {}), {}, 'Object#merge | merge multi empty'); equal(Object.extended({ foo: 'bar' }).merge('wear', 8, null), { foo:'bar' }, 'Object#merge | merge multi invalid', { mootools: { foo: 'bar', wear: 8 } }); var fn1 = function() {}; fn1.foo = 'bar'; equal(Object.extended(function(){}).merge(fn1).foo, 'bar', 'Object.merge | retains properties'); equal(Object.extended({ a:1 }).merge({ a:2 }), { a:2 }, 'Object.merge | incoming wins'); equal(Object.extended({ a:1 }).merge({ a:2 }, true), { a:2 }, 'Object.merge | incoming wins | params true'); equal(Object.extended({ a:1 }).merge({ a:2 }, false, false), { a:1 }, 'Object.merge | target wins'); equal(Object.extended({ a:1 }).merge({ a:2 }, false, function(key, a, b){ return a + b; }), { a:3 }, 'Object.merge | function resolves'); skipEnvironments(['prototype','mootools'], function() { equal(Object.clone('hardy'), 'hardy', 'Object.clone | clone on a string'); }); equal(Object.clone(undefined), undefined, 'Object.clone | clone on undefined', { prototype: {} }); equal(Object.clone(null), null, 'Object.clone | clone on null', { prototype: {} }); equal(Object.clone({ foo: 'bar' }), { foo: 'bar' }, 'Object.clone | basic clone'); equal(Object.clone({ foo: 'bar', broken: 1, wear: null }), { foo: 'bar', broken: 1, wear: null }, 'Object.clone | complex clone'); equal(Object.clone({ foo: { broken: 'wear' }}), { foo: { broken: 'wear' }}, 'Object.clone | deep clone'); equal(Object.clone({ foo: 'bar', broken: 1, wear: /foo/ }) == { foo: 'bar', broken: 1, wear: /foo/ }, false, 'Object.clone | fully cloned'); equal(Object.clone([1,2,3]), [1,2,3], 'Object.clone | clone on arrays'); equal(Object.clone(['a','b','c']), ['a','b','c'], 'Object.clone | clone on array of strings'); var arr1 = [1]; var arr2 = [2]; var arr3 = [3]; var shallow = Object.clone([arr1,arr2,arr3]); var deep = Object.clone([arr1,arr2,arr3], true); equal(shallow[0] === arr1, true, 'Object.clone | shallow clone | index 0 is strictly equal'); equal(shallow[1] === arr2, true, 'Object.clone | shallow clone | index 1 is strictly equal'); equal(shallow[2] === arr3, true, 'Object.clone | shallow clone | index 2 is strictly equal'); equal(deep[0] === arr1, false, 'Object.clone | deep clone | index 0 is not strictly equal'); equal(deep[1] === arr2, false, 'Object.clone | deep clone | index 1 is not strictly equal'); equal(deep[2] === arr3, false, 'Object.clone | deep clone | index 2 is not strictly equal'); var obj1, obj2, obj3; obj1 = { broken: 'wear', foo: { jumpy: 'jump', bucket: { reverse: true } } } obj2 = Object.clone(obj1); equal(obj1.foo.jumpy, 'jump', 'Object.clone | cloned object has nested attribute'); obj1.foo.jumpy = 'hump'; equal(obj1.foo.jumpy, 'hump', 'Object.clone | original object is modified'); equal(obj2.foo.jumpy, 'hump', 'Object.clone | clone is shallow', { mootools: 'jump' }); obj1 = { foo: { bar: [1,2,3] } }; obj2 = Object.clone(obj1); obj3 = Object.clone(obj1, true); obj1.foo.bar = ['a','b','c']; equal(obj1.foo.bar, ['a','b','c'], 'Object#clone | original object is modified'); equal(obj2.foo.bar, ['a','b','c'], 'Object#clone | clone is shallow', { mootools: [1,2,3] }); obj1.foo.bar = ['a','b','c']; equal(obj3.foo.bar, [1,2,3], 'Object#clone | clone is deep', { prototype: ['a','b','c'] }); var arr1 = [obj1, obj1, obj1]; var arr2 = Object.clone(arr1, true); equal(arr1.length, arr2.length, 'Object.clone | array deep | lengths should be equal'); equal(arr2[0] === obj1, false, 'Object.clone | array deep | obj1 is not equal'); equal(arr2[1] === obj2, false, 'Object.clone | array deep | obj2 is not equal'); equal(arr2[2] === obj3, false, 'Object.clone | array deep | obj3 is not equal'); // Note here that the need for these complicated syntaxes is that both Prototype and Mootools' Object.clone is incorrectly // cloning properties in the prototype chain directly into the object itself. equal(Object.extended({ foo: 'bar' }).clone(), { foo: 'bar' }, 'Object#clone | basic clone'); equal(Object.extended({ foo: 'bar', broken: 1, wear: null }).clone(), { foo: 'bar', broken: 1, wear: null }, 'Object#clone | complex clone'); equal(Object.extended({ foo: { broken: 'wear' }}).clone(), { foo: { broken: 'wear' }}, 'Object#clone | deep clone'); equal(Object.extended({ foo: 'bar', broken: 1, wear: /foo/ }).clone() == { foo: 'bar', broken: 1, wear: /foo/ }, false, 'Object#clone | fully cloned'); var obj1, obj2, obj3; obj1 = Object.extended({ broken: 'wear', foo: { jumpy: 'jump', bucket: { reverse: true } } }); obj2 = obj1.clone(); obj3 = obj1.clone(true); equal(obj1.foo.jumpy, 'jump', 'Object#clone | cloned object has nested attribute'); obj1.foo.jumpy = 'hump'; equal(obj1.foo.jumpy, 'hump', 'Object#clone | original object is modified'); equal(obj2.foo.jumpy, 'hump', 'Object#clone | clone is shallow'); equal(obj3.foo.jumpy, 'jump', 'Object#clone | clone is deep', { prototype: 'hump' }); skipEnvironments(['prototype','mootools'], function() { equal(obj2.keys().sort(), ['broken','foo'], 'Object#clone | cloned objects are themselves extended'); }); obj1 = Object.extended({ foo: { bar: [1,2,3] } }); obj2 = obj1.clone(); obj3 = obj1.clone(true); obj1.foo.bar[1] = 'b'; equal(obj1.foo.bar, [1,'b',3], 'Object#clone | original object is modified'); equal(obj3.foo.bar, [1,2,3], 'Object#clone | cloned object is not modified', { prototype: [1,'b',3] }); equal(Object.equal({ broken: 'wear' }, { broken: 'wear' }), true, 'Object.equal | objects are equal'); equal(Object.equal({ broken: 'wear' }, { broken: 'jumpy' }), false, 'Object.equal | objects are not equal'); equal(Object.equal({}, {}), true, 'Object.equal | empty objects are equal'); equal(Object.equal({}, { broken: 'wear' }), false, 'Object.equal | 1st empty'); equal(Object.equal({ broken: 'wear' }, {}), false, 'Object.equal | 2nd empty'); equal(Object.equal({x: 1, y: undefined}, {x: 1, z: 2}), false, 'Object.equal | undefined keys'); equal(Object.extended({ broken: 'wear' }).equals({ broken: 'wear' }), true, 'Object#equals | extended objects are equal to plain objects'); equal(Object.extended({ broken: 'wear' }).equals({ broken: 'jumpy' }), false, 'Object#equals | objects are not equal'); equal(Object.extended({}).equals({}), true, 'Object#equals | empty extended objects are equal to empty plain objects'); equal(Object.extended({}).equals({ broken: 'wear' }), false, 'Object#equals | 1st empty'); equal(Object.extended({ broken: 'wear' }).equals({}), false, 'Object#equals | 2nd empty'); var obj1 = { foo: 'bar' }; equal(Object.equal({ a: obj1, b: obj1 }, { a: obj1, b: obj1 }), true, 'Object.equal | multiple references will not choke'); var obj1 = { foo: 'bar' }; obj1.moo = obj1; equal(Object.equal(obj1, { foo: 'bar', moo: obj1 }), true, 'Object.equal | cyclical references handled'); equal(Object.equal(undefined, 'one'), false, 'Object.equal | string to undefined'); // Enabling native object methods rememberObjectProtoypeMethods(); Object.extend(); var prototypeBaseValues = ({}).values().sort(); count = 0; equal(({ foo: 'bar' }).keys(function() { count++; }), ['foo'], 'Object#keys | Object.prototype'); equal(({ foo: 'bar' }).values(function() { count++; }).sort(), ['bar'], 'Object#values | Object.prototype', { prototype: ['bar'].concat(prototypeBaseValues) }); equal(count, 2, 'Object | Object.prototype should have correctly called all functions', { prototype: 2, mootools: 2 }); equal(({ foo: 'bar' }).equals({ foo: 'bar' }), true, 'Object#equals | Object.prototype'); equal(({ foo: 'bar' }).merge({ moo: 'car' }), { foo: 'bar', moo: 'car' }, 'Object#merge | Object.prototype', { mootools: Object.clone({ foo: 'bar', moo: 'car' }) }); obj1 = { foo: 'bar' }; obj2 = obj1.clone(); obj1.foo = 'mar'; equal(obj2, { foo: 'bar' }, 'Object#clone | Object.prototype'); equal(([1,2,3]).isArray(), true, 'Object#isArray | Object.prototype'); equal(([1,2,3]).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal(([1,2,3]).isDate(), false, 'Object#isDate | Object.prototype'); equal(([1,2,3]).isFunction(), false, 'Object#isFunction | Object.prototype'); equal(([1,2,3]).isNumber(), false, 'Object#isNumber | Object.prototype'); equal(([1,2,3]).isString(), false, 'Object#isString | Object.prototype'); equal(([1,2,3]).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal(([1,2,3]).isNaN(), false, 'Object#isNaN | Object.prototype'); equal((true).isArray(), false, 'Object#isArray | Object.prototype'); equal((true).isBoolean(), true, 'Object#isBoolean | Object.prototype'); equal((true).isDate(), false, 'Object#isDate | Object.prototype'); equal((true).isFunction(), false, 'Object#isFunction | Object.prototype'); equal((true).isNumber(), false, 'Object#isNumber | Object.prototype'); equal((true).isString(), false, 'Object#isString | Object.prototype'); equal((true).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal((true).isNaN(), false, 'Object#isNaN | Object.prototype'); equal((new Date()).isArray(), false, 'Object#isArray | Object.prototype'); equal((new Date()).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal((new Date()).isDate(), true, 'Object#isDate | Object.prototype'); equal((new Date()).isFunction(), false, 'Object#isFunction | Object.prototype'); equal((new Date()).isNumber(), false, 'Object#isNumber | Object.prototype'); equal((new Date()).isString(), false, 'Object#isString | Object.prototype'); equal((new Date()).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal((new Date()).isNaN(), false, 'Object#isNaN | Object.prototype'); equal((function() {}).isArray(), false, 'Object#isArray | Object.prototype'); equal((function() {}).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal((function() {}).isDate(), false, 'Object#isDate | Object.prototype'); equal((function() {}).isFunction(), true, 'Object#isFunction | Object.prototype'); equal((function() {}).isNumber(), false, 'Object#isNumber | Object.prototype'); equal((function() {}).isString(), false, 'Object#isString | Object.prototype'); equal((function() {}).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal((function() {}).isNaN(), false, 'Object#isNaN | Object.prototype'); equal((3).isArray(), false, 'Object#isArray | Object.prototype'); equal((3).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal((3).isDate(), false, 'Object#isDate | Object.prototype'); equal((3).isFunction(), false, 'Object#isFunction | Object.prototype'); equal((3).isNumber(), true, 'Object#isNumber | Object.prototype'); equal((3).isString(), false, 'Object#isString | Object.prototype'); equal((3).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal((3).isNaN(), false, 'Object#isNaN | Object.prototype'); equal(('wasabi').isArray(), false, 'Object#isArray | Object.prototype'); equal(('wasabi').isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal(('wasabi').isDate(), false, 'Object#isDate | Object.prototype'); equal(('wasabi').isFunction(), false, 'Object#isFunction | Object.prototype'); equal(('wasabi').isNumber(), false, 'Object#isNumber | Object.prototype'); equal(('wasabi').isString(), true, 'Object#isString | Object.prototype'); equal(('wasabi').isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal(('wasabi').isNaN(), false, 'Object#isNaN | Object.prototype'); equal((/wasabi/).isArray(), false, 'Object#isArray | Object.prototype'); equal((/wasabi/).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal((/wasabi/).isDate(), false, 'Object#isDate | Object.prototype'); equal((/wasabi/).isFunction(), false, 'Object#isFunction | Object.prototype'); equal((/wasabi/).isNumber(), false, 'Object#isNumber | Object.prototype'); equal((/wasabi/).isString(), false, 'Object#isString | Object.prototype'); equal((/wasabi/).isRegExp(), true, 'Object#isRegExp | Object.prototype'); equal((/wasabi/).isNaN(), false, 'Object#isNaN | Object.prototype'); equal((NaN).isArray(), false, 'Object#isArray | Object.prototype'); equal((NaN).isBoolean(), false, 'Object#isBoolean | Object.prototype'); equal((NaN).isDate(), false, 'Object#isDate | Object.prototype'); equal((NaN).isFunction(), false, 'Object#isFunction | Object.prototype'); equal((NaN).isNumber(), true, 'Object#isNumber | Object.prototype'); equal((NaN).isString(), false, 'Object#isString | Object.prototype'); equal((NaN).isRegExp(), false, 'Object#isRegExp | Object.prototype'); equal((NaN).isNaN(), true, 'Object#isNaN | Object.prototype'); // Object#watch var obj = Object.extended({ foo: 'bar' }), ran = false, counter = 0, key; obj.watch('foo', function(prop, oldVal, newVal) { equal(this, obj, 'Object#watch | scope is the object'); equal(prop, 'foo', 'Object#watch | first argument is the propety'); equal(oldVal, 'bar', 'Object#watch | second argument is the old value'); equal(newVal, 'howdy', 'Object#watch | third argument is the new value'); ran = true; return newVal; }); equal(obj.foo, 'bar', 'Object#watch | old property is retained'); obj.foo = 'howdy'; equal(obj.foo, 'howdy', 'Object#watch | property was set'); equal(ran, true, 'Object#watch | setter ran'); for(key in obj) counter++; equal(counter, 1, 'Object#watch | property should be enumerable'); // Object#tap var fn = function(first) { equal(this, [1,2,3,4,5], 'Object#tap | context is the object'); equal(first, [1,2,3,4,5], 'Object#tap | first argument is also the object'); this.pop(); } var map = function(n) { return n * 2; } var expected = [2,4,6,8]; equal([1,2,3,4,5].tap(fn).map(map), expected, 'Object#tap | pop the array'); equal([1,2,3,4,5].tap('pop').map(map), expected, 'Object#tap | string shortcut | pop the array'); equal([1,2].tap(function() { this.push(3, 4); }).map(map), expected, 'Object#tap | push to the array'); equal([1,2].tap('push', 3, 4).map(map), [2,4], 'Object#tap | string shortcut | passing arguments is not supported'); equal([1,2,3,4].tap(function(){ if(this[this.length - 1] === 5) this.pop(); }).map(map), expected, 'Object#tap | checking last'); var obj = { foo: 'bar' }; equal(obj.tap(), obj, 'Object#tap | return value is strictly equal'); equal('foo'.fromQueryString, undefined, 'Object.fromQueryString should not be mapped'); equal('foo'.extended, undefined, 'Object.extended should not be mapped'); equal('foo'.equal, undefined, 'Object.equal should not be mapped (should be "equals" instead)'); restoreObjectPrototypeMethods(); // Object.fromQueryString equal(Object.fromQueryString('foo=bar&moo=car'), {foo:'bar',moo:'car'}, 'Object.fromQueryString | basic'); equal(Object.fromQueryString('foo=bar&moo=3'), {foo:'bar',moo:3}, 'Object.fromQueryString | with numbers'); equal(Object.fromQueryString('foo=bar&moo=true'), {foo:'bar',moo:true}, 'Object.fromQueryString | with true'); equal(Object.fromQueryString('foo=bar&moo=false'), {foo:'bar',moo:false}, 'Object.fromQueryString | with false'); equal(Object.fromQueryString('foo=bar3'), { foo: 'bar3' }, 'Object.fromQueryString | number in back'); equal(Object.fromQueryString('foo=3bar'), { foo: '3bar' }, 'Object.fromQueryString | number up front'); equal(Object.fromQueryString('foo=345'), { foo: 345 }, 'Object.fromQueryString | numbers only'); equal(Object.fromQueryString('foo=&bar='), { foo: '', bar: '' }, 'Object.fromQueryString | undefined params'); equal(Object.fromQueryString('foo[]=bar&foo[]=car'), { foo: ['bar','car'] }, 'Object.fromQueryString | handles array params'); equal(Object.fromQueryString('foo[bar]=tee&foo[car]=hee'), { foo: { bar: 'tee', car: 'hee' } }, 'Object.fromQueryString | handles hash params'); equal(Object.fromQueryString('foo[0]=a&foo[1]=b&foo[2]=c'), { foo: ['a','b','c'] }, 'Object.fromQueryString | handles array indexes'); equal(Object.fromQueryString('foo[cap][map]=3'), { foo: { cap: { map: 3 } } }, 'Object.fromQueryString | handles array indexes'); equal(Object.fromQueryString('foo[cap][map][]=3'), { foo: { cap: { map: [3] } } }, 'Object.fromQueryString | nested with trailing array'); equal(Object.fromQueryString('foo[moo]=1&bar[far]=2'), { foo: { moo: 1 }, bar: { far: 2 }}, 'Object.fromQueryString | sister objects'); equal(Object.fromQueryString('f[]=a&f[]=b&f[]=c&f[]=d&f[]=e&f[]=f'), { f: ['a','b','c','d','e','f'] }, 'Object.fromQueryString | large array'); equal(Object.fromQueryString('foo[0][]=a&foo[1][]=b'), { foo: [['a'],['b']] }, 'Object.fromQueryString | nested arrays separate'); equal(Object.fromQueryString('foo[0][0]=3&foo[0][1]=4'), { foo: [[3,4]] }, 'Object.fromQueryString | nested arrays together'); equal(Object.fromQueryString('foo[][]=3&foo[][]=4'), { foo: [[3],[4]] }, 'Object.fromQueryString | nested arrays'); equal(Object.fromQueryString('foo[]=bar&foo[]=car', false), { 'foo[]': 'car' }, 'Object.fromQueryString | disallows nested params'); var sparse = []; sparse[3] = 'hardy'; sparse[10] = 'har har'; equal(Object.fromQueryString('foo[3]=hardy&foo[10]=har har'), { foo: sparse }, 'Object.fromQueryString | constructed arrays can be sparse'); equal(Object.fromQueryString('text=What%20is%20going%20on%20here%3f%3f&url=http://animalsbeingdicks.com/page/2'), { text: 'What is going on here??', url: 'http://animalsbeingdicks.com/page/2' }, 'Object.fromQueryString | handles partially escaped params'); equal(Object.fromQueryString('text=What%20is%20going%20on%20here%3f%3f&url=http%3A%2F%2Fanimalsbeingdicks.com%2Fpage%2F2'), { text: 'What is going on here??', url: 'http://animalsbeingdicks.com/page/2' }, 'Object.fromQueryString | handles fully escaped params'); equal(Object.fromQueryString('url=http%3A%2F%2Fwww.site.com%2Fslug%3Fin%3D%2Fuser%2Fjoeyblake'), { url: 'http://www.site.com/slug?in=/user/joeyblake' }, 'Object.fromQueryString | equal must be escaped as well'); equal(Object.fromQueryString('http://fake.com?foo=bar'), { foo: 'bar' }, 'Object.fromQueryString | handles whole URLs'); equal(Object.fromQueryString('foo=bar&moo=car').keys(), ['foo', 'moo'], 'Object.fromQueryString | should be extended'); equal(Object.fromQueryString(), {}, 'Object.fromQueryString | will not die if no arguments'); if(typeof window !== 'undefined') { equal(Object.isArray(Object.fromQueryString(window.location).keys()), true, 'Object.fromQueryString | can handle just window.location'); } equal(Object.fromQueryString('foo=3.14156'), { foo: 3.14156 }, 'Object.fromQueryString | can handle float values'); equal(Object.fromQueryString('foo=127.0.0.1'), { foo: '127.0.0.1' }, 'Object.fromQueryString | IP addresses not treated as numbers'); // Object.watch var obj = { foo: 'bar' }, ran = false, counter = 0, key; Object.watch(obj, 'foo', function(prop, oldVal, newVal) { equal(this, obj, 'Object.watch | scope is the object'); equal(prop, 'foo', 'Object.watch | first argument is the propety'); equal(oldVal, 'bar', 'Object.watch | second argument is the old value'); equal(newVal, 'howdy', 'Object.watch | third argument is the new value'); ran = true; return newVal; }); equal(obj.foo, 'bar', 'Object.watch | old property is retained'); obj.foo = 'howdy'; equal(obj.foo, 'howdy', 'Object.watch | property was set'); equal(ran, true, 'Object.watch | setter ran'); for(key in obj) counter++; equal(counter, 1, 'Object.watch | property should be enumerable'); // Object.tap var fn = function(first) { equal(this, [1,2,3,4,5], 'Object.tap | context is the object'); equal(first, [1,2,3,4,5], 'Object.tap | first argument is also the object'); this.pop(); } var map = function(n) { return n * 2; } var expected = [2,4,6,8]; equal(Object.tap([1,2,3,4,5], fn).map(map), expected, 'Object.tap | pop the array'); equal(Object.tap([1,2,3,4,5], 'pop').map(map), expected, 'Object.tap | string shortcut | pop the array'); equal(Object.tap([1,2], function() { this.push(3, 4); }).map(map), expected, 'Object.tap | push to the array'); equal(Object.tap([1,2], 'push', 3, 4).map(map), [2,4], 'Object.tap | string shortcut | not supported'); equal(Object.tap([1,2,3,4], function(){ if(this[this.length - 1] === 5) this.pop(); }).map(map), expected, 'Object.tap | checking last'); var obj = { foo: 'bar' }; equal(Object.tap(obj), obj, 'Object.tap | return value is strictly equal'); // Class.extend functionality String.extend({ foo: function() { return 'bar'; } }); equal('s'.foo(), 'bar', 'Class.extend | basic functionality'); Number.extend({ plus: function(a, b) { return this + a + b; }, chr: function() { return String.fromCharCode(this); } }); equal((1).plus(2, 3), 6, 'Class.extend | arguments and scope are correct'); Number.prototype.chr = function() { return 'F'; }; equal((69).chr(), 'F', 'Class.extend | should overwrite existing methods'); Number.restore('chr'); equal((69).chr(), 'E', 'Class.extend | simple array of strings should restore Sugar methods'); equal((1).plus(2, 3), 6, 'Class.extend | restoring Sugar methods should not override other custom extended methods'); // Object.extended hasOwnProperty issue #97 // see: http://www.devthought.com/2012/01/18/an-object-is-not-a-hash/ var a = Object.extended({ hasOwnProperty: true }); // Object.has equal(Object.has({ foo: 'bar' }, 'foo'), true, 'Object.has | finds a property'); equal(Object.has({ foo: 'bar' }, 'baz'), false, 'Object.has | does not find a nonexistant property'); equal(Object.has({ hasOwnProperty: true, foo: 'bar' }, 'foo'), true, 'Object.has | local hasOwnProperty is ignored'); // Object.clone on dates and regexes var obj1 = { d: new Date(2000, 5, 25), r: /dasfsa/gi } var obj2 = Object.clone(obj1, true); obj1.d.setDate(3); obj1.r.source = 'mwahaha'; equal(obj2.d.getDate(), 25, 'Object.clone | deep cloning also clones dates'); equal(obj2.r.source, 'dasfsa', 'Object.clone | deep cloning also clones regexes'); // Object.merge should not merge prototype properties var Foo = function(){}; Foo.prototype.bar = 3; var f = new Foo(); equal(Object.merge({}, f).bar, undefined, 'Object.merge should not merge inherited properties'); // Object.merge should not choke when target and source contain strictly equal objects var obj = { foo: 'bar' }; equal(Object.merge({ one: obj }, { one: obj }), { one: obj }, 'Object.merge should be able to handle identical source/target objects'); obj.moo = obj; equal(typeof Object.merge(obj, { foo: obj }), 'object', 'Object.merge should not choke on cyclic references'); // Object.merge deep merges should clone regexes var obj1 = { reg: /foobar/g } equal(Object.merge({}, obj1, true).reg === obj1.reg, false, 'Object.merge | deep merging will clone regexes'); equal(Object.equal(Object.clone(f), f), true, 'Object.clone | same constructor should be equal'); // Object.select var obj = { one: 1, two: 2, three: 3, four: 4, five: 5 }; var obj2 = { foo: obj }; testClassAndInstance('select', obj, ['one'], { one: 1 }, 'Object.select | one key'); testClassAndInstance('select', obj, ['foo'], {}, 'Object.select | nonexistent key'); testClassAndInstance('select', obj, ['one', 'two'], { one: 1, two: 2 }, 'Object.select | two keys'); testClassAndInstance('select', obj, ['one', 'foo'], { one: 1 }, 'Object.select | one existing one non-existing'); testClassAndInstance('select', obj, ['four', 'two'], { two: 2, four: 4 }, 'Object.select | keys out of order'); testClassAndInstance('select', obj, [['four', 'two']], { two: 2, four: 4 }, 'Object.select | keys in an array'); testClassAndInstance('select', obj, [/o/], { one: 1, two: 2, four: 4 }, 'Object.select | regex'); testClassAndInstance('select', obj, [/o$/], { two: 2 }, 'Object.select | regex $'); testClassAndInstance('select', obj, [/^o/], { one: 1 }, 'Object.select | ^ regex'); testClassAndInstance('select', obj, [/z/], {}, 'Object.select | non-matching regex'); testClassAndInstance('select', obj, [{ one: 1 }], { one: 1 }, 'Object.select | comparing object'); testClassAndInstance('select', obj, [{ one: 'foobar' }], { one: 1 }, 'Object.select | comparing object with different values'); testClassAndInstance('select', obj, [{}], {}, 'Object.select | empty object'); testClassAndInstance('select', obj, [[/^o/, /^f/]], { one: 1, four: 4, five: 5 }, 'Object.select | complex nested array of regexes'); equal(Object.select(obj2, 'foo').foo === obj, true, 'Object.select | selected values should be equal by reference'); testClassAndInstance('reject', obj, ['one'], { two: 2, three: 3, four: 4, five: 5 }, 'Object.reject | one key'); testClassAndInstance('reject', obj, ['foo'], obj, 'Object.reject | nonexistent key'); testClassAndInstance('reject', obj, ['one', 'two'], { three: 3, four: 4, five: 5 }, 'Object.reject | two keys'); testClassAndInstance('reject', obj, ['one', 'foo'], { two: 2, three: 3, four: 4, five: 5 }, 'Object.reject | one existing one non-existing'); testClassAndInstance('reject', obj, ['four', 'two'], { one: 1, three: 3, five: 5 }, 'Object.reject | keys out of order'); testClassAndInstance('reject', obj, [['four', 'two']], { one: 1, three: 3, five: 5 }, 'Object.reject | keys in an array'); testClassAndInstance('reject', obj, [/o/], { three: 3, five: 5 }, 'Object.reject | regex'); testClassAndInstance('reject', obj, [/o$/], { one: 1, three: 3, four: 4, five: 5 }, 'Object.reject | regex $'); testClassAndInstance('reject', obj, [/^o/], { two: 2, three: 3, four: 4, five: 5 }, 'Object.reject | ^ regex'); testClassAndInstance('reject', obj, [/z/], obj, 'Object.reject | non-matching regex'); testClassAndInstance('reject', obj, [{ one: 1 }], { two: 2, three: 3, four: 4, five: 5 }, 'Object.reject | comparing object'); testClassAndInstance('reject', obj, [{ one: 'foobar' }], { two: 2, three: 3, four: 4, five: 5 }, 'Object.reject | comparing object with different values'); testClassAndInstance('reject', obj, [{}], obj, 'Object.reject | empty object'); testClassAndInstance('reject', obj, [[/^o/, /^f/]], { two: 2, three: 3 }, 'Object.reject | complex nested array of regexes'); equal(Object.reject(obj2, 'moo').foo === obj, true, 'Object.reject | rejected values should be equal by reference'); });