collections.js (lodash-3.0.0) | : | collections.js (lodash-4.0.0) | ||
---|---|---|---|---|
(function() { | (function() { | |||
var _ = typeof require == 'function' ? require('..') : window._; | ||||
module('Collections'); | QUnit.module('Collections'); | |||
test('each', function() { | QUnit.test('each', function(assert) { | |||
_.each([1, 2, 3], function(num, i) { | _.each([1, 2, 3], function(num, i) { | |||
equal(num, i + 1, 'each iterators provide value and iteration count'); | assert.equal(num, i + 1, 'each iterators provide value and iteration count '); | |||
}); | }); | |||
var answers = []; | var answers = []; | |||
_.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {mul | _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier); }, {mu | |||
tiplier : 5}); | ltiplier: 5}); | |||
deepEqual(answers, [5, 10, 15], 'context object property accessed'); | assert.deepEqual(answers, [5, 10, 15], 'context object property accessed'); | |||
answers = []; | answers = []; | |||
_.each([1, 2, 3], function(num){ answers.push(num); }); | _.each([1, 2, 3], function(num){ answers.push(num); }); | |||
deepEqual(answers, [1, 2, 3], 'aliased as "forEach"'); | assert.deepEqual(answers, [1, 2, 3], 'can iterate a simple array'); | |||
answers = []; | answers = []; | |||
var obj = {one : 1, two : 2, three : 3}; | var obj = {one: 1, two: 2, three: 3}; | |||
obj.constructor.prototype.four = 4; | obj.constructor.prototype.four = 4; | |||
_.each(obj, function(value, key){ answers.push(key); }); | _.each(obj, function(value, key){ answers.push(key); }); | |||
deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects works, a nd ignores the object prototype.'); | assert.deepEqual(answers, ['one', 'two', 'three'], 'iterating over objects w orks, and ignores the object prototype.'); | |||
delete obj.constructor.prototype.four; | delete obj.constructor.prototype.four; | |||
// ensure the each function is JITed | ||||
_(1000).times(function() { _.each([], function(){}); }); | ||||
var count = 0; | ||||
obj = {1: 'foo', 2: 'bar', 3: 'baz'}; | ||||
_.each(obj, function(){ count++; }); | ||||
assert.equal(count, 3, 'the fun should be called only 3 times'); | ||||
var answer = null; | var answer = null; | |||
_.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); | _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; }); | |||
ok(answer, 'can reference the original collection from inside the iterator') ; | assert.ok(answer, 'can reference the original collection from inside the ite rator'); | |||
answers = 0; | answers = 0; | |||
_.each(null, function(){ ++answers; }); | _.each(null, function(){ ++answers; }); | |||
equal(answers, 0, 'handles a null properly'); | assert.equal(answers, 0, 'handles a null properly'); | |||
_.each(false, function(){}); | _.each(false, function(){}); | |||
var a = [1, 2, 3]; | var a = [1, 2, 3]; | |||
strictEqual(_.each(a, function(){}), a); | assert.strictEqual(_.each(a, function(){}), a); | |||
strictEqual(_.each(null, function(){}), null); | assert.strictEqual(_.each(null, function(){}), null); | |||
var b = [1, 2, 3]; | ||||
b.length = 100; | ||||
answers = 0; | ||||
_.each(b, function(){ ++answers; }); | ||||
equal(answers, 100, 'enumerates [0, length)'); | ||||
}); | }); | |||
test('forEach', function() { | QUnit.test('forEach', function(assert) { | |||
strictEqual(_.each, _.forEach, 'alias for each'); | assert.strictEqual(_.forEach, _.each, 'is an alias for each'); | |||
}); | }); | |||
test('lookupIterator with contexts', function() { | QUnit.test('lookupIterator with contexts', function(assert) { | |||
_.each([true, false, 'yes', '', 0, 1, {}], function(context) { | _.each([true, false, 'yes', '', 0, 1, {}], function(context) { | |||
_.each([1], function() { | _.each([1], function() { | |||
equal(this, context); | assert.equal(this, context); | |||
}, context); | }, context); | |||
}); | }); | |||
}); | }); | |||
test('map', function() { | QUnit.test('Iterating objects with sketchy length properties', function(assert | |||
) { | ||||
var functions = [ | ||||
'each', 'map', 'filter', 'find', | ||||
'some', 'every', 'max', 'min', | ||||
'groupBy', 'countBy', 'partition', 'indexBy' | ||||
]; | ||||
var reducers = ['reduce', 'reduceRight']; | ||||
var tricks = [ | ||||
{length: '5'}, | ||||
{length: {valueOf: _.constant(5)}}, | ||||
{length: Math.pow(2, 53) + 1}, | ||||
{length: Math.pow(2, 53)}, | ||||
{length: null}, | ||||
{length: -2}, | ||||
{length: new Number(15)} | ||||
]; | ||||
assert.expect(tricks.length * (functions.length + reducers.length + 4)); | ||||
_.each(tricks, function(trick) { | ||||
var length = trick.length; | ||||
assert.strictEqual(_.size(trick), 1, 'size on obj with length: ' + length) | ||||
; | ||||
assert.deepEqual(_.toArray(trick), [length], 'toArray on obj with length: | ||||
' + length); | ||||
assert.deepEqual(_.shuffle(trick), [length], 'shuffle on obj with length: | ||||
' + length); | ||||
assert.deepEqual(_.sample(trick), length, 'sample on obj with length: ' + | ||||
length); | ||||
_.each(functions, function(method) { | ||||
_[method](trick, function(val, key) { | ||||
assert.strictEqual(key, 'length', method + ': ran with length = ' + va | ||||
l); | ||||
}); | ||||
}); | ||||
_.each(reducers, function(method) { | ||||
assert.strictEqual(_[method](trick), trick.length, method); | ||||
}); | ||||
}); | ||||
}); | ||||
QUnit.test('Resistant to collection length and properties changing while itera | ||||
ting', function(assert) { | ||||
var collection = [ | ||||
'each', 'map', 'filter', 'find', | ||||
'some', 'every', 'max', 'min', 'reject', | ||||
'groupBy', 'countBy', 'partition', 'indexBy', | ||||
'reduce', 'reduceRight' | ||||
]; | ||||
var array = [ | ||||
'findIndex', 'findLastIndex' | ||||
]; | ||||
var object = [ | ||||
'mapObject', 'findKey', 'pick', 'omit' | ||||
]; | ||||
_.each(collection.concat(array), function(method) { | ||||
var sparseArray = [1, 2, 3]; | ||||
sparseArray.length = 100; | ||||
var answers = 0; | ||||
_[method](sparseArray, function(){ | ||||
++answers; | ||||
return method === 'every' ? true : null; | ||||
}, {}); | ||||
assert.equal(answers, 100, method + ' enumerates [0, length)'); | ||||
var growingCollection = [1, 2, 3], count = 0; | ||||
_[method](growingCollection, function() { | ||||
if (count < 10) growingCollection.push(count++); | ||||
return method === 'every' ? true : null; | ||||
}, {}); | ||||
assert.equal(count, 3, method + ' is resistant to length changes'); | ||||
}); | ||||
_.each(collection.concat(object), function(method) { | ||||
var changingObject = {0: 0, 1: 1}, count = 0; | ||||
_[method](changingObject, function(val) { | ||||
if (count < 10) changingObject[++count] = val + 1; | ||||
return method === 'every' ? true : null; | ||||
}, {}); | ||||
assert.equal(count, 2, method + ' is resistant to property changes'); | ||||
}); | ||||
}); | ||||
QUnit.test('map', function(assert) { | ||||
var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); | var doubled = _.map([1, 2, 3], function(num){ return num * 2; }); | |||
deepEqual(doubled, [2, 4, 6], 'doubled numbers'); | assert.deepEqual(doubled, [2, 4, 6], 'doubled numbers'); | |||
var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; | var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; | |||
}, {multiplier : 3}); | }, {multiplier: 3}); | |||
deepEqual(tripled, [3, 6, 9], 'tripled numbers with context'); | assert.deepEqual(tripled, [3, 6, 9], 'tripled numbers with context'); | |||
doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); | doubled = _([1, 2, 3]).map(function(num){ return num * 2; }); | |||
deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers'); | assert.deepEqual(doubled, [2, 4, 6], 'OO-style doubled numbers'); | |||
if (document.querySelectorAll) { | var ids = _.map({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ | |||
var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ ret | ||||
urn n.id; }); | ||||
deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.') | ||||
; | ||||
} | ||||
ids = _.map({length: 2, 0: {id: '1'}, 1: {id: '2'}}, function(n){ | ||||
return n.id; | return n.id; | |||
}); | }); | |||
deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes.'); | assert.deepEqual(ids, ['1', '2'], 'Can use collection methods on Array-likes .'); | |||
deepEqual(_.map(null, _.noop), [], 'handles a null properly'); | assert.deepEqual(_.map(null, _.noop), [], 'handles a null properly'); | |||
deepEqual(_.map([1], function() { | assert.deepEqual(_.map([1], function() { | |||
return this.length; | return this.length; | |||
}, [5]), [1], 'called with context'); | }, [5]), [1], 'called with context'); | |||
// Passing a property name like _.pluck. | // Passing a property name like _.pluck. | |||
var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}]; | var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; | |||
deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string map to | assert.deepEqual(_.map(people, 'name'), ['moe', 'curly'], 'predicate string | |||
object properties'); | map to object properties'); | |||
}); | }); | |||
test('collect', function() { | QUnit.test('collect', function(assert) { | |||
strictEqual(_.map, _.collect, 'alias for map'); | assert.strictEqual(_.collect, _.map, 'is an alias for map'); | |||
}); | }); | |||
test('reduce', function() { | QUnit.test('reduce', function(assert) { | |||
var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0); | var sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }, 0); | |||
equal(sum, 6, 'can sum up an array'); | assert.equal(sum, 6, 'can sum up an array'); | |||
var context = {multiplier : 3}; | var context = {multiplier: 3}; | |||
sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multip | sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num * this.mult | |||
lier; }, 0, context); | iplier; }, 0, context); | |||
equal(sum, 18, 'can reduce with a context object'); | assert.equal(sum, 18, 'can reduce with a context object'); | |||
sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0); | sum = _([1, 2, 3]).reduce(function(memo, num){ return memo + num; }, 0); | |||
equal(sum, 6, 'aliased as "inject"'); | assert.equal(sum, 6, 'OO-style reduce'); | |||
sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0); | sum = _.reduce([1, 2, 3], function(memo, num){ return memo + num; }); | |||
equal(sum, 6, 'OO-style reduce'); | assert.equal(sum, 6, 'default initial value'); | |||
sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }); | var prod = _.reduce([1, 2, 3, 4], function(memo, num){ return memo * num; }) | |||
equal(sum, 6, 'default initial value'); | ; | |||
assert.equal(prod, 24, 'can reduce via multiplication'); | ||||
var prod = _.reduce([1, 2, 3, 4], function(prod, num){ return prod * num; }) | assert.ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial | |||
; | value) properly'); | |||
equal(prod, 24, 'can reduce via multiplication'); | assert.equal(_.reduce([], _.noop, void 0), void 0, 'undefined can be passed | |||
as a special case'); | ||||
ok(_.reduce(null, _.noop, 138) === 138, 'handles a null (with initial value) | assert.equal(_.reduce([_], _.noop), _, 'collection of length one with no ini | |||
properly'); | tial value returns the first item'); | |||
equal(_.reduce([], _.noop, undefined), undefined, 'undefined can be passed a | assert.equal(_.reduce([], _.noop), void 0, 'returns undefined when collectio | |||
s a special case'); | n is empty and no initial value'); | |||
equal(_.reduce([_], _.noop), _, 'collection of length one with no initial va | }); | |||
lue returns the first item'); | ||||
raises(function() { _.reduce([], _.noop); }, TypeError, 'throws an error for | QUnit.test('foldl', function(assert) { | |||
empty arrays with no initial value'); | assert.strictEqual(_.foldl, _.reduce, 'is an alias for reduce'); | |||
raises(function() {_.reduce(null, _.noop);}, TypeError, 'handles a null (wit | ||||
hout initial value) properly'); | ||||
}); | }); | |||
test('foldl', function() { | QUnit.test('inject', function(assert) { | |||
strictEqual(_.reduce, _.foldl, 'alias for reduce'); | assert.strictEqual(_.inject, _.reduce, 'is an alias for reduce'); | |||
}); | }); | |||
test('reduceRight', function() { | QUnit.test('reduceRight', function(assert) { | |||
var list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }, ''); | var list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }, ''); | |||
equal(list, 'bazbarfoo', 'can perform right folds'); | assert.equal(list, 'bazbarfoo', 'can perform right folds'); | |||
list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }); | list = _.reduceRight(['foo', 'bar', 'baz'], function(memo, str){ return memo + str; }); | |||
equal(list, 'bazbarfoo', 'default initial value'); | assert.equal(list, 'bazbarfoo', 'default initial value'); | |||
var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + | var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(memo, num){ return memo | |||
num; }); | + num; }); | |||
equal(sum, 6, 'default initial value on object'); | assert.equal(sum, 6, 'default initial value on object'); | |||
ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with initial v | assert.ok(_.reduceRight(null, _.noop, 138) === 138, 'handles a null (with in | |||
alue) properly'); | itial value) properly'); | |||
equal(_.reduceRight([_], _.noop), _, 'collection of length one with no initi | assert.equal(_.reduceRight([_], _.noop), _, 'collection of length one with n | |||
al value returns the first item'); | o initial value returns the first item'); | |||
equal(_.reduceRight([], _.noop, undefined), undefined, 'undefined can be pas | assert.equal(_.reduceRight([], _.noop, void 0), void 0, 'undefined can be pa | |||
sed as a special case'); | ssed as a special case'); | |||
assert.equal(_.reduceRight([], _.noop), void 0, 'returns undefined when coll | ||||
raises(function() { _.reduceRight([], _.noop); }, TypeError, 'throws an erro | ection is empty and no initial value'); | |||
r for empty arrays with no initial value'); | ||||
raises(function() {_.reduceRight(null, _.noop);}, TypeError, 'handles a null | ||||
(without initial value) properly'); | ||||
// Assert that the correct arguments are being passed. | // Assert that the correct arguments are being passed. | |||
var args, | var args, | |||
memo = {}, | init = {}, | |||
object = {a: 1, b: 2}, | object = {a: 1, b: 2}, | |||
lastKey = _.keys(object).pop(); | lastKey = _.keys(object).pop(); | |||
var expected = lastKey === 'a' | var expected = lastKey === 'a' | |||
? [memo, 1, 'a', object] | ? [init, 1, 'a', object] | |||
: [memo, 2, 'b', object]; | : [init, 2, 'b', object]; | |||
_.reduceRight(object, function() { | _.reduceRight(object, function() { | |||
if (!args) args = _.toArray(arguments); | if (!args) args = _.toArray(arguments); | |||
}, memo); | }, init); | |||
deepEqual(args, expected); | assert.deepEqual(args, expected); | |||
// And again, with numeric keys. | // And again, with numeric keys. | |||
object = {'2': 'a', '1': 'b'}; | object = {2: 'a', 1: 'b'}; | |||
lastKey = _.keys(object).pop(); | lastKey = _.keys(object).pop(); | |||
args = null; | args = null; | |||
expected = lastKey === '2' | expected = lastKey === '2' | |||
? [memo, 'a', '2', object] | ? [init, 'a', '2', object] | |||
: [memo, 'b', '1', object]; | : [init, 'b', '1', object]; | |||
_.reduceRight(object, function() { | _.reduceRight(object, function() { | |||
if (!args) args = _.toArray(arguments); | if (!args) args = _.toArray(arguments); | |||
}, memo); | }, init); | |||
deepEqual(args, expected); | assert.deepEqual(args, expected); | |||
}); | }); | |||
test('foldr', function() { | QUnit.test('foldr', function(assert) { | |||
strictEqual(_.reduceRight, _.foldr, 'alias for reduceRight'); | assert.strictEqual(_.foldr, _.reduceRight, 'is an alias for reduceRight'); | |||
}); | }); | |||
test('find', function() { | QUnit.test('find', function(assert) { | |||
var array = [1, 2, 3, 4]; | var array = [1, 2, 3, 4]; | |||
strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return | assert.strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should | |||
first found `value`'); | return first found `value`'); | |||
strictEqual(_.find(array, function() { return false; }), void 0, 'should ret | assert.strictEqual(_.find(array, function() { return false; }), void 0, 'sho | |||
urn `undefined` if `value` is not found'); | uld return `undefined` if `value` is not found'); | |||
array.dontmatch = 55; | ||||
assert.strictEqual(_.find(array, function(x) { return x === 55; }), void 0, | ||||
'iterates array-likes correctly'); | ||||
// Matching an object like _.findWhere. | // Matching an object like _.findWhere. | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b : 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b : 4}]; | |||
deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhere'); | assert.deepEqual(_.find(list, {a: 1}), {a: 1, b: 2}, 'can be used as findWhe | |||
deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); | re'); | |||
ok(!_.find(list, {c: 1}), 'undefined when not found'); | assert.deepEqual(_.find(list, {b: 4}), {a: 1, b: 4}); | |||
ok(!_.find([], {c: 1}), 'undefined when searching empty list'); | assert.ok(!_.find(list, {c: 1}), 'undefined when not found'); | |||
assert.ok(!_.find([], {c: 1}), 'undefined when searching empty list'); | ||||
var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); | var result = _.find([1, 2, 3], function(num){ return num * 2 === 4; }); | |||
equal(result, 2, 'found the first "2" and broke the loop'); | assert.equal(result, 2, 'found the first "2" and broke the loop'); | |||
var obj = { | ||||
a: {x: 1, z: 3}, | ||||
b: {x: 2, z: 2}, | ||||
c: {x: 3, z: 4}, | ||||
d: {x: 4, z: 1} | ||||
}; | ||||
assert.deepEqual(_.find(obj, {x: 2}), {x: 2, z: 2}, 'works on objects'); | ||||
assert.deepEqual(_.find(obj, {x: 2, z: 1}), void 0); | ||||
assert.deepEqual(_.find(obj, function(x) { | ||||
return x.x === 4; | ||||
}), {x: 4, z: 1}); | ||||
_.findIndex([{a: 1}], function(a, key, o) { | ||||
assert.equal(key, 0); | ||||
assert.deepEqual(o, [{a: 1}]); | ||||
assert.strictEqual(this, _, 'called with context'); | ||||
}, _); | ||||
}); | }); | |||
test('detect', function() { | QUnit.test('detect', function(assert) { | |||
strictEqual(_.detect, _.find, 'alias for detect'); | assert.strictEqual(_.detect, _.find, 'is an alias for find'); | |||
}); | }); | |||
test('filter', function() { | QUnit.test('filter', function(assert) { | |||
var evenArray = [1, 2, 3, 4, 5, 6]; | var evenArray = [1, 2, 3, 4, 5, 6]; | |||
var evenObject = {one: 1, two: 2, three: 3}; | var evenObject = {one: 1, two: 2, three: 3}; | |||
var isEven = function(num){ return num % 2 === 0; }; | var isEven = function(num){ return num % 2 === 0; }; | |||
deepEqual(_.filter(evenArray, isEven), [2, 4, 6]); | assert.deepEqual(_.filter(evenArray, isEven), [2, 4, 6]); | |||
deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects'); | assert.deepEqual(_.filter(evenObject, isEven), [2], 'can filter objects'); | |||
deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predicate st | assert.deepEqual(_.filter([{}, evenObject, []], 'two'), [evenObject], 'predi | |||
ring map to object properties'); | cate string map to object properties'); | |||
_.filter([1], function() { | _.filter([1], function() { | |||
equal(this, evenObject, 'given context'); | assert.equal(this, evenObject, 'given context'); | |||
}, evenObject); | }, evenObject); | |||
// Can be used like _.where. | // Can be used like _.where. | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | |||
deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}] | assert.deepEqual(_.filter(list, {a: 1}), [{a: 1, b: 2}, {a: 1, b: 3}, {a: 1, | |||
); | b: 4}]); | |||
deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]); | assert.deepEqual(_.filter(list, {b: 2}), [{a: 1, b: 2}, {a: 2, b: 2}]); | |||
deepEqual(_.filter(list, {}), list, 'Empty object accepts all items'); | assert.deepEqual(_.filter(list, {}), list, 'Empty object accepts all items') | |||
deepEqual(_(list).filter({}), list, 'OO-filter'); | ; | |||
assert.deepEqual(_(list).filter({}), list, 'OO-filter'); | ||||
}); | }); | |||
test('select', function() { | QUnit.test('select', function(assert) { | |||
strictEqual(_.filter, _.select, 'alias for filter'); | assert.strictEqual(_.select, _.filter, 'is an alias for filter'); | |||
}); | }); | |||
test('reject', function() { | QUnit.test('reject', function(assert) { | |||
var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 === 0; }); | var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 === 0; }); | |||
deepEqual(odds, [1, 3, 5], 'rejected each even number'); | assert.deepEqual(odds, [1, 3, 5], 'rejected each even number'); | |||
var context = 'obj'; | var context = 'obj'; | |||
var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ | var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){ | |||
equal(context, 'obj'); | assert.equal(context, 'obj'); | |||
return num % 2 !== 0; | return num % 2 !== 0; | |||
}, context); | }, context); | |||
deepEqual(evens, [2, 4, 6], 'rejected each odd number'); | assert.deepEqual(evens, [2, 4, 6], 'rejected each odd number'); | |||
deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds], 'pred icate string map to object properties'); | assert.deepEqual(_.reject([odds, {one: 1, two: 2, three: 3}], 'two'), [odds] , 'predicate string map to object properties'); | |||
// Can be used like _.where. | // Can be used like _.where. | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | |||
deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]); | assert.deepEqual(_.reject(list, {a: 1}), [{a: 2, b: 2}]); | |||
deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]); | assert.deepEqual(_.reject(list, {b: 2}), [{a: 1, b: 3}, {a: 1, b: 4}]); | |||
deepEqual(_.reject(list, {}), [], 'Returns empty list given empty object'); | assert.deepEqual(_.reject(list, {}), [], 'Returns empty list given empty obj | |||
deepEqual(_.reject(list, []), [], 'Returns empty list given empty array'); | ect'); | |||
assert.deepEqual(_.reject(list, []), [], 'Returns empty list given empty arr | ||||
ay'); | ||||
}); | }); | |||
test('every', function() { | QUnit.test('every', function(assert) { | |||
ok(_.every([], _.identity), 'the empty set'); | assert.ok(_.every([], _.identity), 'the empty set'); | |||
ok(_.every([true, true, true], _.identity), 'every true values'); | assert.ok(_.every([true, true, true], _.identity), 'every true values'); | |||
ok(!_.every([true, false, true], _.identity), 'one false value'); | assert.ok(!_.every([true, false, true], _.identity), 'one false value'); | |||
ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'even numbe | assert.ok(_.every([0, 10, 28], function(num){ return num % 2 === 0; }), 'eve | |||
rs'); | n numbers'); | |||
ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an odd nu | assert.ok(!_.every([0, 11, 28], function(num){ return num % 2 === 0; }), 'an | |||
mber'); | odd number'); | |||
ok(_.every([1], _.identity) === true, 'cast to boolean - true'); | assert.ok(_.every([1], _.identity) === true, 'cast to boolean - true'); | |||
ok(_.every([0], _.identity) === false, 'cast to boolean - false'); | assert.ok(_.every([0], _.identity) === false, 'cast to boolean - false'); | |||
ok(!_.every([undefined, undefined, undefined], _.identity), 'works with arra | assert.ok(!_.every([void 0, void 0, void 0], _.identity), 'works with arrays | |||
ys of undefined'); | of undefined'); | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | |||
ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); | assert.ok(!_.every(list, {a: 1, b: 2}), 'Can be called with object'); | |||
ok(_.every(list, 'a'), 'String mapped to object property'); | assert.ok(_.every(list, 'a'), 'String mapped to object property'); | |||
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; | list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; | |||
ok(_.every(list, {b: 2}), 'Can be called with object'); | assert.ok(_.every(list, {b: 2}), 'Can be called with object'); | |||
ok(!_.every(list, 'c'), 'String mapped to object property'); | assert.ok(!_.every(list, 'c'), 'String mapped to object property'); | |||
ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); | assert.ok(_.every({a: 1, b: 2, c: 3, d: 4}, _.isNumber), 'takes objects'); | |||
ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); | assert.ok(!_.every({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); | |||
ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}) | assert.ok(_.every(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, | |||
, 'context works'); | d: 4}), 'context works'); | |||
ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, c: 3, | assert.ok(!_.every(['a', 'b', 'c', 'd', 'f'], _.hasOwnProperty, {a: 1, b: 2, | |||
d: 4}), 'context works'); | c: 3, d: 4}), 'context works'); | |||
}); | }); | |||
test('all', function() { | QUnit.test('all', function(assert) { | |||
strictEqual(_.all, _.every, 'alias for all'); | assert.strictEqual(_.all, _.every, 'is an alias for every'); | |||
}); | }); | |||
test('some', function() { | QUnit.test('some', function(assert) { | |||
ok(!_.some([]), 'the empty set'); | assert.ok(!_.some([]), 'the empty set'); | |||
ok(!_.some([false, false, false]), 'all false values'); | assert.ok(!_.some([false, false, false]), 'all false values'); | |||
ok(_.some([false, false, true]), 'one true value'); | assert.ok(_.some([false, false, true]), 'one true value'); | |||
ok(_.some([null, 0, 'yes', false]), 'a string'); | assert.ok(_.some([null, 0, 'yes', false]), 'a string'); | |||
ok(!_.some([null, 0, '', false]), 'falsy values'); | assert.ok(!_.some([null, 0, '', false]), 'falsy values'); | |||
ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all odd nu | assert.ok(!_.some([1, 11, 29], function(num){ return num % 2 === 0; }), 'all | |||
mbers'); | odd numbers'); | |||
ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an even num | assert.ok(_.some([1, 10, 29], function(num){ return num % 2 === 0; }), 'an e | |||
ber'); | ven number'); | |||
ok(_.some([1], _.identity) === true, 'cast to boolean - true'); | assert.ok(_.some([1], _.identity) === true, 'cast to boolean - true'); | |||
ok(_.some([0], _.identity) === false, 'cast to boolean - false'); | assert.ok(_.some([0], _.identity) === false, 'cast to boolean - false'); | |||
ok(_.some([false, false, true])); | assert.ok(_.some([false, false, true])); | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | |||
ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); | assert.ok(!_.some(list, {a: 5, b: 2}), 'Can be called with object'); | |||
ok(_.some(list, 'a'), 'String mapped to object property'); | assert.ok(_.some(list, 'a'), 'String mapped to object property'); | |||
list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; | list = [{a: 1, b: 2}, {a: 2, b: 2, c: true}]; | |||
ok(_.some(list, {b: 2}), 'Can be called with object'); | assert.ok(_.some(list, {b: 2}), 'Can be called with object'); | |||
ok(!_.some(list, 'd'), 'String mapped to object property'); | assert.ok(!_.some(list, 'd'), 'String mapped to object property'); | |||
assert.ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes | ||||
objects'); | ||||
assert.ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); | ||||
assert.ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, | ||||
d: 4}), 'context works'); | ||||
assert.ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4 | ||||
}), 'context works'); | ||||
}); | ||||
QUnit.test('any', function(assert) { | ||||
assert.strictEqual(_.any, _.some, 'is an alias for some'); | ||||
}); | ||||
QUnit.test('includes', function(assert) { | ||||
_.each([null, void 0, 0, 1, NaN, {}, []], function(val) { | ||||
assert.strictEqual(_.includes(val, 'hasOwnProperty'), false); | ||||
}); | ||||
assert.strictEqual(_.includes([1, 2, 3], 2), true, 'two is in the array'); | ||||
assert.ok(!_.includes([1, 3, 9], 2), 'two is not in the array'); | ||||
assert.strictEqual(_.includes([5, 4, 3, 2, 1], 5, true), true, 'doesn\'t del | ||||
egate to binary search'); | ||||
assert.ok(_.includes({moe: 1, larry: 3, curly: 9}, 3) === true, '_.includes | ||||
on objects checks their values'); | ||||
assert.ok(_([1, 2, 3]).includes(2), 'OO-style includes'); | ||||
ok(_.some({a: '1', b: '2', c: '3', d: '4', e: 6}, _.isNumber), 'takes object | var numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3]; | |||
s'); | assert.strictEqual(_.includes(numbers, 1, 1), true, 'takes a fromIndex'); | |||
ok(!_.some({a: 1, b: 2, c: 3, d: 4}, _.isObject), 'takes objects'); | assert.strictEqual(_.includes(numbers, 1, -1), false, 'takes a fromIndex'); | |||
ok(_.some(['a', 'b', 'c', 'd'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), | assert.strictEqual(_.includes(numbers, 1, -2), false, 'takes a fromIndex'); | |||
'context works'); | assert.strictEqual(_.includes(numbers, 1, -3), true, 'takes a fromIndex'); | |||
ok(!_.some(['x', 'y', 'z'], _.hasOwnProperty, {a: 1, b: 2, c: 3, d: 4}), 'co | assert.strictEqual(_.includes(numbers, 1, 6), true, 'takes a fromIndex'); | |||
ntext works'); | assert.strictEqual(_.includes(numbers, 1, 7), false, 'takes a fromIndex'); | |||
assert.ok(_.every([1, 2, 3], _.partial(_.includes, numbers)), 'fromIndex is | ||||
guarded'); | ||||
}); | }); | |||
test('any', function() { | QUnit.test('include', function(assert) { | |||
strictEqual(_.any, _.some, 'alias for any'); | assert.strictEqual(_.include, _.includes, 'is an alias for includes'); | |||
}); | }); | |||
test('contains', function() { | QUnit.test('contains', function(assert) { | |||
ok(_.contains([1, 2, 3], 2), 'two is in the array'); | assert.strictEqual(_.contains, _.includes, 'is an alias for includes'); | |||
ok(!_.contains([1, 3, 9], 2), 'two is not in the array'); | ||||
ok(_.contains({moe: 1, larry: 3, curly: 9}, 3) === true, '_.contains on obje | ||||
cts checks their values'); | ||||
ok(_([1, 2, 3]).contains(2), 'OO-style contains'); | ||||
}); | }); | |||
test('include', function() { | QUnit.test('includes with NaN', function(assert) { | |||
strictEqual(_.contains, _.include, 'alias for contains'); | assert.strictEqual(_.includes([1, 2, NaN, NaN], NaN), true, 'Expected [1, 2, | |||
NaN] to contain NaN'); | ||||
assert.strictEqual(_.includes([1, 2, Infinity], NaN), false, 'Expected [1, 2 | ||||
, NaN] to contain NaN'); | ||||
}); | ||||
QUnit.test('includes with +- 0', function(assert) { | ||||
_.each([-0, +0], function(val) { | ||||
assert.strictEqual(_.includes([1, 2, val, val], val), true); | ||||
assert.strictEqual(_.includes([1, 2, val, val], -val), true); | ||||
assert.strictEqual(_.includes([-1, 1, 2], -val), false); | ||||
}); | ||||
}); | }); | |||
test('invoke', function() { | QUnit.test('invoke', function(assert) { | |||
assert.expect(5); | ||||
var list = [[5, 1, 7], [3, 2, 1]]; | var list = [[5, 1, 7], [3, 2, 1]]; | |||
var result = _.invoke(list, 'sort'); | var result = _.invoke(list, 'sort'); | |||
deepEqual(result[0], [1, 5, 7], 'first array sorted'); | assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); | |||
deepEqual(result[1], [1, 2, 3], 'second array sorted'); | assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); | |||
_.invoke([{ | ||||
method: function() { | ||||
assert.deepEqual(_.toArray(arguments), [1, 2, 3], 'called with arguments | ||||
'); | ||||
} | ||||
}], 'method', 1, 2, 3); | ||||
assert.deepEqual(_.invoke([{a: null}, {}, {a: _.constant(1)}], 'a'), [null, | ||||
void 0, 1], 'handles null & undefined'); | ||||
assert.raises(function() { | ||||
_.invoke([{a: 1}], 'a'); | ||||
}, TypeError, 'throws for non-functions'); | ||||
}); | }); | |||
test('invoke w/ function reference', function() { | QUnit.test('invoke w/ function reference', function(assert) { | |||
var list = [[5, 1, 7], [3, 2, 1]]; | var list = [[5, 1, 7], [3, 2, 1]]; | |||
var result = _.invoke(list, Array.prototype.sort); | var result = _.invoke(list, Array.prototype.sort); | |||
deepEqual(result[0], [1, 5, 7], 'first array sorted'); | assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); | |||
deepEqual(result[1], [1, 2, 3], 'second array sorted'); | assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); | |||
assert.deepEqual(_.invoke([1, 2, 3], function(a) { | ||||
return a + this; | ||||
}, 5), [6, 7, 8], 'receives params from invoke'); | ||||
}); | }); | |||
// Relevant when using ClojureScript | // Relevant when using ClojureScript | |||
test('invoke when strings have a call method', function() { | QUnit.test('invoke when strings have a call method', function(assert) { | |||
String.prototype.call = function() { | String.prototype.call = function() { | |||
return 42; | return 42; | |||
}; | }; | |||
var list = [[5, 1, 7], [3, 2, 1]]; | var list = [[5, 1, 7], [3, 2, 1]]; | |||
var s = 'foo'; | var s = 'foo'; | |||
equal(s.call(), 42, 'call function exists'); | assert.equal(s.call(), 42, 'call function exists'); | |||
var result = _.invoke(list, 'sort'); | var result = _.invoke(list, 'sort'); | |||
deepEqual(result[0], [1, 5, 7], 'first array sorted'); | assert.deepEqual(result[0], [1, 5, 7], 'first array sorted'); | |||
deepEqual(result[1], [1, 2, 3], 'second array sorted'); | assert.deepEqual(result[1], [1, 2, 3], 'second array sorted'); | |||
delete String.prototype.call; | delete String.prototype.call; | |||
equal(s.call, undefined, 'call function removed'); | assert.equal(s.call, void 0, 'call function removed'); | |||
}); | }); | |||
test('pluck', function() { | QUnit.test('pluck', function(assert) { | |||
var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; | var people = [{name: 'moe', age: 30}, {name: 'curly', age: 50}]; | |||
deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out of obj | assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'pulls names out | |||
ects'); | of objects'); | |||
assert.deepEqual(_.pluck(people, 'address'), [void 0, void 0], 'missing prop | ||||
erties are returned as undefined'); | ||||
//compat: most flexible handling of edge cases | //compat: most flexible handling of edge cases | |||
deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]); | assert.deepEqual(_.pluck([{'[object Object]': 1}], {}), [1]); | |||
}); | }); | |||
test('where', function() { | QUnit.test('where', function(assert) { | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}]; | |||
var result = _.where(list, {a: 1}); | var result = _.where(list, {a: 1}); | |||
equal(result.length, 3); | assert.equal(result.length, 3); | |||
equal(result[result.length - 1].b, 4); | assert.equal(result[result.length - 1].b, 4); | |||
result = _.where(list, {b: 2}); | result = _.where(list, {b: 2}); | |||
equal(result.length, 2); | assert.equal(result.length, 2); | |||
equal(result[0].a, 1); | assert.equal(result[0].a, 1); | |||
result = _.where(list, {}); | result = _.where(list, {}); | |||
equal(result.length, list.length); | assert.equal(result.length, list.length); | |||
function test() {} | function test() {} | |||
test.map = _.map; | test.map = _.map; | |||
deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks properties gi ven function'); | assert.deepEqual(_.where([_, {a: 1, b: 2}, _], test), [_, _], 'checks proper ties given function'); | |||
}); | }); | |||
test('findWhere', function() { | QUnit.test('findWhere', function(assert) { | |||
var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b : 4}]; | var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b : 4}]; | |||
var result = _.findWhere(list, {a: 1}); | var result = _.findWhere(list, {a: 1}); | |||
deepEqual(result, {a: 1, b: 2}); | assert.deepEqual(result, {a: 1, b: 2}); | |||
result = _.findWhere(list, {b: 4}); | result = _.findWhere(list, {b: 4}); | |||
deepEqual(result, {a: 1, b: 4}); | assert.deepEqual(result, {a: 1, b: 4}); | |||
result = _.findWhere(list, {c: 1}); | result = _.findWhere(list, {c: 1}); | |||
ok(_.isUndefined(result), 'undefined when not found'); | assert.ok(_.isUndefined(result), 'undefined when not found'); | |||
result = _.findWhere([], {c: 1}); | result = _.findWhere([], {c: 1}); | |||
ok(_.isUndefined(result), 'undefined when searching empty list'); | assert.ok(_.isUndefined(result), 'undefined when searching empty list'); | |||
function test() {} | function test() {} | |||
test.map = _.map; | test.map = _.map; | |||
equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given f unction'); | assert.equal(_.findWhere([_, {a: 1, b: 2}, _], test), _, 'checks properties given function'); | |||
function TestClass() { | function TestClass() { | |||
this.y = 5; | this.y = 5; | |||
this.x = 'foo'; | this.x = 'foo'; | |||
} | } | |||
var expect = {c: 1, x: 'foo', y: 5}; | var expect = {c: 1, x: 'foo', y: 5}; | |||
deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expect, 'use s class instance properties'); | assert.deepEqual(_.findWhere([{y: 5, b: 6}, expect], new TestClass()), expec t, 'uses class instance properties'); | |||
}); | }); | |||
test('max', function() { | QUnit.test('max', function(assert) { | |||
equal(-Infinity, _.max(null), 'can handle null/undefined'); | assert.equal(-Infinity, _.max(null), 'can handle null/undefined'); | |||
equal(-Infinity, _.max(undefined), 'can handle null/undefined'); | assert.equal(-Infinity, _.max(void 0), 'can handle null/undefined'); | |||
equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined'); | assert.equal(-Infinity, _.max(null, _.identity), 'can handle null/undefined' | |||
); | ||||
equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); | assert.equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max'); | |||
var neg = _.max([1, 2, 3], function(num){ return -num; }); | var neg = _.max([1, 2, 3], function(num){ return -num; }); | |||
equal(neg, 1, 'can perform a computation-based max'); | assert.equal(neg, 1, 'can perform a computation-based max'); | |||
assert.equal(-Infinity, _.max({}), 'Maximum value of an empty object'); | ||||
assert.equal(-Infinity, _.max([]), 'Maximum value of an empty array'); | ||||
assert.equal(_.max({a: 'a'}), -Infinity, 'Maximum value of a non-numeric col | ||||
lection'); | ||||
assert.equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big | ||||
array'); | ||||
assert.equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starti | ||||
ng with num and containing a NaN'); | ||||
assert.equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starti | ||||
ng with NaN'); | ||||
assert.equal(3, _.max([1, 2, 3, null]), 'Finds correct max in array starting | ||||
with num and containing a `null`'); | ||||
assert.equal(3, _.max([null, 1, 2, 3]), 'Finds correct max in array starting | ||||
with a `null`'); | ||||
assert.equal(3, _.max([1, 2, 3, '']), 'Finds correct max in array starting w | ||||
ith num and containing an empty string'); | ||||
assert.equal(3, _.max(['', 1, 2, 3]), 'Finds correct max in array starting w | ||||
ith an empty string'); | ||||
equal(-Infinity, _.max({}), 'Maximum value of an empty object'); | assert.equal(3, _.max([1, 2, 3, false]), 'Finds correct max in array startin | |||
equal(-Infinity, _.max([]), 'Maximum value of an empty array'); | g with num and containing a false'); | |||
equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collecti | assert.equal(3, _.max([false, 1, 2, 3]), 'Finds correct max in array startin | |||
on'); | g with a false'); | |||
equal(299999, _.max(_.range(1, 300000)), 'Maximum value of a too-big array') | assert.equal(4, _.max([0, 1, 2, 3, 4]), 'Finds correct max in array containi | |||
; | ng a zero'); | |||
assert.equal(0, _.max([-3, -2, -1, 0]), 'Finds correct max in array containi | ||||
ng negative numbers'); | ||||
equal(3, _.max([1, 2, 3, 'test']), 'Finds correct max in array starting with | assert.deepEqual([3, 6], _.map([[1, 2, 3], [4, 5, 6]], _.max), 'Finds correc | |||
num and containing a NaN'); | t max in array when mapping through multiple arrays'); | |||
equal(3, _.max(['test', 1, 2, 3]), 'Finds correct max in array starting with | ||||
NaN'); | ||||
var a = {x: -Infinity}; | var a = {x: -Infinity}; | |||
var b = {x: -Infinity}; | var b = {x: -Infinity}; | |||
var iterator = function(o){ return o.x; }; | var iterator = function(o){ return o.x; }; | |||
equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infini ty'); | assert.equal(_.max([a, b], iterator), a, 'Respects iterator return value of -Infinity'); | |||
deepEqual(_.max([{'a': 1}, {'a': 0, 'b': 3}, {'a': 4}, {'a': 2}], 'a'), {'a' : 4}, 'String keys use property iterator'); | assert.deepEqual(_.max([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 4}, 'String keys use property iterator'); | |||
deepEqual(_.max([0, 2], function(a){ return a * this.x; }, {x: 1}), 2, 'Iter | assert.deepEqual(_.max([0, 2], function(c){ return c * this.x; }, {x: 1}), 2 | |||
ator context'); | , 'Iterator context'); | |||
deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy iterator | assert.deepEqual(_.max([[1], [2, 3], [-1, 4], [5]], 0), [5], 'Lookup falsy i | |||
'); | terator'); | |||
deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Lookup falsy | assert.deepEqual(_.max([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: 2}, 'Looku | |||
iterator'); | p falsy iterator'); | |||
}); | }); | |||
test('min', function() { | QUnit.test('min', function(assert) { | |||
equal(Infinity, _.min(null), 'can handle null/undefined'); | assert.equal(Infinity, _.min(null), 'can handle null/undefined'); | |||
equal(Infinity, _.min(undefined), 'can handle null/undefined'); | assert.equal(Infinity, _.min(void 0), 'can handle null/undefined'); | |||
equal(Infinity, _.min(null, _.identity), 'can handle null/undefined'); | assert.equal(Infinity, _.min(null, _.identity), 'can handle null/undefined') | |||
; | ||||
equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); | assert.equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min'); | |||
var neg = _.min([1, 2, 3], function(num){ return -num; }); | var neg = _.min([1, 2, 3], function(num){ return -num; }); | |||
equal(neg, 3, 'can perform a computation-based min'); | assert.equal(neg, 3, 'can perform a computation-based min'); | |||
equal(Infinity, _.min({}), 'Minimum value of an empty object'); | assert.equal(Infinity, _.min({}), 'Minimum value of an empty object'); | |||
equal(Infinity, _.min([]), 'Minimum value of an empty array'); | assert.equal(Infinity, _.min([]), 'Minimum value of an empty array'); | |||
equal(_.min({'a': 'a'}), Infinity, 'Minimum value of a non-numeric collectio | assert.equal(_.min({a: 'a'}), Infinity, 'Minimum value of a non-numeric coll | |||
n'); | ection'); | |||
assert.deepEqual([1, 4], _.map([[1, 2, 3], [4, 5, 6]], _.min), 'Finds correc | ||||
t min in array when mapping through multiple arrays'); | ||||
var now = new Date(9999999999); | var now = new Date(9999999999); | |||
var then = new Date(0); | var then = new Date(0); | |||
equal(_.min([now, then]), then); | assert.equal(_.min([now, then]), then); | |||
assert.equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array | ||||
'); | ||||
assert.equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starti | ||||
ng with num and containing a NaN'); | ||||
assert.equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starti | ||||
ng with NaN'); | ||||
equal(1, _.min(_.range(1, 300000)), 'Minimum value of a too-big array'); | assert.equal(1, _.min([1, 2, 3, null]), 'Finds correct min in array starting | |||
with num and containing a `null`'); | ||||
assert.equal(1, _.min([null, 1, 2, 3]), 'Finds correct min in array starting | ||||
with a `null`'); | ||||
equal(1, _.min([1, 2, 3, 'test']), 'Finds correct min in array starting with | assert.equal(0, _.min([0, 1, 2, 3, 4]), 'Finds correct min in array containi | |||
num and containing a NaN'); | ng a zero'); | |||
equal(1, _.min(['test', 1, 2, 3]), 'Finds correct min in array starting with | assert.equal(-3, _.min([-3, -2, -1, 0]), 'Finds correct min in array contain | |||
NaN'); | ing negative numbers'); | |||
var a = {x: Infinity}; | var a = {x: Infinity}; | |||
var b = {x: Infinity}; | var b = {x: Infinity}; | |||
var iterator = function(o){ return o.x; }; | var iterator = function(o){ return o.x; }; | |||
equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinit y'); | assert.equal(_.min([a, b], iterator), a, 'Respects iterator return value of Infinity'); | |||
deepEqual(_.min([{'a': 1}, {'a': 0, 'b': 3}, {'a': 4}, {'a': 2}], 'a'), {'a' : 0, 'b': 3}, 'String keys use property iterator'); | assert.deepEqual(_.min([{a: 1}, {a: 0, b: 3}, {a: 4}, {a: 2}], 'a'), {a: 0, b: 3}, 'String keys use property iterator'); | |||
deepEqual(_.min([0, 2], function(a){ return a * this.x; }, {x: -1}), 2, 'Ite | assert.deepEqual(_.min([0, 2], function(c){ return c * this.x; }, {x: -1}), | |||
rator context'); | 2, 'Iterator context'); | |||
deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup falsy iter | assert.deepEqual(_.min([[1], [2, 3], [-1, 4], [5]], 0), [-1, 4], 'Lookup fal | |||
ator'); | sy iterator'); | |||
deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Lookup fals | assert.deepEqual(_.min([{0: 1}, {0: 2}, {0: -1}, {a: 1}], 0), {0: -1}, 'Look | |||
y iterator'); | up falsy iterator'); | |||
}); | }); | |||
test('sortBy', function() { | QUnit.test('sortBy', function(assert) { | |||
var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}]; | var people = [{name: 'curly', age: 50}, {name: 'moe', age: 30}]; | |||
people = _.sortBy(people, function(person){ return person.age; }); | people = _.sortBy(people, function(person){ return person.age; }); | |||
deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age' ); | assert.deepEqual(_.pluck(people, 'name'), ['moe', 'curly'], 'stooges sorted by age'); | |||
var list = [undefined, 4, 1, undefined, 3, 2]; | var list = [void 0, 4, 1, void 0, 3, 2]; | |||
deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, undefined, undefined], 's | assert.deepEqual(_.sortBy(list, _.identity), [1, 2, 3, 4, void 0, void 0], ' | |||
ortBy with undefined values'); | sortBy with undefined values'); | |||
list = ['one', 'two', 'three', 'four', 'five']; | list = ['one', 'two', 'three', 'four', 'five']; | |||
var sorted = _.sortBy(list, 'length'); | var sorted = _.sortBy(list, 'length'); | |||
deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length '); | assert.deepEqual(sorted, ['one', 'two', 'four', 'five', 'three'], 'sorted by length'); | |||
function Pair(x, y) { | function Pair(x, y) { | |||
this.x = x; | this.x = x; | |||
this.y = y; | this.y = y; | |||
} | } | |||
var collection = [ | var stableArray = [ | |||
new Pair(1, 1), new Pair(1, 2), | new Pair(1, 1), new Pair(1, 2), | |||
new Pair(1, 3), new Pair(1, 4), | new Pair(1, 3), new Pair(1, 4), | |||
new Pair(1, 5), new Pair(1, 6), | new Pair(1, 5), new Pair(1, 6), | |||
new Pair(2, 1), new Pair(2, 2), | new Pair(2, 1), new Pair(2, 2), | |||
new Pair(2, 3), new Pair(2, 4), | new Pair(2, 3), new Pair(2, 4), | |||
new Pair(2, 5), new Pair(2, 6), | new Pair(2, 5), new Pair(2, 6), | |||
new Pair(undefined, 1), new Pair(undefined, 2), | new Pair(void 0, 1), new Pair(void 0, 2), | |||
new Pair(undefined, 3), new Pair(undefined, 4), | new Pair(void 0, 3), new Pair(void 0, 4), | |||
new Pair(undefined, 5), new Pair(undefined, 6) | new Pair(void 0, 5), new Pair(void 0, 6) | |||
]; | ]; | |||
var actual = _.sortBy(collection, function(pair) { | var stableObject = _.object('abcdefghijklmnopqr'.split(''), stableArray); | |||
var actual = _.sortBy(stableArray, function(pair) { | ||||
return pair.x; | return pair.x; | |||
}); | }); | |||
deepEqual(actual, collection, 'sortBy should be stable'); | assert.deepEqual(actual, stableArray, 'sortBy should be stable for arrays'); | |||
assert.deepEqual(_.sortBy(stableArray, 'x'), stableArray, 'sortBy accepts pr | ||||
operty string'); | ||||
deepEqual(_.sortBy(collection, 'x'), collection, 'sortBy accepts property st | actual = _.sortBy(stableObject, function(pair) { | |||
ring'); | return pair.x; | |||
}); | ||||
assert.deepEqual(actual, stableArray, 'sortBy should be stable for objects') | ||||
; | ||||
list = ['q', 'w', 'e', 'r', 't', 'y']; | list = ['q', 'w', 'e', 'r', 't', 'y']; | |||
deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.identity i f iterator is not specified'); | assert.deepEqual(_.sortBy(list), ['e', 'q', 'r', 't', 'w', 'y'], 'uses _.ide ntity if iterator is not specified'); | |||
}); | }); | |||
test('groupBy', function() { | QUnit.test('groupBy', function(assert) { | |||
var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }) ; | var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; }) ; | |||
ok('0' in parity && '1' in parity, 'created a group for each value'); | assert.ok('0' in parity && '1' in parity, 'created a group for each value'); | |||
deepEqual(parity[0], [2, 4, 6], 'put each even number in the right group'); | assert.deepEqual(parity[0], [2, 4, 6], 'put each even number in the right gr | |||
oup'); | ||||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | |||
var grouped = _.groupBy(list, 'length'); | var grouped = _.groupBy(list, 'length'); | |||
deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']); | assert.deepEqual(grouped['3'], ['one', 'two', 'six', 'ten']); | |||
deepEqual(grouped['4'], ['four', 'five', 'nine']); | assert.deepEqual(grouped['4'], ['four', 'five', 'nine']); | |||
deepEqual(grouped['5'], ['three', 'seven', 'eight']); | assert.deepEqual(grouped['5'], ['three', 'seven', 'eight']); | |||
var context = {}; | var context = {}; | |||
_.groupBy([{}], function(){ ok(this === context); }, context); | _.groupBy([{}], function(){ assert.ok(this === context); }, context); | |||
grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { | grouped = _.groupBy([4.2, 6.1, 6.4], function(num) { | |||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; | return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; | |||
}); | }); | |||
equal(grouped.constructor.length, 1); | assert.equal(grouped.constructor.length, 1); | |||
equal(grouped.hasOwnProperty.length, 2); | assert.equal(grouped.hasOwnProperty.length, 2); | |||
var array = [{}]; | var array = [{}]; | |||
_.groupBy(array, function(value, index, obj){ ok(obj === array); }); | _.groupBy(array, function(value, index, obj){ assert.ok(obj === array); }); | |||
array = [1, 2, 1, 2, 3]; | array = [1, 2, 1, 2, 3]; | |||
grouped = _.groupBy(array); | grouped = _.groupBy(array); | |||
equal(grouped['1'].length, 2); | assert.equal(grouped['1'].length, 2); | |||
equal(grouped['3'].length, 1); | assert.equal(grouped['3'].length, 1); | |||
var matrix = [ | var matrix = [ | |||
[1, 2], | [1, 2], | |||
[1, 3], | [1, 3], | |||
[2, 3] | [2, 3] | |||
]; | ]; | |||
deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]}); | assert.deepEqual(_.groupBy(matrix, 0), {1: [[1, 2], [1, 3]], 2: [[2, 3]]}); | |||
deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]}); | assert.deepEqual(_.groupBy(matrix, 1), {2: [[1, 2]], 3: [[1, 3], [2, 3]]}); | |||
}); | }); | |||
test('indexBy', function() { | QUnit.test('indexBy', function(assert) { | |||
var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); | var parity = _.indexBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); | |||
equal(parity['true'], 4); | assert.equal(parity['true'], 4); | |||
equal(parity['false'], 5); | assert.equal(parity['false'], 5); | |||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | |||
var grouped = _.indexBy(list, 'length'); | var grouped = _.indexBy(list, 'length'); | |||
equal(grouped['3'], 'ten'); | assert.equal(grouped['3'], 'ten'); | |||
equal(grouped['4'], 'nine'); | assert.equal(grouped['4'], 'nine'); | |||
equal(grouped['5'], 'eight'); | assert.equal(grouped['5'], 'eight'); | |||
var array = [1, 2, 1, 2, 3]; | var array = [1, 2, 1, 2, 3]; | |||
grouped = _.indexBy(array); | grouped = _.indexBy(array); | |||
equal(grouped['1'], 1); | assert.equal(grouped['1'], 1); | |||
equal(grouped['2'], 2); | assert.equal(grouped['2'], 2); | |||
equal(grouped['3'], 3); | assert.equal(grouped['3'], 3); | |||
}); | }); | |||
test('countBy', function() { | QUnit.test('countBy', function(assert) { | |||
var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); | var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 === 0; }); | |||
equal(parity['true'], 2); | assert.equal(parity['true'], 2); | |||
equal(parity['false'], 3); | assert.equal(parity['false'], 3); | |||
var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | var list = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten']; | |||
var grouped = _.countBy(list, 'length'); | var grouped = _.countBy(list, 'length'); | |||
equal(grouped['3'], 4); | assert.equal(grouped['3'], 4); | |||
equal(grouped['4'], 3); | assert.equal(grouped['4'], 3); | |||
equal(grouped['5'], 3); | assert.equal(grouped['5'], 3); | |||
var context = {}; | var context = {}; | |||
_.countBy([{}], function(){ ok(this === context); }, context); | _.countBy([{}], function(){ assert.ok(this === context); }, context); | |||
grouped = _.countBy([4.2, 6.1, 6.4], function(num) { | grouped = _.countBy([4.2, 6.1, 6.4], function(num) { | |||
return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; | return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor'; | |||
}); | }); | |||
equal(grouped.constructor, 1); | assert.equal(grouped.constructor, 1); | |||
equal(grouped.hasOwnProperty, 2); | assert.equal(grouped.hasOwnProperty, 2); | |||
var array = [{}]; | var array = [{}]; | |||
_.countBy(array, function(value, index, obj){ ok(obj === array); }); | _.countBy(array, function(value, index, obj){ assert.ok(obj === array); }); | |||
array = [1, 2, 1, 2, 3]; | array = [1, 2, 1, 2, 3]; | |||
grouped = _.countBy(array); | grouped = _.countBy(array); | |||
equal(grouped['1'], 2); | assert.equal(grouped['1'], 2); | |||
equal(grouped['3'], 1); | assert.equal(grouped['3'], 1); | |||
}); | ||||
test('sortedIndex', function() { | ||||
var numbers = [10, 20, 30, 40, 50], num = 35; | ||||
var indexForNum = _.sortedIndex(numbers, num); | ||||
equal(indexForNum, 3, '35 should be inserted at index 3'); | ||||
var indexFor30 = _.sortedIndex(numbers, 30); | ||||
equal(indexFor30, 2, '30 should be inserted at index 2'); | ||||
var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}]; | ||||
var iterator = function(obj){ return obj.x; }; | ||||
strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2); | ||||
strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3); | ||||
var context = {1: 2, 2: 3, 3: 4}; | ||||
iterator = function(obj){ return this[obj]; }; | ||||
strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1); | ||||
}); | }); | |||
test('shuffle', function() { | QUnit.test('shuffle', function(assert) { | |||
var numbers = _.range(10); | assert.deepEqual(_.shuffle([1]), [1], 'behaves correctly on size 1 arrays'); | |||
var numbers = _.range(20); | ||||
var shuffled = _.shuffle(numbers); | var shuffled = _.shuffle(numbers); | |||
notStrictEqual(numbers, shuffled, 'original object is unmodified'); | assert.notDeepEqual(numbers, shuffled, 'does change the order'); // Chance o | |||
ok(_.every(_.range(10), function() { //appears consistent? | f false negative: 1 in ~2.4*10^18 | |||
return _.every(numbers, _.partial(_.contains, numbers)); | assert.notStrictEqual(numbers, shuffled, 'original object is unmodified'); | |||
}), 'contains the same members before and after shuffle'); | assert.deepEqual(numbers, _.sortBy(shuffled), 'contains the same members bef | |||
ore and after shuffle'); | ||||
shuffled = _.shuffle({a: 1, b: 2, c: 3, d: 4}); | shuffled = _.shuffle({a: 1, b: 2, c: 3, d: 4}); | |||
equal(shuffled.length, 4); | assert.equal(shuffled.length, 4); | |||
deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects'); | assert.deepEqual(shuffled.sort(), [1, 2, 3, 4], 'works on objects'); | |||
}); | }); | |||
test('sample', function() { | QUnit.test('sample', function(assert) { | |||
assert.strictEqual(_.sample([1]), 1, 'behaves correctly when no second param | ||||
eter is given'); | ||||
assert.deepEqual(_.sample([1, 2, 3], -2), [], 'behaves correctly on negative | ||||
n'); | ||||
var numbers = _.range(10); | var numbers = _.range(10); | |||
var allSampled = _.sample(numbers, 10).sort(); | var allSampled = _.sample(numbers, 10).sort(); | |||
deepEqual(allSampled, numbers, 'contains the same members before and after s ample'); | assert.deepEqual(allSampled, numbers, 'contains the same members before and after sample'); | |||
allSampled = _.sample(numbers, 20).sort(); | allSampled = _.sample(numbers, 20).sort(); | |||
deepEqual(allSampled, numbers, 'also works when sampling more objects than a | assert.deepEqual(allSampled, numbers, 'also works when sampling more objects | |||
re present'); | than are present'); | |||
ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element return | assert.ok(_.contains(numbers, _.sample(numbers)), 'sampling a single element | |||
s something from the array'); | returns something from the array'); | |||
strictEqual(_.sample([]), undefined, 'sampling empty array with no number re | assert.strictEqual(_.sample([]), void 0, 'sampling empty array with no numbe | |||
turns undefined'); | r returns undefined'); | |||
notStrictEqual(_.sample([], 5), [], 'sampling empty array with a number retu | assert.notStrictEqual(_.sample([], 5), [], 'sampling empty array with a numb | |||
rns an empty array'); | er returns an empty array'); | |||
notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 picks r | assert.notStrictEqual(_.sample([1, 2, 3], 0), [], 'sampling an array with 0 | |||
eturns an empty array'); | picks returns an empty array'); | |||
deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of picks ret | assert.deepEqual(_.sample([1, 2], -1), [], 'sampling a negative number of pi | |||
urns an empty array'); | cks returns an empty array'); | |||
ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one value fr | assert.ok(_.contains([1, 2, 3], _.sample({a: 1, b: 2, c: 3})), 'sample one v | |||
om an object'); | alue from an object'); | |||
var partialSample = _.sample(_.range(1000), 10); | ||||
var partialSampleSorted = partialSample.sort(); | ||||
assert.notDeepEqual(partialSampleSorted, _.range(10), 'samples from the whol | ||||
e array, not just the beginning'); | ||||
}); | }); | |||
test('toArray', function() { | QUnit.test('toArray', function(assert) { | |||
ok(!_.isArray(arguments), 'arguments object is not an array'); | assert.ok(!_.isArray(arguments), 'arguments object is not an array'); | |||
ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array') | assert.ok(_.isArray(_.toArray(arguments)), 'arguments object converted into | |||
; | array'); | |||
var a = [1, 2, 3]; | var a = [1, 2, 3]; | |||
ok(_.toArray(a) !== a, 'array is cloned'); | assert.ok(_.toArray(a) !== a, 'array is cloned'); | |||
deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elements'); | assert.deepEqual(_.toArray(a), [1, 2, 3], 'cloned array contains same elemen | |||
ts'); | ||||
var numbers = _.toArray({one : 1, two : 2, three : 3}); | var numbers = _.toArray({one: 1, two: 2, three: 3}); | |||
deepEqual(numbers, [1, 2, 3], 'object flattened into array'); | assert.deepEqual(numbers, [1, 2, 3], 'object flattened into array'); | |||
// test in IE < 9 | var hearts = '\uD83D\uDC95'; | |||
try { | var pair = hearts.split(''); | |||
var actual = _.toArray(document.childNodes); | var expected = [pair[0], hearts, '&', hearts, pair[1]]; | |||
} catch(ex) { } | assert.deepEqual(_.toArray(expected.join('')), expected, 'maintains astral c | |||
haracters'); | ||||
ok(_.isArray(actual), 'should not throw converting a node list'); | assert.deepEqual(_.toArray(''), [], 'empty string into empty array'); | |||
if (typeof document != 'undefined') { | ||||
// test in IE < 9 | ||||
var actual; | ||||
try { | ||||
actual = _.toArray(document.childNodes); | ||||
} catch (e) { /* ignored */ } | ||||
assert.deepEqual(actual, _.map(document.childNodes, _.identity), 'works on | ||||
NodeList'); | ||||
} | ||||
}); | }); | |||
test('size', function() { | QUnit.test('size', function(assert) { | |||
equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an | assert.equal(_.size({one: 1, two: 2, three: 3}), 3, 'can compute the size of | |||
object'); | an object'); | |||
equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); | assert.equal(_.size([1, 2, 3]), 3, 'can compute the size of an array'); | |||
equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size of Arr | assert.equal(_.size({length: 3, 0: 0, 1: 0, 2: 0}), 3, 'can compute the size | |||
ay-likes'); | of Array-likes'); | |||
var func = function() { | var func = function() { | |||
return _.size(arguments); | return _.size(arguments); | |||
}; | }; | |||
equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object'); | assert.equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object '); | |||
equal(_.size('hello'), 5, 'can compute the size of a string literal'); | assert.equal(_.size('hello'), 5, 'can compute the size of a string literal') | |||
equal(_.size(new String('hello')), 5, 'can compute the size of string object | ; | |||
'); | assert.equal(_.size(new String('hello')), 5, 'can compute the size of string | |||
object'); | ||||
equal(_.size(null), 0, 'handles nulls'); | assert.equal(_.size(null), 0, 'handles nulls'); | |||
assert.equal(_.size(0), 0, 'handles numbers'); | ||||
}); | }); | |||
test('partition', function() { | QUnit.test('partition', function(assert) { | |||
var list = [0, 1, 2, 3, 4, 5]; | var list = [0, 1, 2, 3, 4, 5]; | |||
deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2, 3], [ | assert.deepEqual(_.partition(list, function(x) { return x < 4; }), [[0, 1, 2 | |||
4, 5]], 'handles bool return values'); | , 3], [4, 5]], 'handles bool return values'); | |||
deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5], [0, | assert.deepEqual(_.partition(list, function(x) { return x & 1; }), [[1, 3, 5 | |||
2, 4]], 'handles 0 and 1 return values'); | ], [0, 2, 4]], 'handles 0 and 1 return values'); | |||
deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2, 4, 5] | assert.deepEqual(_.partition(list, function(x) { return x - 3; }), [[0, 1, 2 | |||
, [3]], 'handles other numeric return values'); | , 4, 5], [3]], 'handles other numeric return values'); | |||
deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; }), [[ | assert.deepEqual(_.partition(list, function(x) { return x > 1 ? null : true; | |||
0, 1], [2, 3, 4, 5]], 'handles null return values'); | }), [[0, 1], [2, 3, 4, 5]], 'handles null return values'); | |||
deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), [[0, 1 | assert.deepEqual(_.partition(list, function(x) { if (x < 2) return true; }), | |||
], [2, 3, 4, 5]], 'handles undefined return values'); | [[0, 1], [2, 3, 4, 5]], 'handles undefined return values'); | |||
deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; }), [[ | assert.deepEqual(_.partition({a: 1, b: 2, c: 3}, function(x) { return x > 1; | |||
2, 3], [1]], 'handles objects'); | }), [[2, 3], [1]], 'handles objects'); | |||
deepEqual(_.partition(list, function(x, index) { return index % 2; }), [[1, | assert.deepEqual(_.partition(list, function(x, index) { return index % 2; }) | |||
3, 5], [0, 2, 4]], 'can reference the array index'); | , [[1, 3, 5], [0, 2, 4]], 'can reference the array index'); | |||
deepEqual(_.partition(list, function(x, index, arr) { return x === arr.lengt | assert.deepEqual(_.partition(list, function(x, index, arr) { return x === ar | |||
h - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection'); | r.length - 1; }), [[5], [0, 1, 2, 3, 4]], 'can reference the collection'); | |||
// Default iterator | // Default iterator | |||
deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']], 'Defa | assert.deepEqual(_.partition([1, false, true, '']), [[1, true], [false, '']] | |||
ult iterator'); | , 'Default iterator'); | |||
deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1}], [{x | assert.deepEqual(_.partition([{x: 1}, {x: 0}, {x: 1}], 'x'), [[{x: 1}, {x: 1 | |||
: 0}]], 'Takes a string'); | }], [{x: 0}]], 'Takes a string'); | |||
// Context | // Context | |||
var predicate = function(x){ return x === this.x; }; | var predicate = function(x){ return x === this.x; }; | |||
deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], 'partiti on takes a context argument'); | assert.deepEqual(_.partition([1, 2, 3], predicate, {x: 2}), [[2], [1, 3]], ' partition takes a context argument'); | |||
deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object'); | assert.deepEqual(_.partition([{a: 1}, {b: 2}, {a: 1, b: 2}], {a: 1}), [[{a: 1}, {a: 1, b: 2}], [{b: 2}]], 'predicate can be object'); | |||
var object = {a: 1}; | var object = {a: 1}; | |||
_.partition(object, function(val, key, obj) { | _.partition(object, function(val, key, obj) { | |||
equal(val, 1); | assert.equal(val, 1); | |||
equal(key, 'a'); | assert.equal(key, 'a'); | |||
equal(obj, object); | assert.equal(obj, object); | |||
equal(this, predicate); | assert.equal(this, predicate); | |||
}, predicate); | }, predicate); | |||
}); | }); | |||
if (typeof document != 'undefined') { | ||||
QUnit.test('Can use various collection methods on NodeLists', function(asser | ||||
t) { | ||||
var parent = document.createElement('div'); | ||||
parent.innerHTML = '<span id=id1></span>textnode<span id=id2></span>'; | ||||
var elementChildren = _.filter(parent.childNodes, _.isElement); | ||||
assert.equal(elementChildren.length, 2); | ||||
assert.deepEqual(_.map(elementChildren, 'id'), ['id1', 'id2']); | ||||
assert.deepEqual(_.map(parent.childNodes, 'nodeType'), [1, 3, 1]); | ||||
assert.ok(!_.every(parent.childNodes, _.isElement)); | ||||
assert.ok(_.some(parent.childNodes, _.isElement)); | ||||
function compareNode(node) { | ||||
return _.isElement(node) ? node.id.charAt(2) : void 0; | ||||
} | ||||
assert.equal(_.max(parent.childNodes, compareNode), _.last(parent.childNod | ||||
es)); | ||||
assert.equal(_.min(parent.childNodes, compareNode), _.first(parent.childNo | ||||
des)); | ||||
}); | ||||
} | ||||
}()); | }()); | |||
End of changes. 167 change blocks. | ||||
421 lines changed or deleted | 665 lines changed or added |