"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "vendor/underscore/test/collections.js" between
lodash-3.0.0.tar.gz and lodash-4.0.0.tar.gz

About: lodash is a modern JavaScript utility library delivering modularity, performance, & extras.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)